@ecopages/core 0.2.0-beta.2 → 0.2.0-beta.21

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 (273) hide show
  1. package/README.md +1 -1
  2. package/package.json +163 -3
  3. package/src/adapters/abstract/application-adapter.d.ts +104 -5
  4. package/src/adapters/abstract/application-adapter.js +125 -1
  5. package/src/adapters/abstract/server-adapter.d.ts +6 -2
  6. package/src/adapters/abstract/ws-pattern-matcher.d.ts +60 -0
  7. package/src/adapters/abstract/ws-pattern-matcher.js +61 -0
  8. package/src/adapters/bun/client-bridge.d.ts +1 -0
  9. package/src/adapters/bun/client-bridge.js +3 -0
  10. package/src/adapters/bun/create-app.d.ts +6 -4
  11. package/src/adapters/bun/create-app.js +65 -43
  12. package/src/adapters/bun/server-adapter.d.ts +90 -22
  13. package/src/adapters/bun/server-adapter.js +266 -84
  14. package/src/adapters/bun/static-preview-host.js +25 -20
  15. package/src/adapters/create-app.d.ts +13 -11
  16. package/src/adapters/create-app.js +2 -51
  17. package/src/adapters/index.d.ts +1 -1
  18. package/src/adapters/index.js +1 -2
  19. package/src/adapters/node/create-app.d.ts +5 -1
  20. package/src/adapters/node/create-app.js +51 -12
  21. package/src/adapters/node/node-client-bridge.d.ts +1 -0
  22. package/src/adapters/node/node-client-bridge.js +3 -0
  23. package/src/adapters/node/server-adapter-dependencies.js +4 -0
  24. package/src/adapters/node/server-adapter.d.ts +62 -20
  25. package/src/adapters/node/server-adapter.js +160 -131
  26. package/src/adapters/node/static-content-server.d.ts +1 -0
  27. package/src/adapters/node/static-content-server.js +10 -2
  28. package/src/adapters/node/static-preview-host.js +27 -12
  29. package/src/adapters/shared/bun-user-websocket-lifecycle.d.ts +22 -0
  30. package/src/adapters/shared/bun-user-websocket-lifecycle.js +96 -0
  31. package/src/adapters/shared/copy-runtime-public-dir.d.ts +6 -0
  32. package/src/adapters/shared/copy-runtime-public-dir.js +24 -0
  33. package/src/adapters/shared/fs-server-response-matcher.d.ts +2 -0
  34. package/src/adapters/shared/fs-server-response-matcher.js +40 -18
  35. package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +21 -30
  36. package/src/adapters/shared/hmr-entrypoint-registrar.js +49 -54
  37. package/src/adapters/shared/hmr-html-response.d.ts +1 -1
  38. package/src/adapters/shared/hmr-html-response.js +4 -1
  39. package/src/adapters/shared/node-http-websocket-upgrades.d.ts +21 -0
  40. package/src/adapters/shared/node-http-websocket-upgrades.js +100 -0
  41. package/src/adapters/shared/port-manager.d.ts +116 -0
  42. package/src/adapters/shared/port-manager.js +196 -0
  43. package/src/adapters/shared/runtime-app-bootstrap.d.ts +2 -1
  44. package/src/adapters/shared/runtime-app-bootstrap.js +3 -6
  45. package/src/adapters/shared/runtime-server-lifecycle.d.ts +46 -0
  46. package/src/adapters/shared/runtime-server-lifecycle.js +50 -0
  47. package/src/adapters/shared/server-adapter.d.ts +2 -1
  48. package/src/adapters/shared/server-adapter.js +13 -6
  49. package/src/adapters/shared/server-route-handler.d.ts +4 -1
  50. package/src/adapters/shared/server-route-handler.js +5 -2
  51. package/src/adapters/shared/server-static-builder.d.ts +23 -32
  52. package/src/adapters/shared/server-static-builder.js +100 -73
  53. package/src/adapters/shared/shared-hmr-manager.d.ts +45 -11
  54. package/src/adapters/shared/shared-hmr-manager.js +204 -58
  55. package/src/adapters/shared/static-preview-host.d.ts +5 -0
  56. package/src/adapters/shared/websocket-lifecycle.d.ts +24 -0
  57. package/src/adapters/shared/websocket-lifecycle.js +55 -0
  58. package/src/build/README.md +77 -14
  59. package/src/build/app-build-manifest-runtime.d.ts +9 -0
  60. package/src/build/app-build-manifest-runtime.js +87 -0
  61. package/src/build/build-adapter.d.ts +17 -319
  62. package/src/build/build-adapter.js +28 -94
  63. package/src/build/build-contracts.d.ts +97 -0
  64. package/src/build/build-contracts.js +0 -0
  65. package/src/build/build-input-fingerprint.d.ts +28 -0
  66. package/src/build/build-input-fingerprint.js +31 -0
  67. package/src/build/build-profile-options.d.ts +7 -0
  68. package/src/build/build-profile-options.js +37 -0
  69. package/src/build/build-runtime.d.ts +24 -0
  70. package/src/build/build-runtime.js +65 -0
  71. package/src/build/deduping-build-executor.d.ts +28 -0
  72. package/src/build/deduping-build-executor.js +56 -0
  73. package/src/build/jsx-ownership-plugins.d.ts +24 -0
  74. package/src/build/jsx-ownership-plugins.js +41 -0
  75. package/src/build/pages-unified-graph-build.d.ts +31 -0
  76. package/src/build/pages-unified-graph-build.js +206 -0
  77. package/src/build/parallel-build-executor.d.ts +21 -0
  78. package/src/build/parallel-build-executor.js +52 -0
  79. package/src/build/production-build-cache.d.ts +20 -0
  80. package/src/build/production-build-cache.js +63 -0
  81. package/src/build/rolldown-adapter-helpers.d.ts +3 -6
  82. package/src/build/rolldown-adapter-helpers.js +71 -6
  83. package/src/build/rolldown-build-adapter.d.ts +2 -6
  84. package/src/build/rolldown-build-adapter.js +3 -3
  85. package/src/build/rolldown-build-invocation-metrics.d.ts +12 -0
  86. package/src/build/rolldown-build-invocation-metrics.js +43 -0
  87. package/src/build/rolldown-plugin-bridge.d.ts +15 -1
  88. package/src/build/rolldown-plugin-bridge.js +20 -5
  89. package/src/build/rolldown-source-transform-pass.d.ts +15 -0
  90. package/src/build/rolldown-source-transform-pass.js +58 -0
  91. package/src/build/runtime-build-executor.d.ts +8 -15
  92. package/src/build/runtime-build-executor.js +12 -15
  93. package/src/build/runtime-build-output-normalizer.d.ts +7 -0
  94. package/src/build/runtime-build-output-normalizer.js +94 -2
  95. package/src/build/server-entry-build-cache.d.ts +44 -0
  96. package/src/build/server-entry-build-cache.js +161 -0
  97. package/src/client/navigation-scripts/classification.d.ts +16 -0
  98. package/src/client/navigation-scripts/classification.js +41 -0
  99. package/src/client/navigation-scripts/index.d.ts +3 -0
  100. package/src/client/navigation-scripts/index.js +23 -0
  101. package/src/client/navigation-scripts/navigation-scripts.test.browser.js +65 -0
  102. package/src/client/navigation-scripts/registry.d.ts +11 -0
  103. package/src/client/navigation-scripts/registry.js +12 -0
  104. package/src/client/navigation-scripts/rerun-queue.d.ts +37 -0
  105. package/src/client/navigation-scripts/rerun-queue.js +73 -0
  106. package/src/client/scroll.d.ts +17 -0
  107. package/src/client/scroll.js +25 -0
  108. package/src/client/scroll.test.browser.js +37 -0
  109. package/src/client/view-transitions.d.ts +16 -0
  110. package/src/client/view-transitions.js +63 -0
  111. package/src/config/config-builder.d.ts +12 -7
  112. package/src/config/config-builder.js +12 -9
  113. package/src/dev/client-bridge-registry.d.ts +5 -0
  114. package/src/dev/client-bridge-registry.js +15 -0
  115. package/src/dev/dev-client-ownership.d.ts +7 -0
  116. package/src/dev/dev-client-ownership.js +6 -0
  117. package/src/dev/hmr-manager-registry.d.ts +8 -0
  118. package/src/dev/hmr-manager-registry.js +15 -0
  119. package/src/dev/host-runtime.d.ts +3 -0
  120. package/src/dev/host-runtime.js +7 -0
  121. package/src/dev/runtime-server-started-message.d.ts +2 -0
  122. package/src/dev/runtime-server-started-message.js +6 -0
  123. package/src/eco/README.md +11 -0
  124. package/src/eco/eco-declared-component.d.ts +14 -0
  125. package/src/eco/eco-declared-component.js +16 -0
  126. package/src/eco/eco.browser.js +5 -6
  127. package/src/eco/eco.js +5 -6
  128. package/src/eco/eco.types.d.ts +2 -2
  129. package/src/eco/page-layout-normalization.d.ts +21 -0
  130. package/src/eco/page-layout-normalization.js +59 -0
  131. package/src/errors/index.d.ts +1 -0
  132. package/src/errors/index.js +7 -1
  133. package/src/errors/undeclared-component-dependency-error.d.ts +11 -0
  134. package/src/errors/undeclared-component-dependency-error.js +17 -0
  135. package/src/hmr/client/hmr-runtime.js +5 -2
  136. package/src/hmr/hmr-entrypoint-output.d.ts +43 -0
  137. package/src/hmr/hmr-entrypoint-output.js +53 -0
  138. package/src/hmr/hmr-strategy.d.ts +15 -0
  139. package/src/hmr/hmr-strategy.js +19 -0
  140. package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -5
  141. package/src/hmr/strategies/js-hmr-strategy.js +67 -19
  142. package/src/hmr/strategies/server-rendered-template-hmr-strategy.d.ts +17 -0
  143. package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +29 -0
  144. package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -6
  145. package/src/integrations/ghtml/ghtml-renderer.js +2 -51
  146. package/src/integrations/ghtml/ghtml.plugin.d.ts +3 -16
  147. package/src/integrations/ghtml/ghtml.plugin.js +7 -14
  148. package/src/plugins/define-integration.d.ts +26 -0
  149. package/src/plugins/define-integration.js +19 -0
  150. package/src/plugins/eco-component-meta-plugin.js +5 -8
  151. package/src/plugins/foreign-jsx-override-plugin.js +4 -6
  152. package/src/plugins/integration-plugin.d.ts +19 -9
  153. package/src/plugins/integration-plugin.js +7 -4
  154. package/src/plugins/jsx-import-source.utils.d.ts +8 -0
  155. package/src/plugins/jsx-import-source.utils.js +26 -0
  156. package/src/plugins/processor.d.ts +19 -4
  157. package/src/plugins/processor.js +22 -4
  158. package/src/plugins/source-transform.d.ts +31 -0
  159. package/src/plugins/source-transform.js +23 -1
  160. package/src/route-renderer/GRAPH.md +8 -8
  161. package/src/route-renderer/README.md +30 -28
  162. package/src/route-renderer/orchestration/component-graph-collectors.d.ts +10 -0
  163. package/src/route-renderer/orchestration/component-graph-collectors.js +143 -0
  164. package/src/route-renderer/orchestration/component-graph.d.ts +36 -0
  165. package/src/route-renderer/orchestration/component-graph.js +98 -0
  166. package/src/route-renderer/orchestration/component-render-context.d.ts +3 -10
  167. package/src/route-renderer/orchestration/component-render-context.js +3 -1
  168. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +1 -18
  169. package/src/route-renderer/orchestration/declared-ownership-graph.js +5 -31
  170. package/src/route-renderer/orchestration/document-shell-render.service.d.ts +90 -0
  171. package/src/route-renderer/orchestration/document-shell-render.service.js +120 -0
  172. package/src/route-renderer/orchestration/foreign-subtree-execution.service.d.ts +59 -29
  173. package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +164 -35
  174. package/src/route-renderer/orchestration/global-injector-assets.service.d.ts +7 -0
  175. package/src/route-renderer/orchestration/global-injector-assets.service.js +32 -0
  176. package/src/route-renderer/orchestration/integration-renderer.d.ts +18 -54
  177. package/src/route-renderer/orchestration/integration-renderer.js +113 -195
  178. package/src/route-renderer/orchestration/integration-route-render-adapter.d.ts +38 -0
  179. package/src/route-renderer/orchestration/integration-route-render-adapter.js +27 -0
  180. package/src/route-renderer/orchestration/layout-shell-props.service.d.ts +20 -0
  181. package/src/route-renderer/orchestration/layout-shell-props.service.js +31 -0
  182. package/src/route-renderer/orchestration/ownership-validation.service.d.ts +5 -0
  183. package/src/route-renderer/orchestration/ownership-validation.service.js +29 -1
  184. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.d.ts +9 -0
  185. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.js +7 -0
  186. package/src/route-renderer/orchestration/page-browser-graph.service.d.ts +25 -0
  187. package/src/route-renderer/orchestration/page-browser-graph.service.js +174 -0
  188. package/src/route-renderer/orchestration/render-output.utils.d.ts +2 -0
  189. package/src/route-renderer/orchestration/render-output.utils.js +4 -0
  190. package/src/route-renderer/orchestration/route-html-finalization.service.d.ts +17 -0
  191. package/src/route-renderer/orchestration/route-html-finalization.service.js +26 -0
  192. package/src/route-renderer/orchestration/route-prepared-options.builder.d.ts +26 -0
  193. package/src/route-renderer/orchestration/route-prepared-options.builder.js +54 -0
  194. package/src/route-renderer/orchestration/route-prepared-options.utils.d.ts +4 -0
  195. package/src/route-renderer/orchestration/route-prepared-options.utils.js +33 -0
  196. package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +8 -39
  197. package/src/route-renderer/orchestration/route-render-orchestrator.js +53 -461
  198. package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
  199. package/src/route-renderer/orchestration/string-markup-renderer.js +55 -0
  200. package/src/route-renderer/page-loading/component-dependency-collection.js +5 -2
  201. package/src/router/client/link-intent.d.ts +11 -21
  202. package/src/router/client/link-intent.js +10 -0
  203. package/src/router/client/link-intent.test.browser.js +12 -1
  204. package/src/router/client/link-navigation-policy.d.ts +45 -0
  205. package/src/router/client/link-navigation-policy.js +101 -0
  206. package/src/router/client/link-navigation-policy.test.browser.d.ts +1 -0
  207. package/src/router/client/link-navigation-policy.test.browser.js +92 -0
  208. package/src/router/client/navigation-coordinator.d.ts +1 -1
  209. package/src/router/client/navigation-coordinator.js +12 -2
  210. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -0
  211. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
  212. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
  213. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +27 -7
  214. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.d.ts +0 -1
  215. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +18 -15
  216. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
  217. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -3
  218. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -31
  219. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -3
  220. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +2 -30
  221. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.d.ts +2 -0
  222. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +43 -0
  223. package/src/services/assets/browser-bundle.service.d.ts +3 -1
  224. package/src/services/assets/browser-bundle.service.js +17 -5
  225. package/src/services/html/html-transformer.service.d.ts +1 -1
  226. package/src/services/html/html-transformer.service.js +4 -4
  227. package/src/services/invalidation/development-invalidation.service.d.ts +20 -2
  228. package/src/services/invalidation/development-invalidation.service.js +56 -2
  229. package/src/services/module-loading/README.md +49 -0
  230. package/src/services/module-loading/app-server-module-transpiler.service.js +5 -17
  231. package/src/services/module-loading/page-module-import.service.d.ts +5 -1
  232. package/src/services/module-loading/page-module-import.service.js +96 -45
  233. package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
  234. package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
  235. package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
  236. package/src/services/module-loading/route-module-build-cache.js +38 -0
  237. package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
  238. package/src/services/module-loading/route-module-build-cache.store.js +207 -0
  239. package/src/services/module-loading/route-module-build-manifest.d.ts +61 -0
  240. package/src/services/module-loading/route-module-build-manifest.js +116 -0
  241. package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
  242. package/src/services/module-loading/route-module-dependency-hasher.js +122 -0
  243. package/src/services/module-loading/server-module-transpiler.service.js +1 -1
  244. package/src/static-site-generator/README.md +33 -0
  245. package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
  246. package/src/static-site-generator/static-build-invalidation.js +59 -0
  247. package/src/static-site-generator/static-export-context.d.ts +22 -0
  248. package/src/static-site-generator/static-export-context.js +0 -0
  249. package/src/static-site-generator/static-site-generator.d.ts +17 -20
  250. package/src/static-site-generator/static-site-generator.js +188 -85
  251. package/src/types/internal-types.d.ts +16 -9
  252. package/src/types/public-types.d.ts +144 -40
  253. package/src/utils/parse-cli-args.d.ts +2 -0
  254. package/src/utils/parse-cli-args.js +6 -0
  255. package/src/utils/server-utils.module.d.ts +3 -2
  256. package/src/utils/server-utils.module.js +5 -6
  257. package/src/utils/static-file-extensions.d.ts +12 -0
  258. package/src/utils/static-file-extensions.js +48 -0
  259. package/src/watchers/project-watcher-ignore.d.ts +11 -0
  260. package/src/watchers/project-watcher-ignore.js +16 -0
  261. package/src/watchers/project-watcher.d.ts +26 -3
  262. package/src/watchers/project-watcher.js +132 -30
  263. package/src/watchers/project-watcher.test-helpers.js +5 -5
  264. package/src/build/rolldown-dev-build-adapter.d.ts +0 -82
  265. package/src/build/rolldown-dev-build-adapter.js +0 -166
  266. package/src/hmr/hmr.postcss.test.e2e.js +0 -31
  267. package/src/hmr/hmr.test.e2e.js +0 -43
  268. package/src/route-renderer/orchestration/ownership-planning.service.d.ts +0 -24
  269. package/src/route-renderer/orchestration/ownership-planning.service.js +0 -63
  270. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +0 -91
  271. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.js +0 -170
  272. /package/src/{hmr/hmr.postcss.test.e2e.d.ts → client/navigation-scripts/navigation-scripts.test.browser.d.ts} +0 -0
  273. /package/src/{hmr/hmr.test.e2e.d.ts → client/scroll.test.browser.d.ts} +0 -0
@@ -0,0 +1,206 @@
1
+ import path from "node:path";
2
+ import { pathToFileURL } from "node:url";
3
+ import { fileSystem } from "@ecopages/file-system";
4
+ import { appLogger } from "../global/app-logger.js";
5
+ import { build, getAppServerBuildPlugins } from "./build-adapter.js";
6
+ import { requireBuildRuntime } from "./build-runtime.js";
7
+ import { resolveBuildProfileOptions } from "./build-profile-options.js";
8
+ import { createBuildInputsFingerprint, hashAppConfigFile } from "./build-input-fingerprint.js";
9
+ import {
10
+ isProductionCacheManifestCurrent,
11
+ matchesProductionCacheBuildKey,
12
+ matchesProductionCacheFingerprint,
13
+ readProductionCacheManifest,
14
+ writeProductionCacheManifest
15
+ } from "./production-build-cache.js";
16
+ import { getCorePackageVersion } from "../services/module-loading/route-module-build-manifest.js";
17
+ import { resolveInternalExecutionDir } from "../utils/resolve-work-dir.js";
18
+ import { getSharedRouteModuleBuildCache } from "../services/module-loading/route-module-build-cache-registry.js";
19
+ import { normalizeNodeRuntimeBuildOutputFile } from "./runtime-build-output-normalizer.js";
20
+ import { resolveRouteModuleDependencyPaths } from "../services/module-loading/route-module-dependency-hasher.js";
21
+ import { getJsxOwnershipPlugins } from "./jsx-ownership-plugins.js";
22
+ const PAGES_UNIFIED_GRAPH_CACHE_DIR = ".server-pages-graph";
23
+ const PAGES_UNIFIED_GRAPH_CACHE_FILENAME = ".build-cache.json";
24
+ function isPagesUnifiedGraphEnabled() {
25
+ if (process.env.ECOPAGES_UNIFIED_PAGES_GRAPH === "0") {
26
+ return false;
27
+ }
28
+ if (process.env.ECOPAGES_UNIFIED_PAGES_GRAPH === "1") {
29
+ return true;
30
+ }
31
+ return process.env.NODE_ENV === "production";
32
+ }
33
+ function shouldBuildPagesUnifiedGraph() {
34
+ return isPagesUnifiedGraphEnabled() && process.env.NODE_ENV === "production";
35
+ }
36
+ function isPagesUnifiedGraphPage(filePath, appConfig) {
37
+ const normalizedPath = path.normalize(filePath);
38
+ return appConfig.templatesExt.some((extension) => normalizedPath.endsWith(extension));
39
+ }
40
+ function getPagesUnifiedGraphCachePath(appConfig) {
41
+ return path.join(
42
+ resolveInternalExecutionDir(appConfig),
43
+ PAGES_UNIFIED_GRAPH_CACHE_DIR,
44
+ PAGES_UNIFIED_GRAPH_CACHE_FILENAME
45
+ );
46
+ }
47
+ function createPagesUnifiedGraphBuildKey(appConfig, outdir) {
48
+ const plugins = appConfig.runtime?.buildManifest ? getAppServerBuildPlugins(appConfig) : [];
49
+ const pluginNames = [...plugins, ...getJsxOwnershipPlugins(appConfig)].map((plugin) => plugin.name).sort().join("|");
50
+ const templateExtensions = [...appConfig.templatesExt].sort().join("|");
51
+ return [
52
+ path.resolve(outdir),
53
+ hashAppConfigFile(appConfig),
54
+ templateExtensions,
55
+ pluginNames,
56
+ "es2022",
57
+ "esm",
58
+ "external-packages"
59
+ ].join("::");
60
+ }
61
+ function readPagesUnifiedGraphManifest(appConfig) {
62
+ const manifest = readProductionCacheManifest(
63
+ getPagesUnifiedGraphCachePath(appConfig)
64
+ );
65
+ if (!manifest?.outputs) {
66
+ return void 0;
67
+ }
68
+ return manifest;
69
+ }
70
+ function writePagesUnifiedGraphManifest(appConfig, manifest) {
71
+ writeProductionCacheManifest(getPagesUnifiedGraphCachePath(appConfig), manifest);
72
+ }
73
+ function createSafeGraphEntryKey(entryPath, rootDir) {
74
+ const relativePath = path.relative(rootDir, entryPath).replace(/\.[^.]+$/u, "");
75
+ const safeKey = relativePath.replace(/[^a-zA-Z0-9]+/gu, "-").replace(/^-+|-+$/gu, "");
76
+ return safeKey.length > 0 ? safeKey : "page";
77
+ }
78
+ function resolveOutputForEntrypoint(entryPath, entryKey, buildResult) {
79
+ const exactOutput = buildResult.entryOutputs?.[path.resolve(entryPath)];
80
+ if (exactOutput) {
81
+ return exactOutput;
82
+ }
83
+ for (const { path: outputPath } of buildResult.outputs) {
84
+ const outputBaseName = path.basename(outputPath);
85
+ if (outputBaseName.startsWith(`${entryKey}-`) && /\.(?:m?js)$/u.test(outputBaseName)) {
86
+ return outputPath;
87
+ }
88
+ if (outputBaseName === `${entryKey}.js` || outputBaseName === `${entryKey}.mjs`) {
89
+ return outputPath;
90
+ }
91
+ }
92
+ return void 0;
93
+ }
94
+ function isManifestValidForEntries(manifest, appConfig, outdir, entryPaths) {
95
+ if (!isProductionCacheManifestCurrent(manifest, getCorePackageVersion())) {
96
+ return false;
97
+ }
98
+ if (!matchesProductionCacheFingerprint(manifest, createBuildInputsFingerprint(appConfig))) {
99
+ return false;
100
+ }
101
+ if (!matchesProductionCacheBuildKey(manifest, createPagesUnifiedGraphBuildKey(appConfig, outdir))) {
102
+ return false;
103
+ }
104
+ return entryPaths.every((entryPath) => {
105
+ const resolvedEntryPath = path.resolve(entryPath);
106
+ const outputPath = manifest.outputs[resolvedEntryPath];
107
+ return outputPath ? fileSystem.exists(outputPath) : false;
108
+ });
109
+ }
110
+ async function ensurePagesUnifiedGraphBuilt(options) {
111
+ if (!shouldBuildPagesUnifiedGraph()) {
112
+ return void 0;
113
+ }
114
+ const eligibleEntryPaths = options.entryPaths.map((entryPath) => path.resolve(entryPath)).filter((entryPath) => isPagesUnifiedGraphPage(entryPath, options.appConfig));
115
+ if (eligibleEntryPaths.length === 0) {
116
+ return void 0;
117
+ }
118
+ const outdir = path.resolve(options.outdir);
119
+ const existingManifest = options.force ? void 0 : readPagesUnifiedGraphManifest(options.appConfig);
120
+ if (existingManifest && isManifestValidForEntries(existingManifest, options.appConfig, outdir, eligibleEntryPaths)) {
121
+ appLogger.debug("Reusing pages unified graph cache");
122
+ return existingManifest;
123
+ }
124
+ const plugins = options.appConfig.runtime?.buildManifest ? getAppServerBuildPlugins(options.appConfig) : [];
125
+ const mergedPlugins = [...plugins, ...getJsxOwnershipPlugins(options.appConfig)];
126
+ const routeModuleBuildCache = getSharedRouteModuleBuildCache(outdir, options.appConfig);
127
+ const entryRecord = {};
128
+ const entryKeysByPath = /* @__PURE__ */ new Map();
129
+ for (const entryPath of eligibleEntryPaths) {
130
+ const entryKey = createSafeGraphEntryKey(entryPath, options.appConfig.rootDir);
131
+ entryRecord[entryKey] = entryPath;
132
+ entryKeysByPath.set(entryPath, entryKey);
133
+ }
134
+ appLogger.debugTime("pagesUnifiedGraphBuild");
135
+ const buildOptions = {
136
+ ...resolveBuildProfileOptions("route-module", options.appConfig, {
137
+ entrypoints: entryRecord,
138
+ outdir,
139
+ splitting: true,
140
+ naming: "[name]-[hash].[ext]",
141
+ plugins: mergedPlugins.length > 0 ? mergedPlugins : void 0
142
+ }),
143
+ entrypoints: entryRecord
144
+ };
145
+ const buildResult = await build(buildOptions, requireBuildRuntime(options.appConfig).getProfile("route-module"));
146
+ appLogger.debugTimeEnd("pagesUnifiedGraphBuild");
147
+ if (!buildResult.success) {
148
+ const details = buildResult.logs.map((log) => log.message).join(" | ");
149
+ throw new Error(`Pages unified graph build failed: ${details}`);
150
+ }
151
+ const outputs = {};
152
+ for (const entryPath of eligibleEntryPaths) {
153
+ const fileHash = fileSystem.hash(entryPath);
154
+ const entryKey = entryKeysByPath.get(entryPath);
155
+ const compiledOutput = entryKey ? resolveOutputForEntrypoint(entryPath, entryKey, buildResult) : void 0;
156
+ if (!compiledOutput) {
157
+ throw new Error(`Pages unified graph build produced no output for ${entryPath}`);
158
+ }
159
+ normalizeNodeRuntimeBuildOutputFile(compiledOutput, options.appConfig.rootDir);
160
+ outputs[entryPath] = compiledOutput;
161
+ routeModuleBuildCache.recordBuild({
162
+ filePath: entryPath,
163
+ rootDir: options.appConfig.rootDir,
164
+ outdir,
165
+ fileHash,
166
+ outputPath: compiledOutput,
167
+ dependencyModulePaths: resolveRouteModuleDependencyPaths(buildResult, entryPath, options.appConfig.rootDir),
168
+ externalPackages: true,
169
+ plugins: mergedPlugins
170
+ });
171
+ }
172
+ const manifest = {
173
+ invalidationVersion: getCorePackageVersion(),
174
+ buildInputsFingerprint: createBuildInputsFingerprint(options.appConfig),
175
+ buildKey: createPagesUnifiedGraphBuildKey(options.appConfig, outdir),
176
+ builtAt: Date.now(),
177
+ outputs
178
+ };
179
+ writePagesUnifiedGraphManifest(options.appConfig, manifest);
180
+ appLogger.debug(`Built pages unified graph for ${eligibleEntryPaths.length} entries`);
181
+ return manifest;
182
+ }
183
+ async function importPagesUnifiedGraphModule(appConfig, filePath) {
184
+ const manifest = readPagesUnifiedGraphManifest(appConfig);
185
+ if (!manifest) {
186
+ return void 0;
187
+ }
188
+ const resolvedFilePath = path.resolve(filePath);
189
+ const outputPath = manifest.outputs[resolvedFilePath];
190
+ if (!outputPath || !fileSystem.exists(outputPath)) {
191
+ return void 0;
192
+ }
193
+ return await import(
194
+ /* @vite-ignore */
195
+ pathToFileURL(outputPath).href
196
+ );
197
+ }
198
+ export {
199
+ PAGES_UNIFIED_GRAPH_CACHE_DIR,
200
+ PAGES_UNIFIED_GRAPH_CACHE_FILENAME,
201
+ ensurePagesUnifiedGraphBuilt,
202
+ importPagesUnifiedGraphModule,
203
+ isPagesUnifiedGraphEnabled,
204
+ isPagesUnifiedGraphPage,
205
+ shouldBuildPagesUnifiedGraph
206
+ };
@@ -0,0 +1,21 @@
1
+ import type { BuildExecutor, BuildOptions, BuildResult } from './build-adapter.js';
2
+ /**
3
+ * Concurrency-limited build executor wrapper.
4
+ *
5
+ * @remarks
6
+ * Runs up to `limit` builds concurrently. Use for independent route-module
7
+ * and HMR browser builds where FIFO serialization is unnecessary.
8
+ */
9
+ export declare class ParallelBuildExecutor implements BuildExecutor {
10
+ private readonly inner;
11
+ private readonly limit;
12
+ private activeCount;
13
+ private queue;
14
+ constructor(inner: BuildExecutor, limit: number);
15
+ build(options: BuildOptions): Promise<BuildResult>;
16
+ private drainQueue;
17
+ unwrap(): BuildExecutor;
18
+ getConcurrencyLimitForTests(): number;
19
+ getActiveCountForTests(): number;
20
+ getQueuedCountForTests(): number;
21
+ }
@@ -0,0 +1,52 @@
1
+ class ParallelBuildExecutor {
2
+ inner;
3
+ limit;
4
+ activeCount = 0;
5
+ queue = [];
6
+ constructor(inner, limit) {
7
+ this.inner = inner;
8
+ this.limit = Math.max(1, limit);
9
+ }
10
+ build(options) {
11
+ return new Promise((resolve, reject) => {
12
+ this.queue.push({
13
+ operation: () => this.inner.build(options),
14
+ resolve,
15
+ reject
16
+ });
17
+ this.drainQueue();
18
+ });
19
+ }
20
+ drainQueue() {
21
+ while (this.activeCount < this.limit && this.queue.length > 0) {
22
+ const next = this.queue.shift();
23
+ if (!next) {
24
+ return;
25
+ }
26
+ this.activeCount += 1;
27
+ void next.operation().then((result) => {
28
+ next.resolve(result);
29
+ }).catch((error) => {
30
+ next.reject(error);
31
+ }).finally(() => {
32
+ this.activeCount -= 1;
33
+ this.drainQueue();
34
+ });
35
+ }
36
+ }
37
+ unwrap() {
38
+ return this.inner;
39
+ }
40
+ getConcurrencyLimitForTests() {
41
+ return this.limit;
42
+ }
43
+ getActiveCountForTests() {
44
+ return this.activeCount;
45
+ }
46
+ getQueuedCountForTests() {
47
+ return this.queue.length;
48
+ }
49
+ }
50
+ export {
51
+ ParallelBuildExecutor
52
+ };
@@ -0,0 +1,20 @@
1
+ import type { EcoPagesAppConfig } from '../types/internal-types.js';
2
+ /**
3
+ * Shared manifest fields for persisted production build caches.
4
+ */
5
+ export interface ProductionCacheManifestBase {
6
+ invalidationVersion: string;
7
+ buildInputsFingerprint?: string;
8
+ buildKey?: string;
9
+ builtAt?: number;
10
+ }
11
+ export type ProductionBuildCacheKind = 'server-entry' | 'route-module' | 'pages-graph';
12
+ /** Returns every persisted production cache manifest path for one app. */
13
+ export declare function getProductionBuildCacheManifestPaths(appConfig: EcoPagesAppConfig): string[];
14
+ /** Removes all persisted production cache manifests for one app. */
15
+ export declare function clearPersistedProductionBuildCacheManifests(appConfig: EcoPagesAppConfig): void;
16
+ export declare function readProductionCacheManifest<T extends ProductionCacheManifestBase>(manifestPath: string): T | undefined;
17
+ export declare function writeProductionCacheManifest(manifestPath: string, manifest: unknown): void;
18
+ export declare function isProductionCacheManifestCurrent(manifest: ProductionCacheManifestBase | undefined, invalidationVersion: string): boolean;
19
+ export declare function matchesProductionCacheFingerprint(manifest: ProductionCacheManifestBase | undefined, buildInputsFingerprint: string): boolean;
20
+ export declare function matchesProductionCacheBuildKey(manifest: ProductionCacheManifestBase | undefined, buildKey: string): boolean;
@@ -0,0 +1,63 @@
1
+ import { fileSystem } from "@ecopages/file-system";
2
+ import path from "node:path";
3
+ import { ROUTE_MODULE_BUILD_CACHE_FILENAME } from "../services/module-loading/route-module-build-manifest.js";
4
+ import { resolveInternalExecutionDir } from "../utils/resolve-work-dir.js";
5
+ const ROUTE_MODULE_CACHE_OUTDIRS = [".server-modules", ".server-route-modules"];
6
+ const PAGES_GRAPH_CACHE_DIR = ".server-pages-graph";
7
+ function getProductionBuildCacheManifestPaths(appConfig) {
8
+ const executionDir = resolveInternalExecutionDir(appConfig);
9
+ const paths = [];
10
+ for (const subdir of ROUTE_MODULE_CACHE_OUTDIRS) {
11
+ paths.push(path.join(executionDir, subdir, ROUTE_MODULE_BUILD_CACHE_FILENAME));
12
+ }
13
+ paths.push(path.join(executionDir, ".server-entry", ROUTE_MODULE_BUILD_CACHE_FILENAME));
14
+ paths.push(path.join(executionDir, PAGES_GRAPH_CACHE_DIR, ROUTE_MODULE_BUILD_CACHE_FILENAME));
15
+ return paths;
16
+ }
17
+ function clearPersistedProductionBuildCacheManifests(appConfig) {
18
+ if (process.env.NODE_ENV !== "production") {
19
+ return;
20
+ }
21
+ for (const manifestPath of getProductionBuildCacheManifestPaths(appConfig)) {
22
+ if (fileSystem.exists(manifestPath)) {
23
+ fileSystem.remove(manifestPath);
24
+ }
25
+ }
26
+ }
27
+ function readProductionCacheManifest(manifestPath) {
28
+ if (!fileSystem.exists(manifestPath)) {
29
+ return void 0;
30
+ }
31
+ try {
32
+ const parsed = JSON.parse(fileSystem.readFileSync(manifestPath));
33
+ if (!parsed || typeof parsed !== "object") {
34
+ return void 0;
35
+ }
36
+ return parsed;
37
+ } catch {
38
+ return void 0;
39
+ }
40
+ }
41
+ function writeProductionCacheManifest(manifestPath, manifest) {
42
+ fileSystem.ensureDir(path.dirname(manifestPath));
43
+ fileSystem.write(manifestPath, `${JSON.stringify(manifest, null, " ")}
44
+ `);
45
+ }
46
+ function isProductionCacheManifestCurrent(manifest, invalidationVersion) {
47
+ return manifest?.invalidationVersion === invalidationVersion;
48
+ }
49
+ function matchesProductionCacheFingerprint(manifest, buildInputsFingerprint) {
50
+ return manifest?.buildInputsFingerprint === buildInputsFingerprint;
51
+ }
52
+ function matchesProductionCacheBuildKey(manifest, buildKey) {
53
+ return manifest?.buildKey === buildKey;
54
+ }
55
+ export {
56
+ clearPersistedProductionBuildCacheManifests,
57
+ getProductionBuildCacheManifestPaths,
58
+ isProductionCacheManifestCurrent,
59
+ matchesProductionCacheBuildKey,
60
+ matchesProductionCacheFingerprint,
61
+ readProductionCacheManifest,
62
+ writeProductionCacheManifest
63
+ };
@@ -2,12 +2,9 @@
2
2
  * Shared helpers for the Rolldown-backed build adapters.
3
3
  *
4
4
  * @remarks
5
- * The standard {@link RolldownBuildAdapter} (one-shot production builds)
6
- * and the dev {@link RolldownDevBuildAdapter} (DevEngine-backed
7
- * incremental rebuilds) both need the same BuildOptions → Rolldown
8
- * mapping, the same dependency-graph extraction, and the same
9
- * post-build rewriting pipeline. This module hosts the shared code so
10
- * the two adapters stay semantically identical.
5
+ * The standard {@link RolldownBuildAdapter} uses these helpers for
6
+ * BuildOptions Rolldown mapping, dependency-graph extraction, and the
7
+ * post-build rewriting pipeline.
11
8
  *
12
9
  * @module
13
10
  */
@@ -1,10 +1,41 @@
1
1
  import { createRequire } from "node:module";
2
+ import { readFileSync } from "node:fs";
2
3
  import path from "node:path";
3
4
  import { collectBrowserRuntimeImportRewriteMap, rewriteBrowserRuntimeImports } from "./browser-runtime-plugin.js";
4
5
  import { createServerSideCssShimPlugin } from "./server-side-css-shim-plugin.js";
5
6
  import { createRolldownPluginBridge } from "./rolldown-plugin-bridge.js";
6
- import { isDeclaredAppPackageImport, normalizeNodeRuntimeBuildOutputs } from "./runtime-build-output-normalizer.js";
7
+ import {
8
+ isDeclaredAppPackageImport,
9
+ isWorkspacePackageImport,
10
+ normalizeNodeRuntimeBuildOutputs
11
+ } from "./runtime-build-output-normalizer.js";
7
12
  const corePackageRequire = createRequire(new URL("../../package.json", import.meta.url));
13
+ let corePackageNames;
14
+ function getCorePackageNames() {
15
+ if (corePackageNames) {
16
+ return corePackageNames;
17
+ }
18
+ const packageJsonPath = new URL("../../package.json", import.meta.url);
19
+ corePackageNames = /* @__PURE__ */ new Set();
20
+ try {
21
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
22
+ for (const field of ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]) {
23
+ const entries = packageJson[field];
24
+ if (!entries || typeof entries !== "object") {
25
+ continue;
26
+ }
27
+ for (const name of Object.keys(entries)) {
28
+ corePackageNames.add(name);
29
+ }
30
+ }
31
+ } catch {
32
+ }
33
+ return corePackageNames;
34
+ }
35
+ function isCoreDeclaredPackageImport(specifier) {
36
+ const name = specifier.startsWith("@") ? specifier.split("/").slice(0, 2).join("/") : specifier.split("/")[0] ?? specifier;
37
+ return getCorePackageNames().has(name);
38
+ }
8
39
  function transpileProfileToOptions(profile) {
9
40
  switch (profile) {
10
41
  case "browser-script":
@@ -37,13 +68,21 @@ function getAppRootRequire(cache, contextRoot) {
37
68
  return req;
38
69
  }
39
70
  function shouldBundlePackageImport(id, contextRoot, appRootRequireCache) {
71
+ if (isWorkspacePackageImport(id, contextRoot)) {
72
+ return true;
73
+ }
40
74
  if (isDeclaredAppPackageImport(id, contextRoot)) {
41
75
  const appRootRequire = getAppRootRequire(appRootRequireCache, contextRoot);
42
76
  const appResolvedPath = tryResolveModule(id, appRootRequire);
43
77
  return Boolean(appResolvedPath && /\.(?:[cm]?ts|tsx|jsx)$/u.test(appResolvedPath));
44
78
  }
45
- const coreResolvedPath = tryResolveModule(id, corePackageRequire);
46
- return Boolean(coreResolvedPath && /\.(?:[cm]?ts|tsx|jsx)$/u.test(coreResolvedPath));
79
+ if (isCoreDeclaredPackageImport(id)) {
80
+ const coreResolvedPath = tryResolveModule(id, corePackageRequire);
81
+ if (coreResolvedPath && !/\.(?:[cm]?ts|tsx|jsx)$/u.test(coreResolvedPath)) {
82
+ return false;
83
+ }
84
+ }
85
+ return true;
47
86
  }
48
87
  function createExternalMatcher(options, appRootRequireCache) {
49
88
  const explicitExternals = new Set(options.external ?? []);
@@ -162,7 +201,8 @@ function resolveRolldownOptions(options, contextRoot, outdir, appRootRequireCach
162
201
  transformOptions.target = options.target;
163
202
  }
164
203
  const bundlePlugins = options.plugins ?? [];
165
- const appPlugins = createRolldownPluginBridge(bundlePlugins, contextRoot);
204
+ const sourceTransforms = options.target === "browser" ? options.sourceTransforms ?? [] : [];
205
+ const appPlugins = createRolldownPluginBridge(bundlePlugins, contextRoot, sourceTransforms);
166
206
  const allPlugins = [...options.target !== "browser" ? [createServerSideCssShimPlugin()] : [], ...appPlugins];
167
207
  const inputOptions = {
168
208
  input: options.entrypoints,
@@ -172,6 +212,11 @@ function resolveRolldownOptions(options, contextRoot, outdir, appRootRequireCach
172
212
  transform: Object.keys(transformOptions).length > 0 ? transformOptions : void 0,
173
213
  resolve: options.conditions ? { conditionNames: options.conditions } : void 0,
174
214
  treeshake: typeof options.treeshaking === "boolean" ? options.treeshaking : true,
215
+ ...process.env.ECOPAGES_PROFILE_BUILD === "1" ? {} : {
216
+ checks: {
217
+ pluginTimings: false
218
+ }
219
+ },
175
220
  experimental: {
176
221
  nativeMagicString: true
177
222
  },
@@ -215,11 +260,21 @@ function rewriteBrowserRuntimeImportsInOutputs(result, contextRoot, plugins) {
215
260
  if (rewritten !== code) {
216
261
  fs.writeFileSync(output.path, rewritten);
217
262
  }
218
- rewriteCache.add(contentKey);
263
+ rememberRewrite(contentKey);
219
264
  }
220
265
  return result;
221
266
  }
267
+ const REWRITE_CACHE_MAX_ENTRIES = 2048;
222
268
  const rewriteCache = /* @__PURE__ */ new Set();
269
+ function rememberRewrite(contentKey) {
270
+ rewriteCache.add(contentKey);
271
+ if (rewriteCache.size > REWRITE_CACHE_MAX_ENTRIES) {
272
+ const oldest = rewriteCache.values().next().value;
273
+ if (oldest !== void 0) {
274
+ rewriteCache.delete(oldest);
275
+ }
276
+ }
277
+ }
223
278
  function djb2(input) {
224
279
  let hash = 5381;
225
280
  for (let i = 0; i < input.length; i++) {
@@ -246,11 +301,21 @@ function buildResultFromRolldownOutput(output, outdir, contextRoot) {
246
301
  }));
247
302
  const entryChunks = output.output.filter((entry) => entry.type === "chunk" && entry.isEntry);
248
303
  const dependencyGraph = entryChunks.length > 0 ? extractDependencyGraph(entryChunks, contextRoot) : void 0;
304
+ const entryOutputs = {};
305
+ for (const chunk of entryChunks) {
306
+ if (chunk.facadeModuleId) {
307
+ entryOutputs[normalizeModulePath(chunk.facadeModuleId, contextRoot)] = normalizeOutputPath(
308
+ chunk.fileName,
309
+ outdir
310
+ );
311
+ }
312
+ }
249
313
  return {
250
314
  success: true,
251
315
  logs: [],
252
316
  outputs,
253
- dependencyGraph
317
+ dependencyGraph,
318
+ entryOutputs: entryChunks.length > 0 ? entryOutputs : void 0
254
319
  };
255
320
  }
256
321
  export {
@@ -6,9 +6,7 @@
6
6
  * default adapter installed by `ConfigBuilder` and the adapter that
7
7
  * issues real builds in production.
8
8
  *
9
- * Each `build()` creates a fresh `rolldown()` bundler, so there is no
10
- * module-graph reuse across calls. For HMR/watch mode where the same
11
- * entrypoints are rebuilt repeatedly, see {@link RolldownDevBuildAdapter}.
9
+ * Each `build()` creates a fresh `rolldown()` bundler.
12
10
  */
13
11
  import type { BuildAdapter, BuildOptions, BuildResult, BuildTranspileOptions, BuildTranspileProfile } from './build-adapter.js';
14
12
  export declare class RolldownBuildAdapter implements BuildAdapter {
@@ -16,9 +14,7 @@ export declare class RolldownBuildAdapter implements BuildAdapter {
16
14
  /** Per-adapter require cache, keyed on resolved context root. */
17
15
  private readonly appRootRequireCache;
18
16
  /**
19
- * Issues one build. Creates a fresh `rolldown()` bundler per call,
20
- * so no module-graph reuse. For repeated rebuilds on the same
21
- * entrypoints, use {@link RolldownDevBuildAdapter}.
17
+ * Issues one build. Creates a fresh `rolldown()` bundler per call.
22
18
  */
23
19
  buildOrThrow(options: BuildOptions): Promise<BuildResult>;
24
20
  build(options: BuildOptions): Promise<BuildResult>;
@@ -9,17 +9,17 @@ import {
9
9
  toBuildLogs,
10
10
  transpileProfileToOptions
11
11
  } from "./rolldown-adapter-helpers.js";
12
+ import { recordRolldownBuildInvocation } from "./rolldown-build-invocation-metrics.js";
12
13
  const moduleRequire = createRequire(import.meta.url);
13
14
  class RolldownBuildAdapter {
14
15
  ownership = "rolldown";
15
16
  /** Per-adapter require cache, keyed on resolved context root. */
16
17
  appRootRequireCache = /* @__PURE__ */ new Map();
17
18
  /**
18
- * Issues one build. Creates a fresh `rolldown()` bundler per call,
19
- * so no module-graph reuse. For repeated rebuilds on the same
20
- * entrypoints, use {@link RolldownDevBuildAdapter}.
19
+ * Issues one build. Creates a fresh `rolldown()` bundler per call.
21
20
  */
22
21
  async buildOrThrow(options) {
22
+ recordRolldownBuildInvocation("rolldown");
23
23
  const contextRoot = options.root ? path.resolve(options.root) : process.cwd();
24
24
  const outdir = path.resolve(options.outdir ?? "dist/assets");
25
25
  const plugins = options.plugins ?? [];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Process-wide Rolldown build invocation counters for benchmarks and spikes.
3
+ *
4
+ * Gated behind {@link isRolldownBuildMetricsEnabled} so production paths stay quiet.
5
+ */
6
+ export declare function isRolldownBuildMetricsEnabled(): boolean;
7
+ export declare function recordRolldownBuildInvocation(adapter?: 'rolldown'): void;
8
+ export declare function getRolldownBuildInvocationCounts(): Readonly<Record<string, number>>;
9
+ export declare function resetRolldownBuildInvocationCounts(): void;
10
+ export declare function recordPageModuleBuildInvocation(): void;
11
+ export declare function getPageModuleRolldownBuildInvocations(): number;
12
+ export declare function getTotalRolldownBuildInvocations(): number;
@@ -0,0 +1,43 @@
1
+ const invocationCounts = /* @__PURE__ */ new Map();
2
+ let pageModuleBuildInvocations = 0;
3
+ function isRolldownBuildMetricsEnabled() {
4
+ return process.env.ECOPAGES_ROLLDOWN_BUILD_METRICS === "1" || process.env.ECOPAGES_LOGGER_DEBUG === "true";
5
+ }
6
+ function recordRolldownBuildInvocation(adapter = "rolldown") {
7
+ if (!isRolldownBuildMetricsEnabled()) {
8
+ return;
9
+ }
10
+ invocationCounts.set(adapter, (invocationCounts.get(adapter) ?? 0) + 1);
11
+ }
12
+ function getRolldownBuildInvocationCounts() {
13
+ return Object.fromEntries(invocationCounts);
14
+ }
15
+ function resetRolldownBuildInvocationCounts() {
16
+ invocationCounts.clear();
17
+ pageModuleBuildInvocations = 0;
18
+ }
19
+ function recordPageModuleBuildInvocation() {
20
+ if (!isRolldownBuildMetricsEnabled()) {
21
+ return;
22
+ }
23
+ pageModuleBuildInvocations += 1;
24
+ }
25
+ function getPageModuleRolldownBuildInvocations() {
26
+ return pageModuleBuildInvocations;
27
+ }
28
+ function getTotalRolldownBuildInvocations() {
29
+ let total = 0;
30
+ for (const count of invocationCounts.values()) {
31
+ total += count;
32
+ }
33
+ return total;
34
+ }
35
+ export {
36
+ getPageModuleRolldownBuildInvocations,
37
+ getRolldownBuildInvocationCounts,
38
+ getTotalRolldownBuildInvocations,
39
+ isRolldownBuildMetricsEnabled,
40
+ recordPageModuleBuildInvocation,
41
+ recordRolldownBuildInvocation,
42
+ resetRolldownBuildInvocationCounts
43
+ };
@@ -40,6 +40,7 @@
40
40
  * on every source file.
41
41
  */
42
42
  import type { Plugin } from 'rolldown';
43
+ import type { EcoSourceTransform } from '../plugins/source-transform.js';
43
44
  import type { EcoBuildPlugin } from './build-types.js';
44
45
  /**
45
46
  * Creates a Rolldown `Plugin` array that drives the supplied
@@ -55,5 +56,18 @@ import type { EcoBuildPlugin } from './build-types.js';
55
56
  * Plugin ordering is preserved: registrations from earlier eco plugins
56
57
  * are checked before registrations from later ones, matching the
57
58
  * original per-plugin priority semantics.
59
+ *
60
+ * @remarks
61
+ * Rolldown re-fires `buildStart` on each build, so registrations and the
62
+ * virtual-module counter are cleared before every `setup` pass — otherwise
63
+ * handlers accumulate when bridge plugins are reused.
64
+ *
65
+ * @param plugins - `EcoBuildPlugin` instances registered for this build.
66
+ * @param contextRoot - Project root used to resolve relative load paths.
67
+ * @param sourceTransforms - Optional app-owned transforms applied after a matching
68
+ * `onLoad` handler returns module contents. Browser builds pass
69
+ * {@link getAppSourceTransforms | app source transforms} here so metadata injection
70
+ * still runs on output rewritten by boundary/runtime plugins. Virtual modules,
71
+ * CSS, and asset loads are skipped.
58
72
  */
59
- export declare function createRolldownPluginBridge(plugins: EcoBuildPlugin[], contextRoot: string): Plugin[];
73
+ export declare function createRolldownPluginBridge(plugins: EcoBuildPlugin[], contextRoot: string, sourceTransforms?: readonly EcoSourceTransform[]): Plugin[];