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

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/hmr-manager.d.ts +2 -1
  13. package/src/adapters/bun/hmr-manager.js +2 -2
  14. package/src/adapters/bun/server-adapter.d.ts +90 -22
  15. package/src/adapters/bun/server-adapter.js +265 -84
  16. package/src/adapters/bun/static-preview-host.js +25 -20
  17. package/src/adapters/create-app.d.ts +13 -11
  18. package/src/adapters/create-app.js +2 -51
  19. package/src/adapters/index.d.ts +1 -1
  20. package/src/adapters/index.js +1 -2
  21. package/src/adapters/node/create-app.d.ts +5 -1
  22. package/src/adapters/node/create-app.js +51 -12
  23. package/src/adapters/node/node-client-bridge.d.ts +1 -0
  24. package/src/adapters/node/node-client-bridge.js +3 -0
  25. package/src/adapters/node/node-hmr-manager.d.ts +2 -1
  26. package/src/adapters/node/node-hmr-manager.js +2 -2
  27. package/src/adapters/node/server-adapter-dependencies.js +4 -0
  28. package/src/adapters/node/server-adapter.d.ts +62 -20
  29. package/src/adapters/node/server-adapter.js +161 -131
  30. package/src/adapters/node/static-content-server.d.ts +1 -0
  31. package/src/adapters/node/static-content-server.js +10 -2
  32. package/src/adapters/node/static-preview-host.js +27 -12
  33. package/src/adapters/shared/bun-user-websocket-lifecycle.d.ts +22 -0
  34. package/src/adapters/shared/bun-user-websocket-lifecycle.js +96 -0
  35. package/src/adapters/shared/copy-runtime-public-dir.d.ts +6 -0
  36. package/src/adapters/shared/copy-runtime-public-dir.js +24 -0
  37. package/src/adapters/shared/fs-server-response-matcher.d.ts +2 -0
  38. package/src/adapters/shared/fs-server-response-matcher.js +40 -18
  39. package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +0 -2
  40. package/src/adapters/shared/hmr-entrypoint-registrar.js +3 -26
  41. package/src/adapters/shared/hmr-html-response.d.ts +1 -1
  42. package/src/adapters/shared/hmr-html-response.js +4 -1
  43. package/src/adapters/shared/node-http-websocket-upgrades.d.ts +21 -0
  44. package/src/adapters/shared/node-http-websocket-upgrades.js +100 -0
  45. package/src/adapters/shared/port-manager.d.ts +116 -0
  46. package/src/adapters/shared/port-manager.js +196 -0
  47. package/src/adapters/shared/runtime-app-bootstrap.d.ts +2 -1
  48. package/src/adapters/shared/runtime-app-bootstrap.js +3 -6
  49. package/src/adapters/shared/runtime-server-lifecycle.d.ts +38 -0
  50. package/src/adapters/shared/runtime-server-lifecycle.js +43 -0
  51. package/src/adapters/shared/server-adapter.d.ts +2 -1
  52. package/src/adapters/shared/server-adapter.js +13 -6
  53. package/src/adapters/shared/server-route-handler.d.ts +4 -1
  54. package/src/adapters/shared/server-route-handler.js +5 -2
  55. package/src/adapters/shared/server-static-builder.d.ts +23 -32
  56. package/src/adapters/shared/server-static-builder.js +97 -73
  57. package/src/adapters/shared/shared-hmr-manager.d.ts +28 -0
  58. package/src/adapters/shared/shared-hmr-manager.js +119 -9
  59. package/src/adapters/shared/static-preview-host.d.ts +5 -0
  60. package/src/adapters/shared/websocket-lifecycle.d.ts +24 -0
  61. package/src/adapters/shared/websocket-lifecycle.js +55 -0
  62. package/src/build/README.md +77 -14
  63. package/src/build/app-build-manifest-runtime.d.ts +10 -0
  64. package/src/build/app-build-manifest-runtime.js +90 -0
  65. package/src/build/build-adapter.d.ts +17 -319
  66. package/src/build/build-adapter.js +28 -94
  67. package/src/build/build-contracts.d.ts +97 -0
  68. package/src/build/build-contracts.js +0 -0
  69. package/src/build/build-input-fingerprint.d.ts +28 -0
  70. package/src/build/build-input-fingerprint.js +31 -0
  71. package/src/build/build-profile-options.d.ts +7 -0
  72. package/src/build/build-profile-options.js +37 -0
  73. package/src/build/build-runtime.d.ts +24 -0
  74. package/src/build/build-runtime.js +65 -0
  75. package/src/build/deduping-build-executor.d.ts +28 -0
  76. package/src/build/deduping-build-executor.js +56 -0
  77. package/src/build/jsx-ownership-plugins.d.ts +24 -0
  78. package/src/build/jsx-ownership-plugins.js +41 -0
  79. package/src/build/pages-unified-graph-build.d.ts +31 -0
  80. package/src/build/pages-unified-graph-build.js +206 -0
  81. package/src/build/parallel-build-executor.d.ts +21 -0
  82. package/src/build/parallel-build-executor.js +52 -0
  83. package/src/build/production-build-cache.d.ts +20 -0
  84. package/src/build/production-build-cache.js +63 -0
  85. package/src/build/rolldown-adapter-helpers.d.ts +3 -6
  86. package/src/build/rolldown-adapter-helpers.js +71 -6
  87. package/src/build/rolldown-build-adapter.d.ts +2 -6
  88. package/src/build/rolldown-build-adapter.js +3 -3
  89. package/src/build/rolldown-build-invocation-metrics.d.ts +12 -0
  90. package/src/build/rolldown-build-invocation-metrics.js +43 -0
  91. package/src/build/rolldown-plugin-bridge.d.ts +15 -1
  92. package/src/build/rolldown-plugin-bridge.js +20 -5
  93. package/src/build/rolldown-source-transform-pass.d.ts +15 -0
  94. package/src/build/rolldown-source-transform-pass.js +58 -0
  95. package/src/build/runtime-build-executor.d.ts +8 -15
  96. package/src/build/runtime-build-executor.js +12 -15
  97. package/src/build/runtime-build-output-normalizer.d.ts +7 -0
  98. package/src/build/runtime-build-output-normalizer.js +94 -2
  99. package/src/build/server-entry-build-cache.d.ts +44 -0
  100. package/src/build/server-entry-build-cache.js +161 -0
  101. package/src/client/navigation-scripts/classification.d.ts +16 -0
  102. package/src/client/navigation-scripts/classification.js +41 -0
  103. package/src/client/navigation-scripts/index.d.ts +3 -0
  104. package/src/client/navigation-scripts/index.js +23 -0
  105. package/src/client/navigation-scripts/navigation-scripts.test.browser.js +65 -0
  106. package/src/client/navigation-scripts/registry.d.ts +11 -0
  107. package/src/client/navigation-scripts/registry.js +12 -0
  108. package/src/client/navigation-scripts/rerun-queue.d.ts +37 -0
  109. package/src/client/navigation-scripts/rerun-queue.js +73 -0
  110. package/src/client/scroll.d.ts +17 -0
  111. package/src/client/scroll.js +25 -0
  112. package/src/client/scroll.test.browser.js +37 -0
  113. package/src/client/view-transitions.d.ts +16 -0
  114. package/src/client/view-transitions.js +63 -0
  115. package/src/config/config-builder.d.ts +12 -7
  116. package/src/config/config-builder.js +12 -9
  117. package/src/dev/client-bridge-registry.d.ts +5 -0
  118. package/src/dev/client-bridge-registry.js +15 -0
  119. package/src/dev/dev-client-ownership.d.ts +7 -0
  120. package/src/dev/dev-client-ownership.js +6 -0
  121. package/src/dev/hmr-manager-registry.d.ts +8 -0
  122. package/src/dev/hmr-manager-registry.js +15 -0
  123. package/src/dev/host-runtime.d.ts +3 -0
  124. package/src/dev/host-runtime.js +7 -0
  125. package/src/dev/runtime-server-started-message.d.ts +2 -0
  126. package/src/dev/runtime-server-started-message.js +6 -0
  127. package/src/eco/README.md +11 -0
  128. package/src/eco/eco-declared-component.d.ts +14 -0
  129. package/src/eco/eco-declared-component.js +16 -0
  130. package/src/eco/eco.browser.js +5 -6
  131. package/src/eco/eco.js +5 -6
  132. package/src/eco/eco.types.d.ts +2 -2
  133. package/src/eco/page-layout-normalization.d.ts +21 -0
  134. package/src/eco/page-layout-normalization.js +59 -0
  135. package/src/errors/index.d.ts +1 -0
  136. package/src/errors/index.js +7 -1
  137. package/src/errors/undeclared-component-dependency-error.d.ts +11 -0
  138. package/src/errors/undeclared-component-dependency-error.js +17 -0
  139. package/src/hmr/client/hmr-runtime.js +5 -2
  140. package/src/hmr/hmr-entrypoint-output.d.ts +28 -0
  141. package/src/hmr/hmr-entrypoint-output.js +58 -0
  142. package/src/hmr/strategies/js-hmr-strategy.d.ts +3 -0
  143. package/src/hmr/strategies/js-hmr-strategy.js +68 -18
  144. package/src/hmr/strategies/server-rendered-template-hmr-strategy.d.ts +17 -0
  145. package/src/hmr/strategies/server-rendered-template-hmr-strategy.js +29 -0
  146. package/src/integrations/ghtml/ghtml-renderer.d.ts +2 -6
  147. package/src/integrations/ghtml/ghtml-renderer.js +2 -51
  148. package/src/integrations/ghtml/ghtml.plugin.d.ts +3 -16
  149. package/src/integrations/ghtml/ghtml.plugin.js +7 -14
  150. package/src/plugins/define-integration.d.ts +26 -0
  151. package/src/plugins/define-integration.js +19 -0
  152. package/src/plugins/eco-component-meta-plugin.js +5 -8
  153. package/src/plugins/foreign-jsx-override-plugin.js +4 -6
  154. package/src/plugins/integration-plugin.d.ts +19 -9
  155. package/src/plugins/integration-plugin.js +7 -4
  156. package/src/plugins/jsx-import-source.utils.d.ts +8 -0
  157. package/src/plugins/jsx-import-source.utils.js +26 -0
  158. package/src/plugins/processor.d.ts +19 -4
  159. package/src/plugins/processor.js +22 -4
  160. package/src/plugins/source-transform.d.ts +31 -0
  161. package/src/plugins/source-transform.js +23 -1
  162. package/src/route-renderer/GRAPH.md +8 -8
  163. package/src/route-renderer/README.md +30 -28
  164. package/src/route-renderer/orchestration/component-graph-collectors.d.ts +10 -0
  165. package/src/route-renderer/orchestration/component-graph-collectors.js +143 -0
  166. package/src/route-renderer/orchestration/component-graph.d.ts +36 -0
  167. package/src/route-renderer/orchestration/component-graph.js +98 -0
  168. package/src/route-renderer/orchestration/component-render-context.d.ts +3 -10
  169. package/src/route-renderer/orchestration/component-render-context.js +3 -1
  170. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +1 -18
  171. package/src/route-renderer/orchestration/declared-ownership-graph.js +5 -31
  172. package/src/route-renderer/orchestration/document-shell-render.service.d.ts +90 -0
  173. package/src/route-renderer/orchestration/document-shell-render.service.js +120 -0
  174. package/src/route-renderer/orchestration/foreign-subtree-execution.service.d.ts +59 -29
  175. package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +164 -35
  176. package/src/route-renderer/orchestration/global-injector-assets.service.d.ts +7 -0
  177. package/src/route-renderer/orchestration/global-injector-assets.service.js +32 -0
  178. package/src/route-renderer/orchestration/integration-renderer.d.ts +18 -54
  179. package/src/route-renderer/orchestration/integration-renderer.js +113 -195
  180. package/src/route-renderer/orchestration/integration-route-render-adapter.d.ts +38 -0
  181. package/src/route-renderer/orchestration/integration-route-render-adapter.js +27 -0
  182. package/src/route-renderer/orchestration/layout-shell-props.service.d.ts +20 -0
  183. package/src/route-renderer/orchestration/layout-shell-props.service.js +31 -0
  184. package/src/route-renderer/orchestration/ownership-validation.service.d.ts +5 -0
  185. package/src/route-renderer/orchestration/ownership-validation.service.js +29 -1
  186. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.d.ts +9 -0
  187. package/src/route-renderer/orchestration/page-browser-graph-contribution.loader.js +7 -0
  188. package/src/route-renderer/orchestration/page-browser-graph.service.d.ts +25 -0
  189. package/src/route-renderer/orchestration/page-browser-graph.service.js +174 -0
  190. package/src/route-renderer/orchestration/render-output.utils.d.ts +2 -0
  191. package/src/route-renderer/orchestration/render-output.utils.js +4 -0
  192. package/src/route-renderer/orchestration/route-html-finalization.service.d.ts +17 -0
  193. package/src/route-renderer/orchestration/route-html-finalization.service.js +26 -0
  194. package/src/route-renderer/orchestration/route-prepared-options.builder.d.ts +26 -0
  195. package/src/route-renderer/orchestration/route-prepared-options.builder.js +54 -0
  196. package/src/route-renderer/orchestration/route-prepared-options.utils.d.ts +4 -0
  197. package/src/route-renderer/orchestration/route-prepared-options.utils.js +33 -0
  198. package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +8 -39
  199. package/src/route-renderer/orchestration/route-render-orchestrator.js +53 -461
  200. package/src/route-renderer/orchestration/string-markup-renderer.d.ts +14 -0
  201. package/src/route-renderer/orchestration/string-markup-renderer.js +55 -0
  202. package/src/route-renderer/page-loading/component-dependency-collection.js +5 -2
  203. package/src/router/client/link-intent.d.ts +11 -21
  204. package/src/router/client/link-intent.js +10 -0
  205. package/src/router/client/link-intent.test.browser.js +12 -1
  206. package/src/router/client/link-navigation-policy.d.ts +45 -0
  207. package/src/router/client/link-navigation-policy.js +101 -0
  208. package/src/router/client/link-navigation-policy.test.browser.d.ts +1 -0
  209. package/src/router/client/link-navigation-policy.test.browser.js +92 -0
  210. package/src/router/client/navigation-coordinator.d.ts +1 -1
  211. package/src/router/client/navigation-coordinator.js +12 -2
  212. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +1 -0
  213. package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +1 -0
  214. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +4 -2
  215. package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +27 -7
  216. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +36 -14
  217. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +17 -3
  218. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -3
  219. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -31
  220. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -3
  221. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +2 -30
  222. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.d.ts +2 -0
  223. package/src/services/assets/asset-processing-service/processors/stylesheet/stylesheet-processor-pipeline.js +43 -0
  224. package/src/services/assets/browser-bundle.service.d.ts +3 -1
  225. package/src/services/assets/browser-bundle.service.js +17 -5
  226. package/src/services/html/html-transformer.service.d.ts +1 -1
  227. package/src/services/html/html-transformer.service.js +4 -4
  228. package/src/services/invalidation/development-invalidation.service.d.ts +20 -2
  229. package/src/services/invalidation/development-invalidation.service.js +56 -2
  230. package/src/services/module-loading/README.md +49 -0
  231. package/src/services/module-loading/app-server-module-transpiler.service.js +5 -17
  232. package/src/services/module-loading/page-module-import.service.d.ts +5 -1
  233. package/src/services/module-loading/page-module-import.service.js +97 -45
  234. package/src/services/module-loading/route-module-build-cache-registry.d.ts +24 -0
  235. package/src/services/module-loading/route-module-build-cache-registry.js +37 -0
  236. package/src/services/module-loading/route-module-build-cache.d.ts +4 -0
  237. package/src/services/module-loading/route-module-build-cache.js +38 -0
  238. package/src/services/module-loading/route-module-build-cache.store.d.ts +57 -0
  239. package/src/services/module-loading/route-module-build-cache.store.js +207 -0
  240. package/src/services/module-loading/route-module-build-manifest.d.ts +61 -0
  241. package/src/services/module-loading/route-module-build-manifest.js +116 -0
  242. package/src/services/module-loading/route-module-dependency-hasher.d.ts +81 -0
  243. package/src/services/module-loading/route-module-dependency-hasher.js +121 -0
  244. package/src/services/module-loading/server-module-transpiler.service.js +1 -1
  245. package/src/static-site-generator/README.md +33 -0
  246. package/src/static-site-generator/static-build-invalidation.d.ts +10 -0
  247. package/src/static-site-generator/static-build-invalidation.js +59 -0
  248. package/src/static-site-generator/static-export-context.d.ts +22 -0
  249. package/src/static-site-generator/static-export-context.js +0 -0
  250. package/src/static-site-generator/static-site-generator.d.ts +17 -20
  251. package/src/static-site-generator/static-site-generator.js +188 -85
  252. package/src/types/internal-types.d.ts +16 -9
  253. package/src/types/public-types.d.ts +138 -26
  254. package/src/utils/parse-cli-args.d.ts +2 -0
  255. package/src/utils/parse-cli-args.js +6 -0
  256. package/src/utils/server-utils.module.d.ts +3 -2
  257. package/src/utils/server-utils.module.js +5 -6
  258. package/src/utils/static-file-extensions.d.ts +12 -0
  259. package/src/utils/static-file-extensions.js +48 -0
  260. package/src/watchers/project-watcher-ignore.d.ts +11 -0
  261. package/src/watchers/project-watcher-ignore.js +16 -0
  262. package/src/watchers/project-watcher.d.ts +25 -2
  263. package/src/watchers/project-watcher.js +130 -23
  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,28 @@
1
+ /**
2
+ * Returns whether a source path is a registered client script HMR entrypoint.
3
+ *
4
+ * @remarks
5
+ * Registration comes from `dependencies.scripts` via `FileScriptProcessor`,
6
+ * not from filename conventions such as `.script.tsx`.
7
+ */
8
+ export declare function isRegisteredScriptEntrypoint(watchedFiles: ReadonlyMap<string, string>, filePath: string): boolean;
9
+ export declare function encodeHmrDynamicSegments(filepath: string): string;
10
+ /**
11
+ * Resolves the on-disk and browser URL targets for one HMR script entrypoint.
12
+ */
13
+ export declare function resolveHmrEntrypointOutputPaths(srcDir: string, distDir: string, entrypointPath: string): {
14
+ outputPath: string;
15
+ outputUrl: string;
16
+ };
17
+ /**
18
+ * @remarks
19
+ * Rebuilds must delete the previous artifact so browser-hmr does not reuse a
20
+ * stale bundle when the source file changed.
21
+ */
22
+ export declare function removeStaleHmrEntrypointOutput(outputPath: string, scope: string): void;
23
+ /**
24
+ * @remarks
25
+ * Guards against broadcasting reload/update before the bundler has flushed a
26
+ * fresher artifact than the edited source file.
27
+ */
28
+ export declare function isHmrOutputFresh(outputPath: string, sourcePath: string): boolean;
@@ -0,0 +1,58 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileSystem } from "@ecopages/file-system";
4
+ import { RESOLVED_ASSETS_DIR } from "../config/constants.js";
5
+ import { appLogger } from "../global/app-logger.js";
6
+ function isRegisteredScriptEntrypoint(watchedFiles, filePath) {
7
+ const resolvedPath = path.resolve(filePath);
8
+ if (watchedFiles.has(resolvedPath)) {
9
+ return true;
10
+ }
11
+ for (const entrypointPath of watchedFiles.keys()) {
12
+ if (path.resolve(entrypointPath) === resolvedPath) {
13
+ return true;
14
+ }
15
+ }
16
+ return false;
17
+ }
18
+ function encodeHmrDynamicSegments(filepath) {
19
+ return filepath.replace(/\[([^\]]+)\]/g, "_$1_");
20
+ }
21
+ function resolveHmrEntrypointOutputPaths(srcDir, distDir, entrypointPath) {
22
+ const normalizedEntrypoint = path.resolve(entrypointPath);
23
+ const relativePath = path.relative(srcDir, normalizedEntrypoint);
24
+ const relativePathJs = relativePath.replace(/\.(tsx?|jsx?|mdx?)$/, ".js");
25
+ const encodedPathJs = encodeHmrDynamicSegments(relativePathJs);
26
+ const urlPath = encodedPathJs.split(path.sep).join("/");
27
+ return {
28
+ outputUrl: `/${path.join(RESOLVED_ASSETS_DIR, "_hmr", urlPath).split(path.sep).join("/")}`,
29
+ outputPath: path.join(distDir, urlPath)
30
+ };
31
+ }
32
+ function removeStaleHmrEntrypointOutput(outputPath, scope) {
33
+ if (!fileSystem.exists(outputPath)) {
34
+ return;
35
+ }
36
+ try {
37
+ fileSystem.remove(outputPath);
38
+ } catch (error) {
39
+ appLogger.warn(
40
+ `[${scope}] Failed to remove stale entrypoint output ${outputPath}: ${error instanceof Error ? error.message : String(error)}`
41
+ );
42
+ }
43
+ }
44
+ function isHmrOutputFresh(outputPath, sourcePath) {
45
+ if (!fileSystem.exists(outputPath) || !fileSystem.exists(sourcePath)) {
46
+ return false;
47
+ }
48
+ const outputMtimeMs = fs.statSync(outputPath).mtimeMs;
49
+ const sourceMtimeMs = fs.statSync(sourcePath).mtimeMs;
50
+ return outputMtimeMs >= sourceMtimeMs;
51
+ }
52
+ export {
53
+ encodeHmrDynamicSegments,
54
+ isHmrOutputFresh,
55
+ isRegisteredScriptEntrypoint,
56
+ removeStaleHmrEntrypointOutput,
57
+ resolveHmrEntrypointOutputPaths
58
+ };
@@ -98,6 +98,7 @@ export declare class JsHmrStrategy extends HmrStrategy {
98
98
  * Matches if:
99
99
  * 1. There are registered entrypoints to rebuild
100
100
  * 2. The changed file is a JS/TS file in the src directory
101
+ * 3. Registered entrypoints always match, even when they share an integration template extension
101
102
  *
102
103
  * @param filePath - Absolute path to the changed file
103
104
  * @returns True if this file should trigger entrypoint rebuilds
@@ -116,6 +117,8 @@ export declare class JsHmrStrategy extends HmrStrategy {
116
117
  * @returns Action to broadcast update events
117
118
  */
118
119
  process(filePath: string): Promise<HmrAction>;
120
+ private resolveEntrypointOutputPath;
121
+ private removeStaleEntrypointOutput;
119
122
  /**
120
123
  * Bundles one or more entrypoints in a single build invocation.
121
124
  * Uses the source directory as the output base so that the directory structure
@@ -2,6 +2,12 @@ import path from "node:path";
2
2
  import { fileSystem } from "@ecopages/file-system";
3
3
  import { HmrStrategy, HmrStrategyType } from "../hmr-strategy.js";
4
4
  import { appLogger } from "../../global/app-logger.js";
5
+ import {
6
+ removeStaleHmrEntrypointOutput,
7
+ resolveHmrEntrypointOutputPaths,
8
+ isRegisteredScriptEntrypoint,
9
+ isHmrOutputFresh
10
+ } from "../hmr-entrypoint-output.js";
5
11
  class JsHmrStrategy extends HmrStrategy {
6
12
  type = HmrStrategyType.SCRIPT;
7
13
  context;
@@ -15,27 +21,30 @@ class JsHmrStrategy extends HmrStrategy {
15
21
  * Matches if:
16
22
  * 1. There are registered entrypoints to rebuild
17
23
  * 2. The changed file is a JS/TS file in the src directory
24
+ * 3. Registered entrypoints always match, even when they share an integration template extension
18
25
  *
19
26
  * @param filePath - Absolute path to the changed file
20
27
  * @returns True if this file should trigger entrypoint rebuilds
21
28
  */
22
29
  matches(filePath) {
23
30
  const watchedFiles = this.context.getWatchedFiles();
24
- const isJsTs = /\.(ts|tsx|js|jsx)$/.test(filePath);
25
- const isInSrc = filePath.startsWith(this.context.getSrcDir());
26
- const isIntegrationTemplate = this.context.getTemplateExtensions().some((extension) => filePath.endsWith(extension));
31
+ const resolvedPath = path.resolve(filePath);
32
+ const isJsTs = /\.(ts|tsx|js|jsx)$/.test(resolvedPath);
33
+ const srcDir = path.resolve(this.context.getSrcDir());
34
+ const isInSrc = resolvedPath.startsWith(`${srcDir}${path.sep}`) || resolvedPath === srcDir;
35
+ const isIntegrationTemplate = this.context.getTemplateExtensions().some((extension) => resolvedPath.endsWith(extension));
27
36
  if (watchedFiles.size === 0) {
28
37
  return false;
29
38
  }
30
39
  if (!isJsTs || !isInSrc) {
31
40
  return false;
32
41
  }
42
+ if (watchedFiles.has(resolvedPath)) {
43
+ return true;
44
+ }
33
45
  if (isIntegrationTemplate) {
34
46
  return false;
35
47
  }
36
- if (watchedFiles.has(filePath)) {
37
- return true;
38
- }
39
48
  return true;
40
49
  }
41
50
  /**
@@ -53,22 +62,27 @@ class JsHmrStrategy extends HmrStrategy {
53
62
  async process(filePath) {
54
63
  appLogger.debug(`[JsHmrStrategy] Processing ${filePath}`);
55
64
  const watchedFiles = this.context.getWatchedFiles();
65
+ const resolvedChanged = path.resolve(filePath);
66
+ const isRegisteredEntrypointEdit = isRegisteredScriptEntrypoint(watchedFiles, resolvedChanged);
56
67
  if (watchedFiles.size === 0) {
57
68
  appLogger.debug(`[JsHmrStrategy] No watched files to rebuild`);
58
69
  return { type: "none" };
59
70
  }
60
71
  const dependencyHits = this.context.getEntrypointDependencyGraph().getDependencyEntrypoints(filePath);
61
72
  const hasDependencyHit = dependencyHits.size > 0;
62
- const impactedEntrypoints = hasDependencyHit ? Array.from(dependencyHits).filter((entrypoint) => watchedFiles.has(entrypoint)) : Array.from(watchedFiles.keys());
73
+ const impactedEntrypoints = isRegisteredEntrypointEdit ? [resolvedChanged] : hasDependencyHit ? Array.from(dependencyHits).filter((entrypoint) => watchedFiles.has(path.resolve(entrypoint))) : Array.from(watchedFiles.keys());
63
74
  const buildableEntrypoints = impactedEntrypoints.filter(
64
75
  (entrypoint) => this.context.shouldProcessEntrypoint?.(entrypoint) ?? true
65
76
  );
66
- if (!hasDependencyHit) {
77
+ if (!hasDependencyHit && !isRegisteredEntrypointEdit) {
67
78
  appLogger.debug("[JsHmrStrategy] Dependency graph miss, rebuilding all watched entrypoints");
68
79
  }
69
80
  if (buildableEntrypoints.length === 0) {
70
81
  return { type: "none" };
71
82
  }
83
+ for (const entrypoint of buildableEntrypoints) {
84
+ this.removeStaleEntrypointOutput(this.resolveEntrypointOutputPath(entrypoint));
85
+ }
72
86
  const buildResult = await this.bundleEntrypoints(buildableEntrypoints);
73
87
  if (!buildResult.success) {
74
88
  return { type: "none" };
@@ -76,17 +90,19 @@ class JsHmrStrategy extends HmrStrategy {
76
90
  const updates = [];
77
91
  let reloadRequired = false;
78
92
  for (const entrypoint of buildableEntrypoints) {
79
- const outputUrl = watchedFiles.get(entrypoint);
80
- if (!outputUrl) continue;
93
+ const resolvedEntrypoint = path.resolve(entrypoint);
94
+ const derivedOutput = resolveHmrEntrypointOutputPaths(
95
+ this.context.getSrcDir(),
96
+ this.context.getDistDir(),
97
+ resolvedEntrypoint
98
+ );
99
+ const outputUrl = watchedFiles.get(resolvedEntrypoint) ?? derivedOutput.outputUrl;
100
+ const outputPath = this.resolveEntrypointOutputPath(resolvedEntrypoint);
81
101
  if (buildResult.dependencies) {
82
- const entrypointDeps = buildResult.dependencies.get(path.resolve(entrypoint)) ?? [];
83
- this.context.getEntrypointDependencyGraph().setEntrypointDependencies(entrypoint, entrypointDeps);
102
+ const entrypointDeps = buildResult.dependencies.get(resolvedEntrypoint) ?? [];
103
+ this.context.getEntrypointDependencyGraph().setEntrypointDependencies(resolvedEntrypoint, entrypointDeps);
84
104
  }
85
- const srcDir = this.context.getSrcDir();
86
- const relativePath = path.relative(srcDir, entrypoint);
87
- const relativePathJs = relativePath.replace(/\.(tsx?|jsx?|mdx?)$/, ".js");
88
- const outputPath = path.join(this.context.getDistDir(), relativePathJs);
89
- const result = await this.processOutput(outputPath, outputUrl);
105
+ const result = await this.processOutput(outputPath, outputUrl, resolvedEntrypoint);
90
106
  if (result.success) {
91
107
  updates.push(outputUrl);
92
108
  if (result.requiresReload) {
@@ -113,6 +129,12 @@ class JsHmrStrategy extends HmrStrategy {
113
129
  }
114
130
  return { type: "none" };
115
131
  }
132
+ resolveEntrypointOutputPath(entrypointPath) {
133
+ return resolveHmrEntrypointOutputPaths(this.context.getSrcDir(), this.context.getDistDir(), entrypointPath).outputPath;
134
+ }
135
+ removeStaleEntrypointOutput(outputPath) {
136
+ removeStaleHmrEntrypointOutput(outputPath, "JsHmrStrategy");
137
+ }
116
138
  /**
117
139
  * Bundles one or more entrypoints in a single build invocation.
118
140
  * Uses the source directory as the output base so that the directory structure
@@ -120,6 +142,30 @@ class JsHmrStrategy extends HmrStrategy {
120
142
  */
121
143
  async bundleEntrypoints(entrypoints) {
122
144
  try {
145
+ if (entrypoints.length === 1) {
146
+ const entrypoint = entrypoints[0];
147
+ const outputPath = this.resolveEntrypointOutputPath(entrypoint);
148
+ const naming = path.relative(this.context.getDistDir(), outputPath).split(path.sep).join("/");
149
+ const result2 = await this.context.getBrowserBundleService().bundle({
150
+ profile: "hmr-entrypoint",
151
+ entrypoints: [entrypoint],
152
+ outdir: this.context.getDistDir(),
153
+ naming,
154
+ plugins: this.context.getPlugins(),
155
+ minify: false
156
+ });
157
+ if (!result2.success) {
158
+ appLogger.error("[JsHmrStrategy] Entrypoint build failed:", result2.logs);
159
+ return { success: false };
160
+ }
161
+ const dependencies2 = /* @__PURE__ */ new Map();
162
+ if (result2.dependencyGraph?.entrypoints) {
163
+ for (const [resolvedEntrypoint, deps] of Object.entries(result2.dependencyGraph.entrypoints)) {
164
+ dependencies2.set(path.resolve(resolvedEntrypoint), deps);
165
+ }
166
+ }
167
+ return { success: true, dependencies: dependencies2 };
168
+ }
123
169
  const result = await this.context.getBrowserBundleService().bundle({
124
170
  profile: "hmr-entrypoint",
125
171
  entrypoints,
@@ -153,8 +199,12 @@ class JsHmrStrategy extends HmrStrategy {
153
199
  * @param url - URL path for the bundled file
154
200
  * @returns True if processing was successful and update should be broadcast
155
201
  */
156
- async processOutput(filepath, url) {
202
+ async processOutput(filepath, url, sourcePath) {
157
203
  try {
204
+ if (sourcePath && !isHmrOutputFresh(filepath, sourcePath)) {
205
+ appLogger.warn(`[JsHmrStrategy] Skipping broadcast for stale HMR output ${url}`);
206
+ return { success: false, requiresReload: false };
207
+ }
158
208
  const code = await fileSystem.readFile(filepath);
159
209
  if (code.includes("/* [ecopages] hmr */")) {
160
210
  return { success: true, requiresReload: !code.includes("import.meta.hot.accept") };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * HMR strategy for server-rendered include templates and explicit server views.
3
+ *
4
+ * These files affect SSR output (head, layout shell, explicit views) but are not
5
+ * client HMR entrypoints. Broadcast a layout-update so the active navigation
6
+ * runtime can refresh the current page without a full document reload.
7
+ */
8
+ import { HmrStrategy, type HmrAction } from '../hmr-strategy.js';
9
+ import type { DevelopmentInvalidationService } from '../../services/invalidation/development-invalidation.service.js';
10
+ export declare class ServerRenderedTemplateHmrStrategy extends HmrStrategy {
11
+ private readonly invalidationService;
12
+ readonly type: 100;
13
+ readonly priorityOffset = 50;
14
+ constructor(invalidationService: DevelopmentInvalidationService);
15
+ matches(filePath: string): boolean;
16
+ process(filePath: string): Promise<HmrAction>;
17
+ }
@@ -0,0 +1,29 @@
1
+ import { HmrStrategy, HmrStrategyType } from "../hmr-strategy.js";
2
+ const SERVER_RENDERED_TEMPLATE_PRIORITY_OFFSET = 50;
3
+ class ServerRenderedTemplateHmrStrategy extends HmrStrategy {
4
+ constructor(invalidationService) {
5
+ super();
6
+ this.invalidationService = invalidationService;
7
+ }
8
+ invalidationService;
9
+ type = HmrStrategyType.INTEGRATION;
10
+ priorityOffset = SERVER_RENDERED_TEMPLATE_PRIORITY_OFFSET;
11
+ matches(filePath) {
12
+ return this.invalidationService.isIncludeSourceFile(filePath) || this.invalidationService.isExplicitServerViewFile(filePath);
13
+ }
14
+ async process(filePath) {
15
+ return {
16
+ type: "broadcast",
17
+ events: [
18
+ {
19
+ type: "layout-update",
20
+ path: filePath,
21
+ timestamp: Date.now()
22
+ }
23
+ ]
24
+ };
25
+ }
26
+ }
27
+ export {
28
+ ServerRenderedTemplateHmrStrategy
29
+ };
@@ -2,15 +2,11 @@
2
2
  * This module contains the ghtml renderer
3
3
  * @module
4
4
  */
5
- import type { ComponentRenderInput, ComponentRenderResult, EcoComponent, EcoPagesElement, IntegrationRendererRenderOptions, RouteRendererBody } from '../../types/public-types.js';
6
- import { IntegrationRenderer, type RenderToResponseContext } from '../../route-renderer/orchestration/integration-renderer.js';
5
+ import { StringMarkupRenderer } from '../../route-renderer/orchestration/string-markup-renderer.js';
7
6
  /**
8
7
  * A renderer for the ghtml integration.
9
8
  * It renders a page using the HtmlTemplate and Page components.
10
9
  */
11
- export declare class GhtmlRenderer extends IntegrationRenderer<EcoPagesElement> {
10
+ export declare class GhtmlRenderer extends StringMarkupRenderer {
12
11
  name: string;
13
- renderComponent(input: ComponentRenderInput): Promise<ComponentRenderResult>;
14
- render({ params, query, props, locals, pageLocals, metadata, Page, Layout, HtmlTemplate, }: IntegrationRendererRenderOptions): Promise<RouteRendererBody>;
15
- renderToResponse<P = Record<string, unknown>>(view: EcoComponent<P>, props: P, ctx: RenderToResponseContext): Promise<Response>;
16
12
  }
@@ -1,56 +1,7 @@
1
- import {
2
- IntegrationRenderer
3
- } from "../../route-renderer/orchestration/integration-renderer.js";
1
+ import { StringMarkupRenderer } from "../../route-renderer/orchestration/string-markup-renderer.js";
4
2
  import { GHTML_PLUGIN_NAME } from "./ghtml.constants.js";
5
- class GhtmlRenderer extends IntegrationRenderer {
3
+ class GhtmlRenderer extends StringMarkupRenderer {
6
4
  name = GHTML_PLUGIN_NAME;
7
- async renderComponent(input) {
8
- return this.renderStringComponentWithQueuedForeignSubtrees(
9
- input,
10
- input.component
11
- );
12
- }
13
- async render({
14
- params,
15
- query,
16
- props,
17
- locals,
18
- pageLocals,
19
- metadata,
20
- Page,
21
- Layout,
22
- HtmlTemplate
23
- }) {
24
- try {
25
- return await this.renderPageWithDocumentShell({
26
- page: {
27
- component: Page,
28
- props: { params, query, ...props, locals: pageLocals }
29
- },
30
- layout: Layout ? {
31
- component: Layout,
32
- props: locals ? { locals } : {}
33
- } : void 0,
34
- htmlTemplate: HtmlTemplate,
35
- metadata,
36
- pageProps: props ?? {}
37
- });
38
- } catch (error) {
39
- throw this.createRenderError("Error rendering page", error);
40
- }
41
- }
42
- async renderToResponse(view, props, ctx) {
43
- try {
44
- return await this.renderViewWithDocumentShell({
45
- view,
46
- props,
47
- ctx,
48
- layout: view.config?.layout
49
- });
50
- } catch (error) {
51
- throw this.createRenderError("Error rendering view", error);
52
- }
53
- }
54
5
  }
55
6
  export {
56
7
  GhtmlRenderer
@@ -1,16 +1,3 @@
1
- import { IntegrationPlugin, type IntegrationPluginConfig } from '../../plugins/integration-plugin.js';
2
- import { GhtmlRenderer } from './ghtml-renderer.js';
3
- /**
4
- * The Ghtml plugin class
5
- * This plugin provides support for ghtml components in Ecopages
6
- */
7
- export declare class GhtmlPlugin extends IntegrationPlugin {
8
- renderer: typeof GhtmlRenderer;
9
- constructor(options?: Omit<IntegrationPluginConfig, 'name'>);
10
- }
11
- /**
12
- * Factory function to create a Ghtml plugin instance
13
- * @param options Configuration options for the Ghtml plugin
14
- * @returns A new GhtmlPlugin instance
15
- */
16
- export declare function ghtmlPlugin(options?: Omit<IntegrationPluginConfig, 'name'>): GhtmlPlugin;
1
+ export declare const ghtmlPlugin: import("../../plugins/define-integration.js").DefinedIntegration<import("../../index.browser.js").EcoPagesElement>;
2
+ /** @deprecated Use {@link ghtmlPlugin.Plugin} or {@link ghtmlPlugin} instead. */
3
+ export declare const GhtmlPlugin: new (options?: Omit<import("../../plugins/integration-plugin.js").IntegrationPluginConfig, "name">) => import("../../plugins/integration-plugin.js").IntegrationPlugin<import("../../index.browser.js").EcoPagesElement>;
@@ -1,19 +1,12 @@
1
- import { IntegrationPlugin } from "../../plugins/integration-plugin.js";
1
+ import { defineIntegration } from "../../plugins/define-integration.js";
2
2
  import { GhtmlRenderer } from "./ghtml-renderer.js";
3
3
  import { GHTML_PLUGIN_NAME } from "./ghtml.constants.js";
4
- class GhtmlPlugin extends IntegrationPlugin {
5
- renderer = GhtmlRenderer;
6
- constructor(options) {
7
- super({
8
- name: GHTML_PLUGIN_NAME,
9
- extensions: [".ghtml.ts", ".ghtml.tsx", ".ghtml"],
10
- ...options
11
- });
12
- }
13
- }
14
- function ghtmlPlugin(options) {
15
- return new GhtmlPlugin(options);
16
- }
4
+ const ghtmlPlugin = defineIntegration({
5
+ name: GHTML_PLUGIN_NAME,
6
+ extensions: [".ghtml.ts", ".ghtml.tsx", ".ghtml"],
7
+ renderer: GhtmlRenderer
8
+ });
9
+ const GhtmlPlugin = ghtmlPlugin.Plugin;
17
10
  export {
18
11
  GhtmlPlugin,
19
12
  ghtmlPlugin
@@ -0,0 +1,26 @@
1
+ import type { EcoPagesAppConfig } from '../types/internal-types.js';
2
+ import type { AssetProcessingService } from '../services/assets/asset-processing-service/asset-processing.service.js';
3
+ import type { ProcessedAsset } from '../services/assets/asset-processing-service/assets.types.js';
4
+ import type { EcoPagesElement } from '../types/public-types.js';
5
+ import type { IntegrationRenderer } from '../route-renderer/orchestration/integration-renderer.js';
6
+ import { IntegrationPlugin, type IntegrationPluginConfig } from './integration-plugin.js';
7
+ type RendererClass<C> = new (options: {
8
+ appConfig: EcoPagesAppConfig;
9
+ assetProcessingService: AssetProcessingService;
10
+ resolvedIntegrationDependencies: ProcessedAsset[];
11
+ rendererModules?: unknown;
12
+ runtimeOrigin: string;
13
+ }) => IntegrationRenderer<C>;
14
+ export interface DefineIntegrationDefinition<C = EcoPagesElement> extends IntegrationPluginConfig {
15
+ renderer: RendererClass<C>;
16
+ }
17
+ export interface DefinedIntegration<C = EcoPagesElement> {
18
+ (options?: Omit<IntegrationPluginConfig, 'name'>): IntegrationPlugin<C>;
19
+ Plugin: new (options?: Omit<IntegrationPluginConfig, 'name'>) => IntegrationPlugin<C>;
20
+ }
21
+ /**
22
+ * Creates a typed integration plugin factory for integrations that only need
23
+ * declarative config and a renderer class.
24
+ */
25
+ export declare function defineIntegration<C = EcoPagesElement>(definition: DefineIntegrationDefinition<C>): DefinedIntegration<C>;
26
+ export {};
@@ -0,0 +1,19 @@
1
+ import { IntegrationPlugin } from "./integration-plugin.js";
2
+ function defineIntegration(definition) {
3
+ const { renderer, ...defaultConfig } = definition;
4
+ class DefinedIntegrationPlugin extends IntegrationPlugin {
5
+ renderer = renderer;
6
+ constructor(options) {
7
+ super({
8
+ ...defaultConfig,
9
+ ...options
10
+ });
11
+ }
12
+ }
13
+ const factory = ((options) => new DefinedIntegrationPlugin(options));
14
+ factory.Plugin = DefinedIntegrationPlugin;
15
+ return factory;
16
+ }
17
+ export {
18
+ defineIntegration
19
+ };
@@ -1,4 +1,5 @@
1
1
  import { cachedParseSync } from "../cache/module-parse-cache.js";
2
+ import { prependJsxImportSourceIfMissing } from "./jsx-import-source.utils.js";
2
3
  import { rapidhash } from "../utils/hash.js";
3
4
  import {
4
5
  createEcoBuildPluginFromSourceTransform,
@@ -38,13 +39,6 @@ function detectIntegration(filePath, extensionToIntegration) {
38
39
  }
39
40
  return { name: "ghtml" };
40
41
  }
41
- function prependJsxImportSource(code, jsxImportSource) {
42
- if (!jsxImportSource || code.includes("@jsxImportSource")) {
43
- return code;
44
- }
45
- return `/** @jsxImportSource ${jsxImportSource} */
46
- ${code}`;
47
- }
48
42
  function createExtensionPattern(extensions) {
49
43
  if (extensions.length === 0) {
50
44
  throw new Error("[eco-component-meta-plugin] No extensions configured. At least one integration is required.");
@@ -67,7 +61,10 @@ function createEcoComponentMetaTransform(options) {
67
61
  transform(code, id) {
68
62
  const integration = detectIntegration(id, extensionToIntegration);
69
63
  return {
70
- code: prependJsxImportSource(injectEcoMeta(code, id, integration.name), integration.jsxImportSource)
64
+ code: prependJsxImportSourceIfMissing(
65
+ injectEcoMeta(code, id, integration.name),
66
+ integration.jsxImportSource
67
+ )
71
68
  };
72
69
  }
73
70
  };
@@ -1,10 +1,9 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import path from "node:path";
3
+ import { createJsxImportSourcePragma, filterJsxSourceExtensions } from "./jsx-import-source.utils.js";
3
4
  function createForeignJsxOverridePlugin(options) {
4
- const extensions = options.foreignExtensions.filter((ext) => ext.endsWith(".tsx") || ext.endsWith(".jsx"));
5
- const excludedExtensions = (options.excludeExtensions ?? []).filter(
6
- (ext) => ext.endsWith(".tsx") || ext.endsWith(".jsx")
7
- );
5
+ const extensions = filterJsxSourceExtensions(options.foreignExtensions);
6
+ const excludedExtensions = filterJsxSourceExtensions(options.excludeExtensions ?? []);
8
7
  if (extensions.length === 0) {
9
8
  return {
10
9
  name: options.name ?? "foreign-jsx-override",
@@ -12,8 +11,7 @@ function createForeignJsxOverridePlugin(options) {
12
11
  }
13
12
  };
14
13
  }
15
- const pragma = `/** @jsxImportSource ${options.hostJsxImportSource} */
16
- `;
14
+ const pragma = createJsxImportSourcePragma(options.hostJsxImportSource);
17
15
  const filter = new RegExp(`(${extensions.map((e) => e.replace(".", "\\.")).join("|")})$`);
18
16
  return {
19
17
  name: options.name ?? "foreign-jsx-override",
@@ -6,10 +6,12 @@ import type { EcoPagesElement } from '../types/public-types.js';
6
6
  import type { IntegrationRenderer } from '../route-renderer/orchestration/integration-renderer.js';
7
7
  import { AssetProcessingService } from '../services/assets/asset-processing-service/asset-processing.service.js';
8
8
  import type { AssetDefinition, ProcessedAsset } from '../services/assets/asset-processing-service/assets.types.js';
9
+ import type { StaticExportContext } from '../static-site-generator/static-export-context.js';
9
10
  import type { RuntimeCapabilityDeclaration } from './runtime-capability.js';
10
11
  export type { RuntimeCapabilityDeclaration, RuntimeCapabilityTag } from './runtime-capability.js';
11
12
  export type { EcoBuildLoader, EcoBuildOnLoadArgs, EcoBuildOnLoadResult, EcoBuildOnResolveArgs, EcoBuildOnResolveResult, EcoBuildPlugin, EcoBuildPluginBuilder, } from '../build/build-types.js';
12
13
  export type { PageBrowserGraphContribution, PageBrowserGraphContributionContext } from '../types/public-types.js';
14
+ export type { StaticExportContext } from '../static-site-generator/static-export-context.js';
13
15
  export type { HtmlDocumentContribution, HtmlDocumentContributionContext, } from '../route-renderer/orchestration/integration-renderer.js';
14
16
  /**
15
17
  * Type-erased integration plugin stored in app-level registries.
@@ -47,13 +49,6 @@ export interface IntegrationPluginConfig {
47
49
  * They are not specific to any particular page or component.
48
50
  */
49
51
  integrationDependencies?: AssetDefinition[];
50
- /**
51
- * The strategy to use for static building.
52
- * - 'render': Execute component function directly (faster, efficient).
53
- * - 'fetch': Start server and fetch URL (slower, needed for some SSR like Lit).
54
- * @default 'render'
55
- */
56
- staticBuildStep?: 'render' | 'fetch';
57
52
  /**
58
53
  * Declares runtime-specific requirements that must be satisfied before the
59
54
  * app can start with this integration enabled.
@@ -96,7 +91,6 @@ export declare abstract class IntegrationPlugin<C = EcoPagesElement> {
96
91
  readonly name: string;
97
92
  readonly extensions: string[];
98
93
  abstract renderer: RendererClass<C>;
99
- readonly staticBuildStep: 'render' | 'fetch';
100
94
  readonly runtimeCapability?: RuntimeCapabilityDeclaration;
101
95
  readonly jsxImportSource?: string;
102
96
  protected integrationDependencies: AssetDefinition[];
@@ -199,7 +193,6 @@ export declare abstract class IntegrationPlugin<C = EcoPagesElement> {
199
193
  * Renderers are cheap runtime objects. They receive the finalized app config,
200
194
  * a fresh asset-processing service, integration-global processed assets, and
201
195
  * any renderer module context supplied by the active runtime.
202
- renderer.name ||= this.name;
203
196
  */
204
197
  initializeRenderer(options?: {
205
198
  rendererModules?: unknown;
@@ -213,6 +206,23 @@ export declare abstract class IntegrationPlugin<C = EcoPagesElement> {
213
206
  * `setup()`.
214
207
  */
215
208
  prepareBuildContributions(): Promise<void>;
209
+ /**
210
+ * Reports whether this integration's build inputs changed since the last
211
+ * incremental static build.
212
+ */
213
+ didChange(): boolean;
214
+ /**
215
+ * Runs integration-specific setup before static page generation begins.
216
+ *
217
+ * @remarks
218
+ * Integrations that need build-scoped SSR preload or worker sessions should
219
+ * start them here rather than per-page inside the renderer.
220
+ */
221
+ beforeStaticExport?(_context: StaticExportContext): Promise<void>;
222
+ /**
223
+ * Releases resources started in {@link beforeStaticExport}.
224
+ */
225
+ afterStaticExport?(_context: StaticExportContext): Promise<void>;
216
226
  /**
217
227
  * Performs runtime-only integration setup after config build has already
218
228
  * sealed manifest contributions.
@@ -15,7 +15,6 @@ function assertIntegrationInvariant(condition, message) {
15
15
  class IntegrationPlugin {
16
16
  name;
17
17
  extensions;
18
- staticBuildStep;
19
18
  runtimeCapability;
20
19
  jsxImportSource;
21
20
  integrationDependencies;
@@ -60,7 +59,6 @@ class IntegrationPlugin {
60
59
  this.name = config.name;
61
60
  this.extensions = config.extensions;
62
61
  this.integrationDependencies = config.integrationDependencies || [];
63
- this.staticBuildStep = config.staticBuildStep || "render";
64
62
  this.runtimeCapability = config.runtimeCapability;
65
63
  this.jsxImportSource = config.jsxImportSource;
66
64
  }
@@ -152,7 +150,6 @@ class IntegrationPlugin {
152
150
  * Renderers are cheap runtime objects. They receive the finalized app config,
153
151
  * a fresh asset-processing service, integration-global processed assets, and
154
152
  * any renderer module context supplied by the active runtime.
155
- renderer.name ||= this.name;
156
153
  */
157
154
  initializeRenderer(options) {
158
155
  const renderer = new this.renderer(this.createRendererOptions(options));
@@ -169,6 +166,13 @@ class IntegrationPlugin {
169
166
  */
170
167
  async prepareBuildContributions() {
171
168
  }
169
+ /**
170
+ * Reports whether this integration's build inputs changed since the last
171
+ * incremental static build.
172
+ */
173
+ didChange() {
174
+ return false;
175
+ }
172
176
  /**
173
177
  * Performs runtime-only integration setup after config build has already
174
178
  * sealed manifest contributions.
@@ -180,7 +184,6 @@ class IntegrationPlugin {
180
184
  this.integrationDependencies,
181
185
  this.name
182
186
  );
183
- this.initializeRenderer();
184
187
  }
185
188
  /**
186
189
  * Releases runtime resources owned by the integration.