@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.
Files changed (177) hide show
  1. package/README.md +1 -1
  2. package/package.json +98 -74
  3. package/src/adapters/bun/server-adapter.js +2 -2
  4. package/src/adapters/node/server-adapter.js +2 -2
  5. package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +10 -0
  6. package/src/adapters/shared/hmr-entrypoint-registrar.js +34 -10
  7. package/src/adapters/shared/runtime-server-lifecycle.js +1 -1
  8. package/src/adapters/shared/server-static-builder.d.ts +2 -1
  9. package/src/adapters/shared/server-static-builder.js +16 -14
  10. package/src/adapters/shared/shared-hmr-manager.d.ts +11 -4
  11. package/src/adapters/shared/shared-hmr-manager.js +22 -3
  12. package/src/build/README.md +92 -46
  13. package/src/build/app-build-manifest-runtime.d.ts +28 -2
  14. package/src/build/app-build-manifest-runtime.js +26 -10
  15. package/src/build/{browser-runtime-plugin.d.ts → browser/browser-runtime-plugin.d.ts} +1 -1
  16. package/src/build/{browser-runtime-plugin.js → browser/browser-runtime-plugin.js} +1 -1
  17. package/src/build/{jsx-ownership-plugins.d.ts → browser/jsx-ownership-plugins.d.ts} +2 -2
  18. package/src/build/{jsx-ownership-plugins.js → browser/jsx-ownership-plugins.js} +2 -2
  19. package/src/build/build-adapter.d.ts +18 -21
  20. package/src/build/build-adapter.js +8 -43
  21. package/src/build/{build-input-fingerprint.d.ts → cache/build-input-fingerprint.d.ts} +3 -3
  22. package/src/build/cache/cache-constants.d.ts +4 -0
  23. package/src/build/cache/cache-constants.js +6 -0
  24. package/src/build/cache/cache-keys.d.ts +22 -0
  25. package/src/build/cache/cache-keys.js +63 -0
  26. package/src/build/{dev-browser-script-cache.d.ts → cache/dev-browser-script-cache.d.ts} +2 -2
  27. package/src/build/{dev-browser-script-cache.js → cache/dev-browser-script-cache.js} +4 -4
  28. package/src/build/{pages-unified-graph-build.d.ts → cache/pages-unified-graph-build.d.ts} +1 -1
  29. package/src/build/{pages-unified-graph-build.js → cache/pages-unified-graph-build.js} +18 -26
  30. package/src/build/{production-build-cache.d.ts → cache/production-build-cache.d.ts} +1 -1
  31. package/src/build/{production-build-cache.js → cache/production-build-cache.js} +2 -2
  32. package/src/build/{server-entry-build-cache.d.ts → cache/server-entry-build-cache.d.ts} +3 -4
  33. package/src/build/{server-entry-build-cache.js → cache/server-entry-build-cache.js} +16 -12
  34. package/src/build/{build-contracts.d.ts → contracts/build-contracts.d.ts} +1 -2
  35. package/src/build/contracts/build-manifest.d.ts +90 -0
  36. package/src/build/{build-manifest.js → contracts/build-manifest.js} +2 -2
  37. package/src/build/{rolldown-adapter-helpers.d.ts → rolldown/rolldown-adapter-helpers.d.ts} +20 -3
  38. package/src/build/{rolldown-adapter-helpers.js → rolldown/rolldown-adapter-helpers.js} +26 -6
  39. package/src/build/{rolldown-build-adapter.d.ts → rolldown/rolldown-build-adapter.d.ts} +1 -1
  40. package/src/build/{rolldown-plugin-bridge.d.ts → rolldown/rolldown-plugin-bridge.d.ts} +2 -2
  41. package/src/build/{rolldown-plugin-bridge.js → rolldown/rolldown-plugin-bridge.js} +1 -1
  42. package/src/build/{rolldown-source-transform-pass.d.ts → rolldown/rolldown-source-transform-pass.d.ts} +1 -1
  43. package/src/build/{rolldown-source-transform-pass.js → rolldown/rolldown-source-transform-pass.js} +4 -1
  44. package/src/build/{runtime-build-output-normalizer.js → rolldown/runtime-build-output-normalizer.js} +2 -2
  45. package/src/build/{build-profile-options.d.ts → runtime/build-profile-options.d.ts} +2 -2
  46. package/src/build/runtime/build-request-identity.d.ts +17 -0
  47. package/src/build/runtime/build-request-identity.js +54 -0
  48. package/src/build/runtime/build-request-policy.d.ts +59 -0
  49. package/src/build/runtime/build-request-policy.js +46 -0
  50. package/src/build/{build-runtime.d.ts → runtime/build-runtime.d.ts} +8 -4
  51. package/src/build/{build-runtime.js → runtime/build-runtime.js} +11 -11
  52. package/src/build/{deduping-build-executor.d.ts → runtime/deduping-build-executor.d.ts} +2 -9
  53. package/src/build/runtime/deduping-build-executor.js +34 -0
  54. package/src/build/{parallel-build-executor.d.ts → runtime/parallel-build-executor.d.ts} +1 -1
  55. package/src/build/{serialized-build-executor.d.ts → runtime/serialized-build-executor.d.ts} +1 -1
  56. package/src/config/config-builder.d.ts +1 -1
  57. package/src/diagnostics/startup-trace.d.ts +49 -2
  58. package/src/diagnostics/startup-trace.js +140 -8
  59. package/src/eco/eco.js +2 -2
  60. package/src/eco/eco.utils.d.ts +1 -1
  61. package/src/eco/eco.utils.js +1 -1
  62. package/src/hmr/client/hmr-runtime.js +2 -2
  63. package/src/hmr/hmr-file-change-prep.d.ts +10 -0
  64. package/src/hmr/hmr-file-change-prep.js +17 -0
  65. package/src/plugins/alias-resolver-plugin.d.ts +1 -1
  66. package/src/plugins/eco-component-meta-plugin.d.ts +1 -1
  67. package/src/plugins/foreign-jsx-override-plugin.d.ts +1 -1
  68. package/src/plugins/integration-plugin.d.ts +16 -5
  69. package/src/plugins/integration-plugin.js +11 -1
  70. package/src/plugins/processor.d.ts +36 -8
  71. package/src/plugins/source-transform.d.ts +1 -1
  72. package/src/route-renderer/GRAPH.md +22 -28
  73. package/src/route-renderer/README.md +12 -7
  74. package/src/route-renderer/orchestration/{document-shell-render.service.d.ts → document-shell/document-shell-render.service.d.ts} +19 -2
  75. package/src/route-renderer/orchestration/{document-shell-render.service.js → document-shell/document-shell-render.service.js} +28 -0
  76. package/src/route-renderer/orchestration/{layout-shell-props.service.d.ts → document-shell/layout-shell-props.service.d.ts} +1 -1
  77. package/src/route-renderer/orchestration/{component-render-context.d.ts → foreign-child/component-render-context.d.ts} +5 -5
  78. package/src/route-renderer/orchestration/{component-render-context.js → foreign-child/component-render-context.js} +1 -1
  79. package/src/route-renderer/orchestration/{render-output.utils.d.ts → foreign-child/foreign-child-output.utils.d.ts} +15 -7
  80. package/src/route-renderer/orchestration/{render-output.utils.js → foreign-child/foreign-child-output.utils.js} +31 -26
  81. package/src/route-renderer/orchestration/{foreign-subtree-execution.service.d.ts → foreign-child/foreign-subtree-execution.service.d.ts} +5 -5
  82. package/src/route-renderer/orchestration/{foreign-subtree-execution.service.js → foreign-child/foreign-subtree-execution.service.js} +7 -3
  83. package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.d.ts +19 -0
  84. package/src/route-renderer/orchestration/foreign-child/owning-renderer-resolution.js +35 -0
  85. package/src/route-renderer/orchestration/integration-renderer.d.ts +14 -97
  86. package/src/route-renderer/orchestration/integration-renderer.js +90 -247
  87. package/src/route-renderer/orchestration/integration-renderer.test-fixtures.d.ts +75 -0
  88. package/src/route-renderer/orchestration/integration-renderer.test-fixtures.js +177 -0
  89. package/src/route-renderer/orchestration/{component-graph-collectors.d.ts → ownership-graph/component-graph-collectors.d.ts} +4 -4
  90. package/src/route-renderer/orchestration/{component-graph-collectors.js → ownership-graph/component-graph-collectors.js} +1 -1
  91. package/src/route-renderer/orchestration/{component-graph.d.ts → ownership-graph/component-graph.d.ts} +1 -3
  92. package/src/route-renderer/orchestration/{component-graph.js → ownership-graph/component-graph.js} +0 -2
  93. package/src/route-renderer/orchestration/{ownership-validation.service.d.ts → ownership-graph/ownership-validation.service.d.ts} +2 -2
  94. package/src/route-renderer/orchestration/{ownership-validation.service.js → ownership-graph/ownership-validation.service.js} +3 -4
  95. package/src/route-renderer/orchestration/{global-injector-assets.service.d.ts → page-browser-graph/global-injector-assets.service.d.ts} +3 -3
  96. package/src/route-renderer/orchestration/{global-injector-assets.service.js → page-browser-graph/global-injector-assets.service.js} +2 -2
  97. package/src/route-renderer/orchestration/{page-browser-graph-contribution.loader.d.ts → page-browser-graph/page-browser-graph-contribution.loader.d.ts} +1 -1
  98. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.d.ts +12 -0
  99. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-merge.utils.js +29 -0
  100. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.d.ts +106 -0
  101. package/src/route-renderer/orchestration/page-browser-graph/page-browser-graph-session.js +436 -0
  102. package/src/route-renderer/orchestration/{page-browser-graph.service.d.ts → page-browser-graph/page-browser-graph.service.d.ts} +12 -6
  103. package/src/route-renderer/orchestration/{page-browser-graph.service.js → page-browser-graph/page-browser-graph.service.js} +91 -42
  104. package/src/route-renderer/orchestration/{processed-asset-dedupe.d.ts → page-browser-graph/processed-asset-dedupe.d.ts} +1 -1
  105. package/src/route-renderer/orchestration/{integration-route-render-adapter.d.ts → route-pipeline/integration-route-render-adapter.d.ts} +3 -10
  106. package/src/route-renderer/orchestration/{integration-route-render-adapter.js → route-pipeline/integration-route-render-adapter.js} +1 -3
  107. package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.d.ts +6 -0
  108. package/src/route-renderer/orchestration/route-pipeline/marker-artifact.utils.js +27 -0
  109. package/src/route-renderer/orchestration/{route-html-finalization.service.d.ts → route-pipeline/route-html-finalization.service.d.ts} +2 -3
  110. package/src/route-renderer/orchestration/route-pipeline/route-html-finalization.service.js +21 -0
  111. package/src/route-renderer/orchestration/{route-prepared-options.builder.d.ts → route-pipeline/route-prepared-options.builder.d.ts} +3 -4
  112. package/src/route-renderer/orchestration/{route-prepared-options.builder.js → route-pipeline/route-prepared-options.builder.js} +3 -12
  113. package/src/route-renderer/orchestration/{route-prepared-options.utils.js → route-pipeline/route-prepared-options.utils.js} +1 -1
  114. package/src/route-renderer/orchestration/{route-render-orchestrator.d.ts → route-pipeline/route-render-orchestrator.d.ts} +8 -17
  115. package/src/route-renderer/orchestration/{route-render-orchestrator.js → route-pipeline/route-render-orchestrator.js} +12 -19
  116. package/src/route-renderer/orchestration/string-markup-renderer.js +1 -1
  117. package/src/services/assets/asset-processing-service/asset-processing.service.js +1 -1
  118. package/src/services/assets/asset-processing-service/assets.types.d.ts +1 -1
  119. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -1
  120. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +0 -2
  121. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +2 -15
  122. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +1 -1
  123. package/src/services/assets/browser-bundle.service.d.ts +27 -31
  124. package/src/services/assets/browser-bundle.service.js +12 -23
  125. package/src/services/html/html-transformer.service.js +1 -1
  126. package/src/services/invalidation/development-invalidation.service.d.ts +5 -0
  127. package/src/services/invalidation/development-invalidation.service.js +8 -9
  128. package/src/services/module-loading/app-server-module-transpiler.service.d.ts +8 -0
  129. package/src/services/module-loading/app-server-module-transpiler.service.js +1 -7
  130. package/src/services/module-loading/page-module-import.service.d.ts +1 -1
  131. package/src/services/module-loading/page-module-import.service.js +40 -28
  132. package/src/services/module-loading/route-module-build-cache.store.js +1 -1
  133. package/src/services/module-loading/route-module-build-manifest.d.ts +2 -9
  134. package/src/services/module-loading/route-module-build-manifest.js +12 -43
  135. package/src/services/module-loading/server-module-transpiler.service.d.ts +1 -1
  136. package/src/static-site-generator/README.md +1 -1
  137. package/src/static-site-generator/production-page-browser-graph-prebuild.d.ts +28 -0
  138. package/src/static-site-generator/production-page-browser-graph-prebuild.js +22 -0
  139. package/src/static-site-generator/static-build-invalidation.d.ts +2 -2
  140. package/src/static-site-generator/static-build-invalidation.js +3 -3
  141. package/src/static-site-generator/static-site-generator.js +23 -1
  142. package/src/types/internal-types.d.ts +10 -4
  143. package/src/types/public-types.d.ts +59 -10
  144. package/src/watchers/project-watcher.d.ts +3 -3
  145. package/src/watchers/project-watcher.js +15 -5
  146. package/src/build/build-manifest.d.ts +0 -33
  147. package/src/build/deduping-build-executor.js +0 -56
  148. package/src/build/runtime-build-executor.d.ts +0 -14
  149. package/src/build/runtime-build-executor.js +0 -16
  150. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +0 -1
  151. package/src/route-renderer/orchestration/declared-ownership-graph.js +0 -8
  152. package/src/route-renderer/orchestration/route-html-finalization.service.js +0 -26
  153. package/src/route-renderer/orchestration/template-serialization.d.ts +0 -38
  154. package/src/route-renderer/orchestration/template-serialization.js +0 -45
  155. /package/src/build/{browser-runtime-manifest.d.ts → browser/browser-runtime-manifest.d.ts} +0 -0
  156. /package/src/build/{browser-runtime-manifest.js → browser/browser-runtime-manifest.js} +0 -0
  157. /package/src/build/{browser-runtime-plugin-helpers.d.ts → browser/browser-runtime-plugin-helpers.d.ts} +0 -0
  158. /package/src/build/{browser-runtime-plugin-helpers.js → browser/browser-runtime-plugin-helpers.js} +0 -0
  159. /package/src/build/{lit-static-render-worker-context.d.ts → browser/lit-static-render-worker-context.d.ts} +0 -0
  160. /package/src/build/{lit-static-render-worker-context.js → browser/lit-static-render-worker-context.js} +0 -0
  161. /package/src/build/{build-input-fingerprint.js → cache/build-input-fingerprint.js} +0 -0
  162. /package/src/build/{build-contracts.js → contracts/build-contracts.js} +0 -0
  163. /package/src/build/{build-types.d.ts → contracts/build-types.d.ts} +0 -0
  164. /package/src/build/{build-types.js → contracts/build-types.js} +0 -0
  165. /package/src/build/{rolldown-build-adapter.js → rolldown/rolldown-build-adapter.js} +0 -0
  166. /package/src/build/{rolldown-build-invocation-metrics.d.ts → rolldown/rolldown-build-invocation-metrics.d.ts} +0 -0
  167. /package/src/build/{rolldown-build-invocation-metrics.js → rolldown/rolldown-build-invocation-metrics.js} +0 -0
  168. /package/src/build/{runtime-build-output-normalizer.d.ts → rolldown/runtime-build-output-normalizer.d.ts} +0 -0
  169. /package/src/build/{server-side-css-shim-plugin.d.ts → rolldown/server-side-css-shim-plugin.d.ts} +0 -0
  170. /package/src/build/{server-side-css-shim-plugin.js → rolldown/server-side-css-shim-plugin.js} +0 -0
  171. /package/src/build/{build-profile-options.js → runtime/build-profile-options.js} +0 -0
  172. /package/src/build/{parallel-build-executor.js → runtime/parallel-build-executor.js} +0 -0
  173. /package/src/build/{serialized-build-executor.js → runtime/serialized-build-executor.js} +0 -0
  174. /package/src/route-renderer/orchestration/{layout-shell-props.service.js → document-shell/layout-shell-props.service.js} +0 -0
  175. /package/src/route-renderer/orchestration/{page-browser-graph-contribution.loader.js → page-browser-graph/page-browser-graph-contribution.loader.js} +0 -0
  176. /package/src/route-renderer/orchestration/{processed-asset-dedupe.js → page-browser-graph/processed-asset-dedupe.js} +0 -0
  177. /package/src/route-renderer/orchestration/{route-prepared-options.utils.d.ts → route-pipeline/route-prepared-options.utils.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
- import type { ProcessedAsset } from '../../services/assets/asset-processing-service/index.js';
2
- import type { HtmlDocumentContribution } from '../../services/html/html-transformer.service.js';
3
- import type { ComponentRenderResult, EcoComponent, EcoPageFile, IntegrationRendererRenderOptions, PageBrowserGraphContribution, PageBrowserGraphContributionContext, PagePackageResult, RouteRendererBody, RouteRendererOptions } from '../../types/public-types.js';
1
+ import type { ProcessedAsset } from '../../../services/assets/asset-processing-service/index.js';
2
+ import type { HtmlDocumentContribution } from '../../../services/html/html-transformer.service.js';
3
+ import type { EcoComponent, EcoPageFile, IntegrationRendererRenderOptions, PageBrowserGraphContribution, PageBrowserGraphContributionContext, PagePackageResult, RouteRendererBody, RouteRendererOptions } from '../../../types/public-types.js';
4
4
  import type { RouteHtmlFinalization, RouteRenderOrchestratorAdapter, RouteRenderOrchestratorResolvedInputs } from './route-render-orchestrator.js';
5
5
  /**
6
6
  * Host surface required to build the orchestrator adapter for one integration renderer.
@@ -15,19 +15,12 @@ export type IntegrationRouteRenderAdapterHost<C> = {
15
15
  }>;
16
16
  importPageFile(file: string): Promise<EcoPageFile>;
17
17
  collectPageBrowserGraphContribution(context: PageBrowserGraphContributionContext): Promise<PageBrowserGraphContribution | undefined>;
18
- resolveRoutePageComponentRender(input: {
19
- Page: EcoComponent;
20
- Layout?: EcoComponent;
21
- props: Record<string, unknown>;
22
- routeOptions: RouteRendererOptions;
23
- }): Promise<ComponentRenderResult | undefined>;
24
18
  renderRouteBody(renderOptions: IntegrationRendererRenderOptions<C>): Promise<RouteRendererBody>;
25
19
  getDocumentAttributes(renderOptions: IntegrationRendererRenderOptions<C>): Record<string, string> | undefined;
26
20
  getHtmlDocumentContributions(options: {
27
21
  renderOptions: IntegrationRendererRenderOptions<C>;
28
22
  partial: boolean;
29
23
  }): HtmlDocumentContribution[] | undefined;
30
- applyAttributesToFirstBodyElement(html: string, attributes: Record<string, string>): string;
31
24
  applyAttributesToHtmlElement(html: string, attributes: Record<string, string>): string;
32
25
  transformRouteResponse(response: Response, htmlContributions?: HtmlDocumentContribution[], pagePackage?: PagePackageResult): Promise<RouteRendererBody>;
33
26
  };
@@ -1,4 +1,4 @@
1
- import { loadPageBrowserGraphContribution } from "./page-browser-graph-contribution.loader.js";
1
+ import { loadPageBrowserGraphContribution } from "../page-browser-graph/page-browser-graph-contribution.loader.js";
2
2
  import { buildRouteHtmlFinalization } from "./route-html-finalization.service.js";
3
3
  function createIntegrationRouteRenderAdapter(host) {
4
4
  return {
@@ -10,13 +10,11 @@ function createIntegrationRouteRenderAdapter(host) {
10
10
  (file) => host.importPageFile(file),
11
11
  (context) => host.collectPageBrowserGraphContribution(context)
12
12
  ),
13
- resolveRoutePageComponentRender: (input) => host.resolveRoutePageComponentRender(input),
14
13
  renderRouteBody: (renderOptions) => host.renderRouteBody(renderOptions),
15
14
  getRouteHtmlFinalization: (renderOptions) => buildRouteHtmlFinalization({
16
15
  renderOptions,
17
16
  getDocumentAttributes: (options) => host.getDocumentAttributes(options),
18
17
  getHtmlDocumentContributions: (options) => host.getHtmlDocumentContributions(options),
19
- applyAttributesToFirstBodyElement: (html, attributes) => host.applyAttributesToFirstBodyElement(html, attributes),
20
18
  applyAttributesToHtmlElement: (html, attributes) => host.applyAttributesToHtmlElement(html, attributes)
21
19
  }),
22
20
  transformRouteResponse: (response, htmlContributions, pagePackage) => host.transformRouteResponse(response, htmlContributions, pagePackage)
@@ -0,0 +1,6 @@
1
+ export declare function decodeHtmlEntities(value: string): string;
2
+ export declare function normalizeUnresolvedMarkerArtifactHtml(html: string): string;
3
+ export declare function inspectUnresolvedMarkerArtifactHtml(html: string): {
4
+ hasUnresolvedMarkerArtifacts: boolean;
5
+ normalizedHtml: string;
6
+ };
@@ -0,0 +1,27 @@
1
+ function decodeHtmlEntities(value) {
2
+ let decoded = value;
3
+ let previous;
4
+ do {
5
+ previous = decoded;
6
+ decoded = decoded.replaceAll("&quot;", '"').replaceAll("&#39;", "'").replaceAll("&#x27;", "'").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&amp;", "&");
7
+ } while (decoded !== previous);
8
+ return decoded;
9
+ }
10
+ function normalizeUnresolvedMarkerArtifactHtml(html) {
11
+ return html.replace(
12
+ /&(?:amp;)?lt;eco-marker\b[\s\S]*?&(?:amp;)?gt;&(?:amp;)?lt;\/eco-marker&(?:amp;)?gt;/g,
13
+ (marker) => decodeHtmlEntities(marker)
14
+ );
15
+ }
16
+ function inspectUnresolvedMarkerArtifactHtml(html) {
17
+ const normalizedHtml = normalizeUnresolvedMarkerArtifactHtml(html);
18
+ return {
19
+ normalizedHtml,
20
+ hasUnresolvedMarkerArtifacts: normalizedHtml.includes("<eco-marker")
21
+ };
22
+ }
23
+ export {
24
+ decodeHtmlEntities,
25
+ inspectUnresolvedMarkerArtifactHtml,
26
+ normalizeUnresolvedMarkerArtifactHtml
27
+ };
@@ -1,5 +1,5 @@
1
- import type { HtmlDocumentContribution } from '../../services/html/html-transformer.service.js';
2
- import type { IntegrationRendererRenderOptions } from '../../types/public-types.js';
1
+ import type { HtmlDocumentContribution } from '../../../services/html/html-transformer.service.js';
2
+ import type { IntegrationRendererRenderOptions } from '../../../types/public-types.js';
3
3
  import type { RouteHtmlFinalization } from './route-render-orchestrator.js';
4
4
  export type RouteHtmlFinalizationContext<C> = {
5
5
  renderOptions: IntegrationRendererRenderOptions<C>;
@@ -8,7 +8,6 @@ export type RouteHtmlFinalizationContext<C> = {
8
8
  renderOptions: IntegrationRendererRenderOptions<C>;
9
9
  partial: boolean;
10
10
  }) => HtmlDocumentContribution[] | undefined;
11
- applyAttributesToFirstBodyElement: (html: string, attributes: Record<string, string>) => string;
12
11
  applyAttributesToHtmlElement: (html: string, attributes: Record<string, string>) => string;
13
12
  };
14
13
  /**
@@ -0,0 +1,21 @@
1
+ function buildRouteHtmlFinalization(context) {
2
+ const { renderOptions } = context;
3
+ const documentAttributes = context.getDocumentAttributes(renderOptions);
4
+ const htmlContributions = context.getHtmlDocumentContributions({ renderOptions, partial: false });
5
+ const hasStructuralFinalization = documentAttributes && Object.keys(documentAttributes).length > 0;
6
+ if (!hasStructuralFinalization && (!htmlContributions || htmlContributions.length === 0)) {
7
+ return {};
8
+ }
9
+ return {
10
+ htmlContributions,
11
+ finalizeHtml: (html) => {
12
+ if (!documentAttributes || Object.keys(documentAttributes).length === 0) {
13
+ return html;
14
+ }
15
+ return context.applyAttributesToHtmlElement(html, documentAttributes);
16
+ }
17
+ };
18
+ }
19
+ export {
20
+ buildRouteHtmlFinalization
21
+ };
@@ -1,6 +1,6 @@
1
- import type { EcoPagesAppConfig } from '../../types/internal-types.js';
2
- import type { ComponentRenderResult, EcoComponent, EcoPageComponent, EcoPageFile, HtmlTemplateProps, IntegrationRendererRenderOptions, PageBrowserGraphResult, PageMetadataProps, EcoPageLayoutEntry, RouteRendererOptions } from '../../types/public-types.js';
3
- import { type ProcessedAsset } from '../../services/assets/asset-processing-service/index.js';
1
+ import type { EcoPagesAppConfig } from '../../../types/internal-types.js';
2
+ import type { EcoComponent, EcoPageComponent, EcoPageFile, HtmlTemplateProps, IntegrationRendererRenderOptions, PageBrowserGraphResult, PageMetadataProps, EcoPageLayoutEntry, RouteRendererOptions } from '../../../types/public-types.js';
3
+ import { type ProcessedAsset } from '../../../services/assets/asset-processing-service/index.js';
4
4
  type PreparedRenderInputs = {
5
5
  Page: EcoPageFile['default'] | EcoPageComponent<any>;
6
6
  HtmlTemplate: EcoComponent<HtmlTemplateProps>;
@@ -20,7 +20,6 @@ export declare function buildPreparedRenderOptions<C = unknown>(input: {
20
20
  resolvedDependencies: ProcessedAsset[];
21
21
  allDependencies: ProcessedAsset[];
22
22
  pageBrowserGraph?: PageBrowserGraphResult;
23
- componentRender?: ComponentRenderResult;
24
23
  appConfig: EcoPagesAppConfig;
25
24
  }): IntegrationRendererRenderOptions<C>;
26
25
  export {};
@@ -1,16 +1,8 @@
1
- import { createPagePackage } from "../../services/assets/asset-processing-service/index.js";
2
- import { dedupeProcessedAssets } from "./processed-asset-dedupe.js";
1
+ import { createPagePackage } from "../../../services/assets/asset-processing-service/index.js";
2
+ import { dedupeProcessedAssets } from "../page-browser-graph/processed-asset-dedupe.js";
3
3
  import { createPageLocalsProxy } from "./route-prepared-options.utils.js";
4
4
  function buildPreparedRenderOptions(input) {
5
- const {
6
- routeOptions,
7
- resolvedInputs,
8
- resolvedDependencies,
9
- allDependencies,
10
- pageBrowserGraph,
11
- componentRender,
12
- appConfig
13
- } = input;
5
+ const { routeOptions, resolvedInputs, resolvedDependencies, allDependencies, pageBrowserGraph, appConfig } = input;
14
6
  const { Page, HtmlTemplate, Layouts, Layout, layoutEntries, props, metadata, integrationSpecificProps } = resolvedInputs;
15
7
  const dedupedDependencies = dedupeProcessedAssets(allDependencies);
16
8
  const pagePackage = createPagePackage(dedupedDependencies, { pageBrowserGraph });
@@ -29,7 +21,6 @@ function buildPreparedRenderOptions(input) {
29
21
  ...routeOptions,
30
22
  resolvedDependencies,
31
23
  pagePackage,
32
- componentRender,
33
24
  HtmlTemplate,
34
25
  Layouts,
35
26
  Layout,
@@ -1,4 +1,4 @@
1
- import { LocalsAccessError } from "../../errors/locals-access-error.js";
1
+ import { LocalsAccessError } from "../../../errors/locals-access-error.js";
2
2
  function createPageLocalsProxy(filePath) {
3
3
  const errorMessage = `[ecopages] Request locals are only available during request-time rendering with cache: 'dynamic'. Page: ${filePath}. If you meant to use locals here, set cache: 'dynamic' and provide locals from route middleware/handlers.`;
4
4
  return new Proxy(
@@ -1,9 +1,9 @@
1
- import type { EcoPagesAppConfig } from '../../types/internal-types.js';
2
- import type { ComponentRenderResult, EcoComponent, EcoPageComponent, EcoPageFile, HtmlTemplateProps, IntegrationRendererRenderOptions, PageBrowserGraphContribution, PageBrowserGraphResult, PageMetadataProps, RouteRendererBody, RouteRendererOptions, RouteRenderResult, EcoPageLayoutEntry } from '../../types/public-types.js';
3
- import type { AssetProcessingService, ProcessedAsset } from '../../services/assets/asset-processing-service/index.js';
4
- import type { HtmlDocumentContribution } from '../../services/html/html-transformer.service.js';
5
- import { OwnershipValidationService } from './ownership-validation.service.js';
6
- import { PageBrowserGraphService } from './page-browser-graph.service.js';
1
+ import type { EcoPagesAppConfig } from '../../../types/internal-types.js';
2
+ import type { EcoComponent, EcoPageComponent, EcoPageFile, HtmlTemplateProps, IntegrationRendererRenderOptions, PageBrowserGraphContribution, PageBrowserGraphResult, PageMetadataProps, RouteRendererBody, RouteRendererOptions, RouteRenderResult, EcoPageLayoutEntry } from '../../../types/public-types.js';
3
+ import type { AssetProcessingService, ProcessedAsset } from '../../../services/assets/asset-processing-service/index.js';
4
+ import type { HtmlDocumentContribution } from '../../../services/html/html-transformer.service.js';
5
+ import { OwnershipValidationService } from '../ownership-graph/ownership-validation.service.js';
6
+ import { PageBrowserGraphService } from '../page-browser-graph/page-browser-graph.service.js';
7
7
  export type RouteRenderOrchestratorResolvedInputs = {
8
8
  Page: EcoPageFile['default'] | EcoPageComponent<any>;
9
9
  HtmlTemplate: EcoComponent<HtmlTemplateProps>;
@@ -46,15 +46,6 @@ export interface RouteRenderOrchestratorAdapter<C> {
46
46
  * Collects declarative Page Browser Graph requirements for one route.
47
47
  */
48
48
  collectPageBrowserGraphContribution(routeFile: string): Promise<PageBrowserGraphContribution | undefined>;
49
- /**
50
- * Resolves the optional page-root render through the foreign-child-aware component contract.
51
- */
52
- resolveRoutePageComponentRender(input: {
53
- Page: EcoComponent;
54
- Layout?: EcoComponent;
55
- props: Record<string, unknown>;
56
- routeOptions: RouteRendererOptions;
57
- }): Promise<ComponentRenderResult | undefined>;
58
49
  /**
59
50
  * Executes the Integration-specific route render.
60
51
  */
@@ -100,8 +91,8 @@ export declare class RouteRenderOrchestrator {
100
91
  * Builds normalized route render options before the integration render runs.
101
92
  *
102
93
  * This preparation step validates route-root ownership, resolves page data,
103
- * collects processed assets, captures optional page-root render metadata, and
104
- * produces the page package consumed by downstream HTML transformation.
94
+ * collects processed assets, and produces the page package consumed by downstream
95
+ * HTML transformation.
105
96
  */
106
97
  prepareRenderOptions<C = unknown>(routeOptions: RouteRendererOptions, adapter: RouteRenderOrchestratorAdapter<C>): Promise<IntegrationRendererRenderOptions<C>>;
107
98
  resolveDeclaredPageBrowserGraph(input: {
@@ -1,12 +1,15 @@
1
- import { inspectUnresolvedMarkerArtifactHtml } from "./render-output.utils.js";
2
- import { OwnershipValidationService, throwIfOwnershipInvalid } from "./ownership-validation.service.js";
1
+ import { inspectUnresolvedMarkerArtifactHtml } from "./marker-artifact.utils.js";
2
+ import {
3
+ OwnershipValidationService,
4
+ throwIfOwnershipInvalid
5
+ } from "../ownership-graph/ownership-validation.service.js";
3
6
  import {
4
7
  buildEagerSsrLazyAssetsFromGraph,
5
8
  collectResolvedLazyTriggersFromGraph,
6
9
  collectUsedIntegrationDependenciesFromGraph
7
- } from "./component-graph-collectors.js";
8
- import { buildGlobalInjectorAssets } from "./global-injector-assets.service.js";
9
- import { PageBrowserGraphService } from "./page-browser-graph.service.js";
10
+ } from "../ownership-graph/component-graph-collectors.js";
11
+ import { buildGlobalInjectorAssets } from "../page-browser-graph/global-injector-assets.service.js";
12
+ import { PageBrowserGraphService } from "../page-browser-graph/page-browser-graph.service.js";
10
13
  import { buildPreparedRenderOptions } from "./route-prepared-options.builder.js";
11
14
  class RouteRenderOrchestrator {
12
15
  appConfig;
@@ -23,12 +26,12 @@ class RouteRenderOrchestrator {
23
26
  * Builds normalized route render options before the integration render runs.
24
27
  *
25
28
  * This preparation step validates route-root ownership, resolves page data,
26
- * collects processed assets, captures optional page-root render metadata, and
27
- * produces the page package consumed by downstream HTML transformation.
29
+ * collects processed assets, and produces the page package consumed by downstream
30
+ * HTML transformation.
28
31
  */
29
32
  async prepareRenderOptions(routeOptions, adapter) {
30
33
  const resolvedInputs = await adapter.resolveRouteRenderInputs(routeOptions);
31
- const { Page, HtmlTemplate, Layouts, Layout } = resolvedInputs;
34
+ const { Page, HtmlTemplate, Layouts } = resolvedInputs;
32
35
  const validationErrors = this.ownershipValidationService.validate({
33
36
  currentIntegrationName: adapter.name,
34
37
  roots: [
@@ -39,7 +42,7 @@ class RouteRenderOrchestrator {
39
42
  });
40
43
  throwIfOwnershipInvalid(validationErrors);
41
44
  const componentsToResolve = [HtmlTemplate, ...Layouts, Page];
42
- const [{ resolvedDependencies }, pageBrowserGraph, componentRender] = await Promise.all([
45
+ const [{ resolvedDependencies }, pageBrowserGraph] = await Promise.all([
43
46
  adapter.resolveRouteDependencies({
44
47
  components: componentsToResolve
45
48
  }),
@@ -47,21 +50,12 @@ class RouteRenderOrchestrator {
47
50
  routeFile: routeOptions.file,
48
51
  integrationName: adapter.name,
49
52
  collectContribution: async (routeFile) => await adapter.collectPageBrowserGraphContribution(routeFile)
50
- }),
51
- adapter.resolveRoutePageComponentRender({
52
- Page,
53
- Layout,
54
- props: resolvedInputs.props,
55
- routeOptions
56
53
  })
57
54
  ]);
58
55
  const allDependencies = [
59
56
  ...resolvedDependencies,
60
57
  ...collectUsedIntegrationDependenciesFromGraph(this.appConfig, componentsToResolve, adapter.name)
61
58
  ];
62
- if (componentRender?.assets?.length) {
63
- allDependencies.push(...componentRender.assets);
64
- }
65
59
  const triggers = collectResolvedLazyTriggersFromGraph(componentsToResolve, adapter.name);
66
60
  const [globalAssets, eagerSsrLazyAssets] = await Promise.all([
67
61
  triggers.length > 0 ? buildGlobalInjectorAssets(this.appConfig, this.assetProcessingService, triggers, adapter.name) : Promise.resolve([]),
@@ -74,7 +68,6 @@ class RouteRenderOrchestrator {
74
68
  resolvedDependencies,
75
69
  allDependencies,
76
70
  pageBrowserGraph,
77
- componentRender,
78
71
  appConfig: this.appConfig
79
72
  });
80
73
  }
@@ -1,5 +1,5 @@
1
1
  import { IntegrationRenderer } from "./integration-renderer.js";
2
- import { resolveInnermostPageLayout } from "./layout-shell-props.service.js";
2
+ import { resolveInnermostPageLayout } from "./document-shell/layout-shell-props.service.js";
3
3
  class StringMarkupRenderer extends IntegrationRenderer {
4
4
  async renderComponent(input) {
5
5
  if (typeof input.component !== "function") {
@@ -16,7 +16,7 @@ import { materializeContentScriptAsset } from "./materialize-content-script-asse
16
16
  import {
17
17
  getDevBrowserScriptCacheEntry,
18
18
  setDevBrowserScriptCacheEntry
19
- } from "../../../build/dev-browser-script-cache.js";
19
+ } from "../../../build/cache/dev-browser-script-cache.js";
20
20
  import {
21
21
  ContentScriptProcessor,
22
22
  ContentStylesheetProcessor,
@@ -1,4 +1,4 @@
1
- import type { EcoBuildPlugin } from '../../../build/build-types.js';
1
+ import type { EcoBuildPlugin } from '../../../build/contracts/build-types.js';
2
2
  export type AssetSource = 'content' | 'file' | 'node-module';
3
3
  export type AssetKind = 'script' | 'stylesheet';
4
4
  export type AssetPosition = 'head' | 'body';
@@ -1,4 +1,4 @@
1
- import type { EcoBuildPlugin } from '../../../build/build-types.js';
1
+ import type { EcoBuildPlugin } from '../../../build/contracts/build-types.js';
2
2
  import type { AssetDefinition } from './assets.types.js';
3
3
  import { type BrowserRuntimeEntryModuleConfig } from './browser-runtime-entry.factory.js';
4
4
  export declare const BROWSER_RUNTIME_SCRIPT_ATTRIBUTES: {
@@ -1,5 +1,4 @@
1
1
  import type { EcoPagesAppConfig } from '../../../../../types/internal-types.js';
2
- import type { EcoBuildPlugin } from '../../../../../build/build-types.js';
3
2
  import type { ScriptAsset } from '../../assets.types.js';
4
3
  import { BaseProcessor } from './base-processor.js';
5
4
  import { type BrowserBundleGroupedEntry } from '../../../browser-bundle.service.js';
@@ -10,7 +9,6 @@ export declare abstract class BaseScriptProcessor<T extends ScriptAsset> extends
10
9
  });
11
10
  protected shouldBundle(dep: T): boolean;
12
11
  protected getBundlerOptions(dep: T): Record<string, any>;
13
- protected collectBuildPlugins(excludePluginNames?: string[]): EcoBuildPlugin[];
14
12
  protected bundleScript({ entrypoint, outdir, excludeAppBuildPlugins, plugins: additionalPlugins, ...rest }: {
15
13
  entrypoint: string;
16
14
  outdir: string;
@@ -1,5 +1,4 @@
1
1
  import { appLogger } from "../../../../../global/app-logger.js";
2
- import { getAppBrowserBuildPlugins } from "../../../../../build/build-adapter.js";
3
2
  import { fileSystem } from "@ecopages/file-system";
4
3
  import path from "node:path";
5
4
  import { BaseProcessor } from "./base-processor.js";
@@ -22,14 +21,6 @@ class BaseScriptProcessor extends BaseProcessor {
22
21
  }
23
22
  return dep.bundleOptions || {};
24
23
  }
25
- collectBuildPlugins(excludePluginNames) {
26
- const buildPlugins = getAppBrowserBuildPlugins(this.appConfig);
27
- if (!excludePluginNames || excludePluginNames.length === 0) {
28
- return buildPlugins;
29
- }
30
- const excluded = new Set(excludePluginNames);
31
- return buildPlugins.filter((plugin) => !excluded.has(plugin.name));
32
- }
33
24
  async bundleScript({
34
25
  entrypoint,
35
26
  outdir,
@@ -37,8 +28,6 @@ class BaseScriptProcessor extends BaseProcessor {
37
28
  plugins: additionalPlugins,
38
29
  ...rest
39
30
  }) {
40
- const buildPlugins = this.collectBuildPlugins(excludeAppBuildPlugins);
41
- const allPlugins = additionalPlugins ? [...additionalPlugins, ...buildPlugins] : buildPlugins;
42
31
  const buildResult = await this.browserBundleService.bundle({
43
32
  profile: "browser-script",
44
33
  entrypoints: [entrypoint],
@@ -47,7 +36,7 @@ class BaseScriptProcessor extends BaseProcessor {
47
36
  excludeAppBuildPlugins,
48
37
  splitting: true,
49
38
  naming: "[name]-[hash].[ext]",
50
- plugins: allPlugins,
39
+ plugins: additionalPlugins,
51
40
  ...rest
52
41
  });
53
42
  if (!buildResult.success) {
@@ -86,8 +75,6 @@ class BaseScriptProcessor extends BaseProcessor {
86
75
  plugins: additionalPlugins,
87
76
  ...rest
88
77
  }) {
89
- const buildPlugins = this.collectBuildPlugins(excludeAppBuildPlugins);
90
- const allPlugins = additionalPlugins ? [...additionalPlugins, ...buildPlugins] : buildPlugins;
91
78
  const buildResult = await this.browserBundleService.bundleGroupedEntries(entries, {
92
79
  profile: "browser-script",
93
80
  outdir,
@@ -96,7 +83,7 @@ class BaseScriptProcessor extends BaseProcessor {
96
83
  ...rest,
97
84
  splitting: true,
98
85
  naming: "[name]-[hash].[ext]",
99
- plugins: allPlugins
86
+ plugins: additionalPlugins
100
87
  });
101
88
  if (!buildResult.success) {
102
89
  for (const log of buildResult.logs) {
@@ -1,7 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { fileSystem } from "@ecopages/file-system";
3
3
  import { resolveInlineContentScriptBody } from "../../inline-content-script-body.js";
4
- import { shouldUseDevBrowserScriptCache } from "../../../../../build/dev-browser-script-cache.js";
4
+ import { shouldUseDevBrowserScriptCache } from "../../../../../build/cache/dev-browser-script-cache.js";
5
5
  import { BaseScriptProcessor } from "../base/base-script-processor.js";
6
6
  class ContentScriptProcessor extends BaseScriptProcessor {
7
7
  getContentScriptEntryDir() {
@@ -1,6 +1,24 @@
1
- import type { BuildResult, BuildTranspileProfile } from '../../build/build-adapter.js';
2
- import type { EcoBuildPlugin } from '../../build/build-types.js';
1
+ import type { BuildResult } from '../../build/build-adapter.js';
2
+ import type { BuildTranspileProfile } from '../../build/build-adapter.js';
3
+ import type { EcoBuildPlugin } from '../../build/contracts/build-types.js';
3
4
  import type { EcoPagesAppConfig } from '../../types/internal-types.js';
5
+ /**
6
+ * Browser-oriented build request accepted by {@link BrowserBundleService}.
7
+ *
8
+ * @remarks
9
+ * `profile` is a {@link BuildTranspileProfile} (transpile settings only).
10
+ * `executor` selects the {@link BuildRuntime} concurrency slot:
11
+ * - `'hmr'` + (`hmr-entrypoint` | `hmr-runtime`) → `'browser-hmr'`
12
+ * - everything else (including `browser-script`, and `'build'`) → `'route-module'`
13
+ *
14
+ * Defaults `executor` to `'hmr'`. Request options are always assembled with
15
+ * browser-hmr *defaults* via {@link createBrowserBuildRequest}; only the
16
+ * concurrency/dedupe wrapper differs.
17
+ *
18
+ * Uses request-scope {@link requestBuildDedupe} plus in-flight
19
+ * {@link DedupingBuildExecutor} coalescing; both key on
20
+ * {@link createBuildRequestIdentity}.
21
+ */
4
22
  export type BrowserBundleOptions = {
5
23
  entrypoints: string[] | Record<string, string>;
6
24
  outdir?: string;
@@ -17,28 +35,10 @@ export type BrowserBundleOptions = {
17
35
  external?: string[];
18
36
  plugins?: EcoBuildPlugin[];
19
37
  executor?: 'build' | 'hmr';
20
- [key: string]: unknown;
21
- profile: BuildTranspileProfile;
22
- excludeAppBuildPlugins?: string[];
23
- };
24
- type BrowserBundleGroupedOptions = {
25
- outdir?: string;
26
- outbase?: string;
27
- naming?: string;
28
- conditions?: string[];
29
- define?: Record<string, string>;
30
- minify?: boolean;
31
- treeshaking?: boolean;
32
- splitting?: boolean;
33
- root?: string;
34
- bundle?: boolean;
35
- externalPackages?: boolean;
36
- external?: string[];
37
- plugins?: EcoBuildPlugin[];
38
- [key: string]: unknown;
39
38
  profile: BuildTranspileProfile;
40
39
  excludeAppBuildPlugins?: string[];
41
40
  };
41
+ type BrowserBundleGroupedOptions = Omit<BrowserBundleOptions, 'entrypoints'>;
42
42
  export interface BrowserBundleExecutor {
43
43
  bundle(options: BrowserBundleOptions): Promise<BuildResult>;
44
44
  }
@@ -50,24 +50,20 @@ export type BrowserBundleGroupedEntry = {
50
50
  * App-owned boundary for browser-oriented bundle work.
51
51
  *
52
52
  * @remarks
53
- * This service owns the shared browser transpile defaults and ensures browser
54
- * builds always run through the app-owned executor rather than direct backend
55
- * calls scattered across HMR and asset processing paths.
53
+ * Owns shared browser transpile defaults and ensures browser builds run through
54
+ * the app-owned executor rather than direct backend calls. Assembles a complete
55
+ * request via {@link createBrowserBuildRequest} before scheduling.
56
56
  */
57
57
  export declare class BrowserBundleService implements BrowserBundleExecutor {
58
58
  private readonly appConfig;
59
- /**
60
- * Creates the browser bundle boundary for one finalized app instance.
61
- */
62
59
  constructor(appConfig: EcoPagesAppConfig);
63
60
  /**
64
61
  * Runs one browser-targeted build through the app-owned executor.
65
62
  *
66
63
  * @remarks
67
- * Browser defaults and app-owned browser build plugins are applied here so HMR
68
- * and runtime asset generation do not have to recreate that policy at each call
69
- * site. Also forwards {@link getAppSourceTransforms | app source transforms} so
70
- * metadata injection runs after boundary/runtime `onLoad` rewrites.
64
+ * Browser defaults, app-owned browser plugins, and
65
+ * {@link getAppSourceTransforms | app source transforms} are applied here
66
+ * so HMR and asset generation do not recreate that policy at each call site.
71
67
  */
72
68
  bundle(options: BrowserBundleOptions): Promise<BuildResult>;
73
69
  bundleGroupedEntries(entries: BrowserBundleGroupedEntry[], options: BrowserBundleGroupedOptions): Promise<BuildResult>;
@@ -1,10 +1,8 @@
1
- import { getAppBrowserBuildPlugins, getAppTranspileOptions } from "../../build/build-adapter.js";
2
- import { requireBuildRuntime } from "../../build/build-runtime.js";
3
- import { mergeEcoBuildPlugins } from "../../build/build-manifest.js";
4
- import { getAppSourceTransforms } from "../../plugins/source-transform.js";
1
+ import { createBrowserBuildRequest } from "../../build/runtime/build-request-policy.js";
2
+ import { requireBuildRuntime } from "../../build/runtime/build-runtime.js";
5
3
  import { startupTrace } from "../../diagnostics/startup-trace.js";
6
4
  import { requestBuildDedupe } from "../../diagnostics/request-build-dedupe.js";
7
- import { createBuildOptionsDedupeKey } from "../../build/deduping-build-executor.js";
5
+ import { createBuildRequestIdentity } from "../../build/runtime/build-request-identity.js";
8
6
  function resolveBrowserBundleExecutor(appConfig, profile, executor) {
9
7
  const buildRuntime = requireBuildRuntime(appConfig);
10
8
  if (executor === "hmr" && (profile === "hmr-entrypoint" || profile === "hmr-runtime")) {
@@ -14,9 +12,6 @@ function resolveBrowserBundleExecutor(appConfig, profile, executor) {
14
12
  }
15
13
  class BrowserBundleService {
16
14
  appConfig;
17
- /**
18
- * Creates the browser bundle boundary for one finalized app instance.
19
- */
20
15
  constructor(appConfig) {
21
16
  this.appConfig = appConfig;
22
17
  }
@@ -24,24 +19,18 @@ class BrowserBundleService {
24
19
  * Runs one browser-targeted build through the app-owned executor.
25
20
  *
26
21
  * @remarks
27
- * Browser defaults and app-owned browser build plugins are applied here so HMR
28
- * and runtime asset generation do not have to recreate that policy at each call
29
- * site. Also forwards {@link getAppSourceTransforms | app source transforms} so
30
- * metadata injection runs after boundary/runtime `onLoad` rewrites.
22
+ * Browser defaults, app-owned browser plugins, and
23
+ * {@link getAppSourceTransforms | app source transforms} are applied here
24
+ * so HMR and asset generation do not recreate that policy at each call site.
31
25
  */
32
26
  async bundle(options) {
33
- const { profile, excludeAppBuildPlugins, plugins, executor = "hmr", ...rawBuildOptions } = options;
34
- const appBrowserPlugins = getAppBrowserBuildPlugins(this.appConfig);
35
- const filteredAppBrowserPlugins = excludeAppBuildPlugins && excludeAppBuildPlugins.length > 0 ? appBrowserPlugins.filter((plugin) => !excludeAppBuildPlugins.includes(plugin.name)) : appBrowserPlugins;
36
- const request = {
37
- ...rawBuildOptions,
38
- entrypoints: options.entrypoints,
39
- ...getAppTranspileOptions(this.appConfig, profile),
40
- plugins: mergeEcoBuildPlugins(plugins, filteredAppBrowserPlugins),
41
- sourceTransforms: getAppSourceTransforms(this.appConfig)
42
- };
27
+ const { profile, executor = "hmr", ...requestInput } = options;
28
+ const request = createBrowserBuildRequest(this.appConfig, {
29
+ ...requestInput,
30
+ profile
31
+ });
43
32
  const buildExecutor = resolveBrowserBundleExecutor(this.appConfig, profile, executor);
44
- const dedupeKey = createBuildOptionsDedupeKey(request);
33
+ const dedupeKey = createBuildRequestIdentity(request);
45
34
  return requestBuildDedupe.dedupeBuild(dedupeKey, async () => {
46
35
  const result = await buildExecutor.build(request);
47
36
  startupTrace.recordBrowserBundle(result.outputs);
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  buildProcessedAssetDedupeKey,
6
6
  dedupeProcessedAssets
7
- } from "../../route-renderer/orchestration/processed-asset-dedupe.js";
7
+ } from "../../route-renderer/orchestration/page-browser-graph/processed-asset-dedupe.js";
8
8
  class HtmlTransformerService {
9
9
  processedDependencies = [];
10
10
  pagePackage;
@@ -87,6 +87,11 @@ export declare class DevelopmentInvalidationService {
87
87
  isServerModuleSourceFile(filePath: string): boolean;
88
88
  /**
89
89
  * Returns whether a processor owns the changed file as an asset input.
90
+ *
91
+ * @remarks
92
+ * Watch config drives processor notifications only. Asset ownership requires
93
+ * declared capabilities so dependency-only watches (for example content
94
+ * collection MDX scans) do not skip server invalidation and HMR.
90
95
  */
91
96
  isProcessorOwnedAsset(filePath: string): boolean;
92
97
  }
@@ -218,21 +218,20 @@ class DevelopmentInvalidationService {
218
218
  }
219
219
  /**
220
220
  * Returns whether a processor owns the changed file as an asset input.
221
+ *
222
+ * @remarks
223
+ * Watch config drives processor notifications only. Asset ownership requires
224
+ * declared capabilities so dependency-only watches (for example content
225
+ * collection MDX scans) do not skip server invalidation and HMR.
221
226
  */
222
227
  isProcessorOwnedAsset(filePath) {
223
228
  for (const processor of this.appConfig.processors.values()) {
224
229
  const capabilities = processor.getAssetCapabilities?.() ?? [];
225
- if (capabilities.length > 0) {
226
- const matchesConfiguredAsset = typeof processor.matchesFileFilter !== "function" || processor.matchesFileFilter(filePath);
227
- if (matchesConfiguredAsset && capabilities.some((capability) => processor.canProcessAsset?.(capability.kind, filePath))) {
228
- return true;
229
- }
230
+ if (capabilities.length === 0) {
230
231
  continue;
231
232
  }
232
- const watchConfig = processor.getWatchConfig();
233
- if (!watchConfig) continue;
234
- const { extensions = [] } = watchConfig;
235
- if (extensions.length && extensions.some((ext) => filePath.endsWith(ext))) {
233
+ const matchesConfiguredAsset = typeof processor.matchesFileFilter !== "function" || processor.matchesFileFilter(filePath);
234
+ if (matchesConfiguredAsset && capabilities.some((capability) => processor.canProcessAsset?.(capability.kind, filePath))) {
236
235
  return true;
237
236
  }
238
237
  }
@@ -5,6 +5,14 @@ import { ServerModuleTranspiler } from './server-module-transpiler.service.js';
5
5
  export declare function shouldAppUseHostModuleLoader(appConfig: EcoPagesAppConfig, filePath: string): boolean;
6
6
  export declare function getAppHostModuleLoader(appConfig: EcoPagesAppConfig): SourceModuleLoader | undefined;
7
7
  export declare function setAppHostModuleLoader(appConfig: EcoPagesAppConfig, hostModuleLoader?: SourceModuleLoader): void;
8
+ /**
9
+ * Creates the app module loader that imports route modules through the build pipeline.
10
+ *
11
+ * @remarks
12
+ * Caller `plugins` are treated as contributions only.
13
+ * {@link PageModuleImportService} assembles the complete server request via
14
+ * {@link createServerBuildRequest}; this loader does not merge app plugins.
15
+ */
8
16
  export declare function createAppModuleLoader(appConfig: EcoPagesAppConfig): AppModuleLoader;
9
17
  export declare function getAppModuleLoader(appConfig: EcoPagesAppConfig): AppModuleLoader;
10
18
  export declare function setAppModuleLoader(appConfig: EcoPagesAppConfig, appModuleLoader: AppModuleLoader): void;