@ecopages/core 0.2.0-beta.25 → 0.2.0-beta.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/package.json +58 -50
  2. package/src/adapters/bun/server-adapter.js +2 -2
  3. package/src/adapters/node/server-adapter.js +2 -2
  4. package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +10 -0
  5. package/src/adapters/shared/hmr-entrypoint-registrar.js +34 -10
  6. package/src/adapters/shared/runtime-server-lifecycle.js +1 -1
  7. package/src/adapters/shared/server-static-builder.d.ts +2 -1
  8. package/src/adapters/shared/server-static-builder.js +16 -14
  9. package/src/adapters/shared/shared-hmr-manager.d.ts +11 -4
  10. package/src/adapters/shared/shared-hmr-manager.js +22 -3
  11. package/src/build/README.md +92 -46
  12. package/src/build/app-build-manifest-runtime.d.ts +28 -2
  13. package/src/build/app-build-manifest-runtime.js +26 -10
  14. package/src/build/{browser-runtime-plugin.d.ts → browser/browser-runtime-plugin.d.ts} +1 -1
  15. package/src/build/{browser-runtime-plugin.js → browser/browser-runtime-plugin.js} +1 -1
  16. package/src/build/{jsx-ownership-plugins.d.ts → browser/jsx-ownership-plugins.d.ts} +2 -2
  17. package/src/build/{jsx-ownership-plugins.js → browser/jsx-ownership-plugins.js} +2 -2
  18. package/src/build/build-adapter.d.ts +18 -21
  19. package/src/build/build-adapter.js +8 -43
  20. package/src/build/{build-input-fingerprint.d.ts → cache/build-input-fingerprint.d.ts} +3 -3
  21. package/src/build/cache/cache-constants.d.ts +4 -0
  22. package/src/build/cache/cache-constants.js +6 -0
  23. package/src/build/cache/cache-keys.d.ts +22 -0
  24. package/src/build/cache/cache-keys.js +63 -0
  25. package/src/build/{dev-browser-script-cache.d.ts → cache/dev-browser-script-cache.d.ts} +2 -2
  26. package/src/build/{dev-browser-script-cache.js → cache/dev-browser-script-cache.js} +4 -4
  27. package/src/build/{pages-unified-graph-build.d.ts → cache/pages-unified-graph-build.d.ts} +1 -1
  28. package/src/build/{pages-unified-graph-build.js → cache/pages-unified-graph-build.js} +18 -26
  29. package/src/build/{production-build-cache.d.ts → cache/production-build-cache.d.ts} +1 -1
  30. package/src/build/{production-build-cache.js → cache/production-build-cache.js} +2 -2
  31. package/src/build/{server-entry-build-cache.d.ts → cache/server-entry-build-cache.d.ts} +3 -4
  32. package/src/build/{server-entry-build-cache.js → cache/server-entry-build-cache.js} +16 -12
  33. package/src/build/{build-contracts.d.ts → contracts/build-contracts.d.ts} +1 -2
  34. package/src/build/contracts/build-manifest.d.ts +90 -0
  35. package/src/build/{build-manifest.js → contracts/build-manifest.js} +2 -2
  36. package/src/build/{rolldown-adapter-helpers.d.ts → rolldown/rolldown-adapter-helpers.d.ts} +20 -3
  37. package/src/build/{rolldown-adapter-helpers.js → rolldown/rolldown-adapter-helpers.js} +26 -6
  38. package/src/build/{rolldown-build-adapter.d.ts → rolldown/rolldown-build-adapter.d.ts} +1 -1
  39. package/src/build/{rolldown-plugin-bridge.d.ts → rolldown/rolldown-plugin-bridge.d.ts} +2 -2
  40. package/src/build/{rolldown-plugin-bridge.js → rolldown/rolldown-plugin-bridge.js} +1 -1
  41. package/src/build/{rolldown-source-transform-pass.d.ts → rolldown/rolldown-source-transform-pass.d.ts} +1 -1
  42. package/src/build/{rolldown-source-transform-pass.js → rolldown/rolldown-source-transform-pass.js} +4 -1
  43. package/src/build/{runtime-build-output-normalizer.js → rolldown/runtime-build-output-normalizer.js} +2 -2
  44. package/src/build/{build-profile-options.d.ts → runtime/build-profile-options.d.ts} +2 -2
  45. package/src/build/runtime/build-request-identity.d.ts +17 -0
  46. package/src/build/runtime/build-request-identity.js +54 -0
  47. package/src/build/runtime/build-request-policy.d.ts +59 -0
  48. package/src/build/runtime/build-request-policy.js +46 -0
  49. package/src/build/{build-runtime.d.ts → runtime/build-runtime.d.ts} +8 -4
  50. package/src/build/{build-runtime.js → runtime/build-runtime.js} +11 -11
  51. package/src/build/{deduping-build-executor.d.ts → runtime/deduping-build-executor.d.ts} +2 -9
  52. package/src/build/runtime/deduping-build-executor.js +34 -0
  53. package/src/build/{parallel-build-executor.d.ts → runtime/parallel-build-executor.d.ts} +1 -1
  54. package/src/build/{serialized-build-executor.d.ts → runtime/serialized-build-executor.d.ts} +1 -1
  55. package/src/config/config-builder.d.ts +1 -1
  56. package/src/diagnostics/startup-trace.d.ts +49 -2
  57. package/src/diagnostics/startup-trace.js +140 -8
  58. package/src/hmr/client/hmr-runtime.js +1 -1
  59. package/src/hmr/hmr-file-change-prep.d.ts +10 -0
  60. package/src/hmr/hmr-file-change-prep.js +17 -0
  61. package/src/plugins/alias-resolver-plugin.d.ts +1 -1
  62. package/src/plugins/eco-component-meta-plugin.d.ts +1 -1
  63. package/src/plugins/foreign-jsx-override-plugin.d.ts +1 -1
  64. package/src/plugins/integration-plugin.d.ts +16 -5
  65. package/src/plugins/integration-plugin.js +11 -1
  66. package/src/plugins/processor.d.ts +28 -8
  67. package/src/plugins/source-transform.d.ts +1 -1
  68. package/src/route-renderer/GRAPH.md +13 -19
  69. package/src/route-renderer/README.md +1 -1
  70. package/src/route-renderer/orchestration/component-render-context.d.ts +4 -4
  71. package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +6 -2
  72. package/src/route-renderer/orchestration/integration-renderer.d.ts +11 -52
  73. package/src/route-renderer/orchestration/integration-renderer.js +38 -91
  74. package/src/route-renderer/orchestration/integration-route-render-adapter.d.ts +1 -8
  75. package/src/route-renderer/orchestration/integration-route-render-adapter.js +0 -2
  76. package/src/route-renderer/orchestration/page-browser-graph-session.d.ts +106 -0
  77. package/src/route-renderer/orchestration/page-browser-graph-session.js +436 -0
  78. package/src/route-renderer/orchestration/page-browser-graph.service.d.ts +9 -3
  79. package/src/route-renderer/orchestration/page-browser-graph.service.js +89 -40
  80. package/src/route-renderer/orchestration/render-output.utils.d.ts +14 -0
  81. package/src/route-renderer/orchestration/render-output.utils.js +30 -0
  82. package/src/route-renderer/orchestration/route-html-finalization.service.d.ts +0 -1
  83. package/src/route-renderer/orchestration/route-html-finalization.service.js +4 -9
  84. package/src/route-renderer/orchestration/route-prepared-options.builder.d.ts +1 -2
  85. package/src/route-renderer/orchestration/route-prepared-options.builder.js +1 -10
  86. package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +3 -12
  87. package/src/route-renderer/orchestration/route-render-orchestrator.js +4 -14
  88. package/src/services/assets/asset-processing-service/asset-dependency-keys.d.ts +13 -0
  89. package/src/services/assets/asset-processing-service/asset-dependency-keys.js +3 -0
  90. package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +3 -1
  91. package/src/services/assets/asset-processing-service/asset-processing.service.js +4 -2
  92. package/src/services/assets/asset-processing-service/assets.types.d.ts +1 -1
  93. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -1
  94. package/src/services/assets/asset-processing-service/grouped-content-bundles.js +19 -3
  95. package/src/services/assets/asset-processing-service/inline-content-script-body.d.ts +11 -0
  96. package/src/services/assets/asset-processing-service/inline-content-script-body.js +17 -0
  97. package/src/services/assets/asset-processing-service/materialize-content-script-asset.d.ts +4 -6
  98. package/src/services/assets/asset-processing-service/materialize-content-script-asset.js +2 -1
  99. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.d.ts +0 -2
  100. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +2 -15
  101. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.d.ts +3 -2
  102. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +33 -54
  103. package/src/services/assets/browser-bundle.service.d.ts +27 -31
  104. package/src/services/assets/browser-bundle.service.js +12 -23
  105. package/src/services/module-loading/app-server-module-transpiler.service.d.ts +8 -0
  106. package/src/services/module-loading/app-server-module-transpiler.service.js +1 -7
  107. package/src/services/module-loading/page-module-import.service.d.ts +1 -1
  108. package/src/services/module-loading/page-module-import.service.js +40 -28
  109. package/src/services/module-loading/route-module-build-cache.store.js +1 -1
  110. package/src/services/module-loading/route-module-build-manifest.d.ts +2 -9
  111. package/src/services/module-loading/route-module-build-manifest.js +12 -43
  112. package/src/services/module-loading/server-module-transpiler.service.d.ts +1 -1
  113. package/src/static-site-generator/README.md +1 -1
  114. package/src/static-site-generator/production-page-browser-graph-prebuild.d.ts +28 -0
  115. package/src/static-site-generator/production-page-browser-graph-prebuild.js +22 -0
  116. package/src/static-site-generator/static-build-invalidation.d.ts +2 -2
  117. package/src/static-site-generator/static-build-invalidation.js +3 -3
  118. package/src/static-site-generator/static-site-generator.js +23 -1
  119. package/src/types/internal-types.d.ts +10 -4
  120. package/src/types/public-types.d.ts +58 -9
  121. package/src/watchers/project-watcher.js +12 -2
  122. package/src/build/build-manifest.d.ts +0 -33
  123. package/src/build/deduping-build-executor.js +0 -56
  124. package/src/build/runtime-build-executor.d.ts +0 -14
  125. package/src/build/runtime-build-executor.js +0 -16
  126. /package/src/build/{browser-runtime-manifest.d.ts → browser/browser-runtime-manifest.d.ts} +0 -0
  127. /package/src/build/{browser-runtime-manifest.js → browser/browser-runtime-manifest.js} +0 -0
  128. /package/src/build/{browser-runtime-plugin-helpers.d.ts → browser/browser-runtime-plugin-helpers.d.ts} +0 -0
  129. /package/src/build/{browser-runtime-plugin-helpers.js → browser/browser-runtime-plugin-helpers.js} +0 -0
  130. /package/src/build/{lit-static-render-worker-context.d.ts → browser/lit-static-render-worker-context.d.ts} +0 -0
  131. /package/src/build/{lit-static-render-worker-context.js → browser/lit-static-render-worker-context.js} +0 -0
  132. /package/src/build/{build-input-fingerprint.js → cache/build-input-fingerprint.js} +0 -0
  133. /package/src/build/{build-contracts.js → contracts/build-contracts.js} +0 -0
  134. /package/src/build/{build-types.d.ts → contracts/build-types.d.ts} +0 -0
  135. /package/src/build/{build-types.js → contracts/build-types.js} +0 -0
  136. /package/src/build/{rolldown-build-adapter.js → rolldown/rolldown-build-adapter.js} +0 -0
  137. /package/src/build/{rolldown-build-invocation-metrics.d.ts → rolldown/rolldown-build-invocation-metrics.d.ts} +0 -0
  138. /package/src/build/{rolldown-build-invocation-metrics.js → rolldown/rolldown-build-invocation-metrics.js} +0 -0
  139. /package/src/build/{runtime-build-output-normalizer.d.ts → rolldown/runtime-build-output-normalizer.d.ts} +0 -0
  140. /package/src/build/{server-side-css-shim-plugin.d.ts → rolldown/server-side-css-shim-plugin.d.ts} +0 -0
  141. /package/src/build/{server-side-css-shim-plugin.js → rolldown/server-side-css-shim-plugin.js} +0 -0
  142. /package/src/build/{build-profile-options.js → runtime/build-profile-options.js} +0 -0
  143. /package/src/build/{parallel-build-executor.js → runtime/parallel-build-executor.js} +0 -0
  144. /package/src/build/{serialized-build-executor.js → runtime/serialized-build-executor.js} +0 -0
@@ -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) {
@@ -3,11 +3,12 @@ import { BaseScriptProcessor } from '../base/base-script-processor.js';
3
3
  export declare class ContentScriptProcessor extends BaseScriptProcessor<ContentScriptAsset> {
4
4
  private getContentScriptEntryDir;
5
5
  private getContentScriptEntryPath;
6
- private createBundleConfigHash;
7
- private createContentScriptCacheKey;
8
6
  private toProcessedAsset;
9
7
  private removeContentScriptEntry;
10
8
  processGrouped(deps: ContentScriptAsset[]): Promise<ProcessedAsset[]>;
11
9
  private getGroupedBundlerOptions;
10
+ /**
11
+ * Emits one content script asset. Cache reuse is owned by {@link AssetProcessingService}.
12
+ */
12
13
  process(dep: ContentScriptAsset): Promise<ProcessedAsset>;
13
14
  }
@@ -1,6 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { fileSystem } from "@ecopages/file-system";
3
- import { shouldUseDevBrowserScriptCache } from "../../../../../build/dev-browser-script-cache.js";
3
+ import { resolveInlineContentScriptBody } from "../../inline-content-script-body.js";
4
+ import { shouldUseDevBrowserScriptCache } from "../../../../../build/cache/dev-browser-script-cache.js";
4
5
  import { BaseScriptProcessor } from "../base/base-script-processor.js";
5
6
  class ContentScriptProcessor extends BaseScriptProcessor {
6
7
  getContentScriptEntryDir() {
@@ -11,24 +12,10 @@ class ContentScriptProcessor extends BaseScriptProcessor {
11
12
  getContentScriptEntryPath(contentHash) {
12
13
  return path.join(this.getContentScriptEntryDir(), `${contentHash}.js`);
13
14
  }
14
- createBundleConfigHash(dep, shouldBundle) {
15
- return this.generateHash(
16
- JSON.stringify({
17
- bundle: shouldBundle,
18
- minify: shouldBundle && this.isProduction,
19
- opts: dep.bundleOptions
20
- })
21
- );
22
- }
23
- createContentScriptCacheKey(dep, shouldBundle) {
24
- const contentHash = this.generateHash(dep.content);
25
- const configHash = this.createBundleConfigHash(dep, shouldBundle);
26
- return `${this.buildCacheKey(`content-script:${contentHash}`, contentHash, dep)}:${configHash}`;
27
- }
28
- toProcessedAsset(dep, filepath, inlineContent) {
15
+ toProcessedAsset(dep, filepath) {
29
16
  return {
30
17
  filepath,
31
- content: dep.inline ? inlineContent : void 0,
18
+ content: resolveInlineContentScriptBody(dep, filepath),
32
19
  kind: "script",
33
20
  position: dep.position,
34
21
  attributes: dep.attributes,
@@ -81,11 +68,7 @@ class ContentScriptProcessor extends BaseScriptProcessor {
81
68
  if (!bundledFilePath) {
82
69
  throw new Error(`Missing grouped bundle output for ${entryName}`);
83
70
  }
84
- return this.toProcessedAsset(
85
- dep,
86
- bundledFilePath,
87
- dep.inline ? fileSystem.readFileSync(bundledFilePath).toString() : void 0
88
- );
71
+ return this.toProcessedAsset(dep, bundledFilePath);
89
72
  });
90
73
  } finally {
91
74
  for (const { contentHash } of tempEntries) {
@@ -104,41 +87,37 @@ class ContentScriptProcessor extends BaseScriptProcessor {
104
87
  }
105
88
  return options;
106
89
  }
90
+ /**
91
+ * Emits one content script asset. Cache reuse is owned by {@link AssetProcessingService}.
92
+ */
107
93
  async process(dep) {
108
94
  const shouldBundle = this.shouldBundle(dep);
109
- const cacheKey = this.createContentScriptCacheKey(dep, shouldBundle);
110
- return this.getOrProcess(cacheKey, async () => {
111
- const hash = this.generateHash(dep.content);
112
- const filename = dep.name ? `${dep.name}.js` : `script-${hash}.js`;
113
- const filepath = path.join(this.getAssetsDir(), "scripts", filename);
114
- if (!shouldBundle) {
115
- if (!dep.inline) {
116
- fileSystem.write(filepath, dep.content);
117
- }
118
- return this.toProcessedAsset(dep, filepath, dep.inline ? dep.content : void 0);
95
+ const hash = this.generateHash(dep.content);
96
+ const filename = dep.name ? `${dep.name}.js` : `script-${hash}.js`;
97
+ const filepath = path.join(this.getAssetsDir(), "scripts", filename);
98
+ if (!shouldBundle) {
99
+ if (!dep.inline) {
100
+ fileSystem.write(filepath, dep.content);
119
101
  }
120
- if (!dep.content) {
121
- throw new Error("No content found for script asset");
122
- }
123
- const entryPath = this.getContentScriptEntryPath(hash);
124
- fileSystem.write(entryPath, dep.content);
125
- try {
126
- const bundledFilePath = await this.bundleScript({
127
- entrypoint: entryPath,
128
- outdir: this.getAssetsDir(),
129
- minify: this.isProduction,
130
- naming: `${path.parse(filename).name}-[hash].[ext]`,
131
- ...this.getBundlerOptions(dep)
132
- });
133
- return this.toProcessedAsset(
134
- dep,
135
- bundledFilePath,
136
- dep.inline ? fileSystem.readFileSync(bundledFilePath).toString() : void 0
137
- );
138
- } finally {
139
- this.removeContentScriptEntry(hash);
140
- }
141
- });
102
+ return this.toProcessedAsset(dep, filepath);
103
+ }
104
+ if (!dep.content) {
105
+ throw new Error("No content found for script asset");
106
+ }
107
+ const entryPath = this.getContentScriptEntryPath(hash);
108
+ fileSystem.write(entryPath, dep.content);
109
+ try {
110
+ const bundledFilePath = await this.bundleScript({
111
+ entrypoint: entryPath,
112
+ outdir: this.getAssetsDir(),
113
+ minify: this.isProduction,
114
+ naming: `${path.parse(filename).name}-[hash].[ext]`,
115
+ ...this.getBundlerOptions(dep)
116
+ });
117
+ return this.toProcessedAsset(dep, bundledFilePath);
118
+ } finally {
119
+ this.removeContentScriptEntry(hash);
120
+ }
142
121
  }
143
122
  }
144
123
  export {
@@ -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);
@@ -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;
@@ -1,6 +1,4 @@
1
- import { getAppServerBuildPlugins } from "../../build/build-adapter.js";
2
- import { requireBuildRuntime } from "../../build/build-runtime.js";
3
- import { getJsxOwnershipPlugins } from "../../build/jsx-ownership-plugins.js";
1
+ import { requireBuildRuntime } from "../../build/runtime/build-runtime.js";
4
2
  import path from "node:path";
5
3
  import { DevelopmentInvalidationService } from "../invalidation/development-invalidation.service.js";
6
4
  import {} from "./app-module-loader.service.js";
@@ -44,8 +42,6 @@ function createAppModuleLoader(appConfig) {
44
42
  canLoadSourceModuleFromHost: (filePath) => shouldAppUseHostModuleLoader(appConfig, filePath),
45
43
  getHostModuleLoader: () => getAppHostModuleLoader(appConfig)
46
44
  });
47
- const appServerBuildPlugins = appConfig.runtime?.buildManifest ? getAppServerBuildPlugins(appConfig) : Array.from(appConfig.loaders?.values() ?? []);
48
- const jsxOwnershipPlugins = getJsxOwnershipPlugins(appConfig);
49
45
  const appModuleLoader = {
50
46
  get owner() {
51
47
  return getAppModuleLoaderOwner(appConfig);
@@ -53,10 +49,8 @@ function createAppModuleLoader(appConfig) {
53
49
  pageModuleImportService,
54
50
  async importModule(options) {
55
51
  const invalidationVersion = options.invalidationVersion ?? invalidationService.getServerModuleInvalidationVersion();
56
- const mergedPlugins = [...appServerBuildPlugins, ...jsxOwnershipPlugins, ...options.plugins ?? []];
57
52
  return await pageModuleImportService.importModule({
58
53
  ...options,
59
- ...mergedPlugins.length > 0 ? { plugins: mergedPlugins } : {},
60
54
  buildExecutor: options.buildExecutor ?? requireBuildRuntime(appConfig).getProfile("route-module"),
61
55
  invalidationVersion
62
56
  });
@@ -1,5 +1,5 @@
1
1
  import { build, type BuildExecutor, type BuildResult } from '../../build/build-adapter.js';
2
- import type { EcoBuildPlugin } from '../../build/build-types.js';
2
+ import type { EcoBuildPlugin } from '../../build/contracts/build-types.js';
3
3
  import type { EcoPagesAppConfig } from '../../types/internal-types.js';
4
4
  import type { SourceModuleLoaderFactory } from './module-loading-types.js';
5
5
  interface PageModuleImportBaseOptions {
@@ -2,19 +2,16 @@ import path from "node:path";
2
2
  import { pathToFileURL } from "node:url";
3
3
  import { fileSystem } from "@ecopages/file-system";
4
4
  import { build } from "../../build/build-adapter.js";
5
- import { resolveBuildProfileOptions } from "../../build/build-profile-options.js";
6
- import { normalizeNodeRuntimeBuildOutputFile } from "../../build/runtime-build-output-normalizer.js";
5
+ import { createServerBuildRequest } from "../../build/runtime/build-request-policy.js";
6
+ import { resolveBuildProfileOptions } from "../../build/runtime/build-profile-options.js";
7
7
  import {
8
8
  importPagesUnifiedGraphModule,
9
9
  isPagesUnifiedGraphPage,
10
10
  shouldBuildPagesUnifiedGraph
11
- } from "../../build/pages-unified-graph-build.js";
12
- import { recordPageModuleBuildInvocation } from "../../build/rolldown-build-invocation-metrics.js";
13
- import {
14
- resolvePageModuleOutputFileName,
15
- createPluginCacheKey,
16
- createJsxCacheKey
17
- } from "./route-module-build-cache.js";
11
+ } from "../../build/cache/pages-unified-graph-build.js";
12
+ import { recordPageModuleBuildInvocation } from "../../build/rolldown/rolldown-build-invocation-metrics.js";
13
+ import { resolvePageModuleOutputFileName } from "./route-module-build-cache.js";
14
+ import { createPluginCacheKey, createJsxCacheKey } from "../../build/cache/cache-keys.js";
18
15
  import { getSharedRouteModuleBuildCache } from "./route-module-build-cache-registry.js";
19
16
  import {
20
17
  RouteModuleDependencyHasher,
@@ -151,11 +148,41 @@ class PageModuleImportService {
151
148
  });
152
149
  const outputNamingTemplate = outputFileName.replace(/\.mjs$/u, ".[ext]");
153
150
  const preferredOutputPath = path.join(outdir, outputFileName);
154
- const routeModuleBuildCache = this.getRouteModuleBuildCache(outdir);
155
- const cachedBuild = routeModuleBuildCache.lookup({
151
+ const buildOptions = this.appConfig ? createServerBuildRequest(this.appConfig, {
152
+ profile: "route-module",
153
+ entrypoints: [filePath],
154
+ outdir,
155
+ naming: outputNamingTemplate,
156
+ splitting: splitting ?? true,
157
+ jsx: options.jsx,
158
+ plugins: options.plugins,
159
+ root: rootDir,
160
+ ...externalPackages !== void 0 ? { externalPackages } : {}
161
+ }) : {
162
+ ...resolveBuildProfileOptions("route-module", { rootDir }, {
163
+ entrypoints: [filePath],
164
+ outdir,
165
+ naming: outputNamingTemplate,
166
+ splitting: splitting ?? true,
167
+ jsx: options.jsx,
168
+ plugins: options.plugins,
169
+ ...externalPackages !== void 0 ? { externalPackages } : {}
170
+ }),
171
+ root: rootDir,
172
+ entrypoints: [filePath]
173
+ };
174
+ const cacheBuildOptions = {
156
175
  ...options,
176
+ rootDir: buildOptions.root ?? rootDir,
177
+ outdir: buildOptions.outdir ?? outdir,
178
+ splitting: buildOptions.splitting,
179
+ externalPackages: buildOptions.externalPackages,
180
+ jsx: buildOptions.jsx,
181
+ plugins: buildOptions.plugins,
157
182
  fileHash
158
- });
183
+ };
184
+ const routeModuleBuildCache = this.getRouteModuleBuildCache(outdir);
185
+ const cachedBuild = routeModuleBuildCache.lookup(cacheBuildOptions);
159
186
  if (cachedBuild) {
160
187
  return await import(
161
188
  /* @vite-ignore */
@@ -169,19 +196,6 @@ class PageModuleImportService {
169
196
  }
170
197
  }
171
198
  recordPageModuleBuildInvocation();
172
- const buildOptions = {
173
- ...resolveBuildProfileOptions("route-module", this.appConfig ?? { rootDir }, {
174
- entrypoints: [filePath],
175
- outdir,
176
- naming: outputNamingTemplate,
177
- splitting: splitting ?? true,
178
- jsx: options.jsx,
179
- plugins: options.plugins,
180
- ...externalPackages !== void 0 ? { externalPackages } : {}
181
- }),
182
- root: rootDir,
183
- entrypoints: [filePath]
184
- };
185
199
  const buildResult = await this.dependencies.buildModule(buildOptions, options.buildExecutor);
186
200
  if (!buildResult.success) {
187
201
  const details = buildResult.logs.map((log) => log.message).join(" | ");
@@ -191,7 +205,6 @@ class PageModuleImportService {
191
205
  if (!compiledOutput) {
192
206
  throw new Error(noOutputMessage(filePath));
193
207
  }
194
- normalizeNodeRuntimeBuildOutputFile(compiledOutput, rootDir);
195
208
  const dependencyModulePaths = resolveRouteModuleDependencyPaths(buildResult, filePath, rootDir);
196
209
  const dependencyHashes = this.dependencyHasher.createDependencyHashes(dependencyModulePaths);
197
210
  dependencyHashes[path.normalize(filePath)] = fileHash;
@@ -202,8 +215,7 @@ class PageModuleImportService {
202
215
  }
203
216
  }
204
217
  routeModuleBuildCache.recordBuild({
205
- ...options,
206
- fileHash,
218
+ ...cacheBuildOptions,
207
219
  outputPath: compiledOutput,
208
220
  dependencyModulePaths
209
221
  });
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  isProductionCacheManifestCurrent,
16
16
  matchesProductionCacheFingerprint
17
- } from "../../build/production-build-cache.js";
17
+ } from "../../build/cache/production-build-cache.js";
18
18
  class RouteModuleBuildCache {
19
19
  manifestPath;
20
20
  dependencies;
@@ -1,8 +1,7 @@
1
- import type { EcoBuildPlugin } from '../../build/build-types.js';
2
1
  import type { PageModuleBuildImportOptions } from './page-module-import.service.js';
3
2
  import type { RouteModuleDependencyHashes } from './route-module-dependency-hasher.js';
4
- /** Filename written beside transpiled server modules that stores incremental build metadata. */
5
- export declare const ROUTE_MODULE_BUILD_CACHE_FILENAME = ".build-cache.json";
3
+ export { createJsxCacheKey, createPluginCacheKey, getCorePackageVersion, hashPluginSetup, } from '../../build/cache/cache-keys.js';
4
+ export { ROUTE_MODULE_BUILD_CACHE_FILENAME } from '../../build/cache/cache-constants.js';
6
5
  /** One persisted route-module build entry in {@link ROUTE_MODULE_BUILD_CACHE_FILENAME}. */
7
6
  export interface RouteModuleBuildCacheEntry {
8
7
  sourceHash: string;
@@ -37,8 +36,6 @@ export interface RouteModuleStaticRenderCacheContext {
37
36
  }
38
37
  export type RouteModuleBuildCacheManifestReader = (manifestPath: string) => RouteModuleBuildCacheManifest | undefined;
39
38
  export type RouteModuleBuildCacheManifestWriter = (manifestPath: string, manifest: RouteModuleBuildCacheManifest) => void;
40
- /** Returns the installed `@ecopages/core` package version used to invalidate persisted caches. */
41
- export declare function getCorePackageVersion(): string;
42
39
  /** Normalizes filesystem paths used as manifest keys and build-key inputs. */
43
40
  export declare function normalizeRouteModuleCachePath(filePath: string): string;
44
41
  /** Returns whether route-module disk caching should run for the current import. */
@@ -55,7 +52,3 @@ export declare function createPersistedRouteModuleBuildKey(options: PageModuleBu
55
52
  export declare function createEmptyRouteModuleBuildCacheManifest(): RouteModuleBuildCacheManifest;
56
53
  export declare function readRouteModuleBuildCacheManifest(manifestPath: string): RouteModuleBuildCacheManifest | undefined;
57
54
  export declare function writeRouteModuleBuildCacheManifest(manifestPath: string, manifest: RouteModuleBuildCacheManifest): void;
58
- export declare function createJsxCacheKey(jsx: PageModuleBuildImportOptions['jsx']): string;
59
- export declare function createPluginCacheKey(plugins?: EcoBuildPlugin[]): string;
60
- /** Exported for in-process import caches that must match persisted build keys. */
61
- export declare function hashPluginSetup(setup: EcoBuildPlugin['setup']): string;
@@ -1,17 +1,13 @@
1
- import { readFileSync } from "node:fs";
2
1
  import path from "node:path";
3
- import { readProductionCacheManifest, writeProductionCacheManifest } from "../../build/production-build-cache.js";
4
- const ROUTE_MODULE_BUILD_CACHE_FILENAME = ".build-cache.json";
5
- let cachedCorePackageVersion;
6
- function getCorePackageVersion() {
7
- if (cachedCorePackageVersion) {
8
- return cachedCorePackageVersion;
9
- }
10
- const packageJsonPath = new URL("../../../package.json", import.meta.url);
11
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
12
- cachedCorePackageVersion = packageJson.version ?? "0.0.0";
13
- return cachedCorePackageVersion;
14
- }
2
+ import { readProductionCacheManifest, writeProductionCacheManifest } from "../../build/cache/production-build-cache.js";
3
+ import { createJsxCacheKey, createPluginCacheKey, getCorePackageVersion } from "../../build/cache/cache-keys.js";
4
+ import {
5
+ createJsxCacheKey as createJsxCacheKey2,
6
+ createPluginCacheKey as createPluginCacheKey2,
7
+ getCorePackageVersion as getCorePackageVersion2,
8
+ hashPluginSetup
9
+ } from "../../build/cache/cache-keys.js";
10
+ import { ROUTE_MODULE_BUILD_CACHE_FILENAME } from "../../build/cache/cache-constants.js";
15
11
  function normalizeRouteModuleCachePath(filePath) {
16
12
  return path.resolve(filePath);
17
13
  }
@@ -73,40 +69,13 @@ function shouldVersionBuildOutputPath(invalidationVersion) {
73
69
  function sanitizeCacheScope(cacheScope) {
74
70
  return cacheScope.replace(/[^a-zA-Z0-9_-]+/g, "-");
75
71
  }
76
- function createJsxCacheKey(jsx) {
77
- if (!jsx) {
78
- return "jsx:default";
79
- }
80
- return JSON.stringify({
81
- development: jsx.development ?? false,
82
- factory: jsx.factory ?? null,
83
- fragment: jsx.fragment ?? null,
84
- importSource: jsx.importSource ?? null,
85
- runtime: jsx.runtime ?? null,
86
- sideEffects: jsx.sideEffects ?? null
87
- });
88
- }
89
- function createPluginCacheKey(plugins) {
90
- if (!plugins || plugins.length === 0) {
91
- return "plugins:default";
92
- }
93
- return `plugins:${plugins.map((plugin) => `${plugin.name}:${hashPluginSetup(plugin.setup)}`).join(",")}`;
94
- }
95
- function hashPluginSetup(setup) {
96
- let hash = 0;
97
- const source = setup.toString();
98
- for (let index = 0; index < source.length; index += 1) {
99
- hash = hash * 31 + source.charCodeAt(index) | 0;
100
- }
101
- return (hash >>> 0).toString(36);
102
- }
103
72
  export {
104
73
  ROUTE_MODULE_BUILD_CACHE_FILENAME,
105
74
  createEmptyRouteModuleBuildCacheManifest,
106
- createJsxCacheKey,
75
+ createJsxCacheKey2 as createJsxCacheKey,
107
76
  createPersistedRouteModuleBuildKey,
108
- createPluginCacheKey,
109
- getCorePackageVersion,
77
+ createPluginCacheKey2 as createPluginCacheKey,
78
+ getCorePackageVersion2 as getCorePackageVersion,
110
79
  hashPluginSetup,
111
80
  normalizeRouteModuleCachePath,
112
81
  readRouteModuleBuildCacheManifest,
@@ -1,5 +1,5 @@
1
1
  import type { BuildExecutor } from '../../build/build-adapter.js';
2
- import type { EcoBuildPlugin } from '../../build/build-types.js';
2
+ import type { EcoBuildPlugin } from '../../build/contracts/build-types.js';
3
3
  import type { AppModuleLoader } from './app-module-loader.service.js';
4
4
  import { type PageModuleBuildImportOptions } from './page-module-import.service.js';
5
5
  import type { SourceModuleLoaderFactory } from './module-loading-types.js';
@@ -33,7 +33,7 @@ It should not invent a parallel rendering stack just for build mode.
33
33
  | `static-export-context.ts` | Hook context type for `beforeStaticExport` / `afterStaticExport` |
34
34
  | `static-build-invalidation.ts` | `dist/` reset policy, production cache clearing, static-render cache context |
35
35
 
36
- Build-input fingerprinting (`hashAppConfigFile`, `createBuildInputsFingerprint`) lives in `packages/core/src/build/build-input-fingerprint.ts` and is shared with server-entry and unified-graph caches.
36
+ Build-input fingerprinting (`hashAppConfigFile`, `createBuildInputsFingerprint`) lives in `packages/core/src/build/cache/build-input-fingerprint.ts` and is shared with server-entry and unified-graph caches.
37
37
 
38
38
  ## Incremental static export
39
39