@ecopages/core 0.2.0-alpha.26 → 0.2.0-alpha.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +63 -7
  3. package/package.json +8 -94
  4. package/src/adapters/bun/create-app.d.ts +1 -0
  5. package/src/adapters/bun/create-app.js +39 -2
  6. package/src/adapters/bun/hmr-manager.d.ts +1 -13
  7. package/src/adapters/bun/hmr-manager.js +1 -22
  8. package/src/adapters/bun/server-adapter.js +23 -4
  9. package/src/adapters/node/node-hmr-manager.d.ts +2 -14
  10. package/src/adapters/node/node-hmr-manager.js +2 -23
  11. package/src/adapters/shared/explicit-static-render-preparation.d.ts +25 -0
  12. package/src/adapters/shared/explicit-static-render-preparation.js +26 -0
  13. package/src/adapters/shared/explicit-static-route-matcher.d.ts +5 -2
  14. package/src/adapters/shared/explicit-static-route-matcher.js +14 -16
  15. package/src/adapters/shared/file-route-middleware-pipeline.d.ts +7 -10
  16. package/src/adapters/shared/file-route-middleware-pipeline.js +2 -11
  17. package/src/adapters/shared/fs-server-response-factory.d.ts +13 -9
  18. package/src/adapters/shared/fs-server-response-factory.js +10 -26
  19. package/src/adapters/shared/fs-server-response-matcher.d.ts +14 -6
  20. package/src/adapters/shared/fs-server-response-matcher.js +67 -28
  21. package/src/adapters/shared/render-context.d.ts +2 -2
  22. package/src/adapters/shared/server-adapter.d.ts +21 -10
  23. package/src/adapters/shared/server-adapter.js +171 -132
  24. package/src/adapters/shared/server-route-handler.d.ts +2 -2
  25. package/src/adapters/shared/server-route-handler.js +1 -1
  26. package/src/adapters/shared/server-static-builder.d.ts +4 -4
  27. package/src/config/README.md +1 -1
  28. package/src/config/config-builder.d.ts +2 -2
  29. package/src/config/config-builder.js +0 -5
  30. package/src/dev/host-runtime.d.ts +10 -0
  31. package/src/dev/host-runtime.js +24 -0
  32. package/src/eco/eco.js +7 -7
  33. package/src/eco/eco.types.d.ts +3 -3
  34. package/src/errors/index.d.ts +1 -0
  35. package/src/errors/index.js +3 -1
  36. package/src/hmr/strategies/js-hmr-strategy.d.ts +0 -5
  37. package/src/integrations/ghtml/ghtml-renderer.d.ts +0 -4
  38. package/src/integrations/ghtml/ghtml-renderer.js +1 -7
  39. package/src/plugins/eco-component-meta-plugin.js +0 -1
  40. package/src/plugins/integration-plugin.d.ts +14 -18
  41. package/src/plugins/integration-plugin.js +14 -21
  42. package/src/plugins/processor.d.ts +2 -0
  43. package/src/plugins/processor.js +6 -1
  44. package/src/route-renderer/GRAPH.md +81 -289
  45. package/src/route-renderer/README.md +67 -105
  46. package/src/route-renderer/orchestration/component-render-context.d.ts +24 -18
  47. package/src/route-renderer/orchestration/component-render-context.js +14 -14
  48. package/src/route-renderer/orchestration/declared-ownership-graph.d.ts +18 -0
  49. package/src/route-renderer/orchestration/declared-ownership-graph.js +34 -0
  50. package/src/route-renderer/orchestration/foreign-subtree-execution.service.d.ts +108 -0
  51. package/src/route-renderer/orchestration/foreign-subtree-execution.service.js +206 -0
  52. package/src/route-renderer/orchestration/integration-renderer.d.ts +96 -136
  53. package/src/route-renderer/orchestration/integration-renderer.js +280 -303
  54. package/src/route-renderer/orchestration/ownership-planning.service.d.ts +24 -0
  55. package/src/route-renderer/orchestration/ownership-planning.service.js +63 -0
  56. package/src/route-renderer/orchestration/ownership-validation.service.d.ts +29 -0
  57. package/src/route-renderer/orchestration/ownership-validation.service.js +53 -0
  58. package/src/route-renderer/orchestration/queued-foreign-subtree-resolution.service.d.ts +90 -0
  59. package/src/route-renderer/orchestration/{queued-boundary-runtime.service.js → queued-foreign-subtree-resolution.service.js} +28 -25
  60. package/src/route-renderer/orchestration/render-output.utils.d.ts +3 -3
  61. package/src/route-renderer/orchestration/render-output.utils.js +6 -6
  62. package/src/route-renderer/orchestration/route-render-orchestrator.d.ts +120 -0
  63. package/src/route-renderer/orchestration/{render-preparation.service.js → route-render-orchestrator.js} +132 -108
  64. package/src/route-renderer/page-loading/component-dependency-collection.js +8 -1
  65. package/src/route-renderer/page-loading/dependency-resolver.js +5 -7
  66. package/src/route-renderer/page-loading/page-dependency-bundling.d.ts +1 -1
  67. package/src/route-renderer/page-loading/page-dependency-bundling.js +41 -19
  68. package/src/route-renderer/route-renderer.d.ts +28 -26
  69. package/src/route-renderer/route-renderer.js +4 -27
  70. package/src/router/README.md +16 -19
  71. package/src/router/server/route-registry.d.ts +78 -0
  72. package/src/router/server/route-registry.js +262 -0
  73. package/src/services/README.md +1 -2
  74. package/src/services/assets/asset-processing-service/assets.types.d.ts +3 -0
  75. package/src/services/assets/asset-processing-service/index.d.ts +1 -0
  76. package/src/services/assets/asset-processing-service/index.js +1 -0
  77. package/src/services/assets/asset-processing-service/page-package.d.ts +3 -0
  78. package/src/services/assets/asset-processing-service/page-package.js +74 -0
  79. package/src/services/assets/asset-processing-service/processors/base/base-script-processor.js +4 -4
  80. package/src/services/assets/asset-processing-service/processors/script/content-script.processor.js +6 -3
  81. package/src/services/assets/asset-processing-service/processors/script/file-script.processor.js +9 -3
  82. package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.js +4 -2
  83. package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +2 -1
  84. package/src/services/assets/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +3 -1
  85. package/src/services/module-loading/node-bootstrap-plugin.js +15 -3
  86. package/src/static-site-generator/static-site-generator.d.ts +20 -21
  87. package/src/static-site-generator/static-site-generator.js +107 -140
  88. package/src/types/internal-types.d.ts +13 -12
  89. package/src/types/public-types.d.ts +46 -36
  90. package/src/watchers/project-watcher.test-helpers.js +5 -5
  91. package/src/route-renderer/orchestration/boundary-planning.service.d.ts +0 -25
  92. package/src/route-renderer/orchestration/boundary-planning.service.js +0 -97
  93. package/src/route-renderer/orchestration/page-packaging.service.d.ts +0 -16
  94. package/src/route-renderer/orchestration/page-packaging.service.js +0 -66
  95. package/src/route-renderer/orchestration/queued-boundary-runtime.service.d.ts +0 -89
  96. package/src/route-renderer/orchestration/render-execution.service.d.ts +0 -43
  97. package/src/route-renderer/orchestration/render-execution.service.js +0 -106
  98. package/src/route-renderer/orchestration/render-preparation.service.d.ts +0 -120
  99. package/src/route-renderer/orchestration/route-shell-composer.service.d.ts +0 -50
  100. package/src/route-renderer/orchestration/route-shell-composer.service.js +0 -81
  101. package/src/router/server/fs-router-scanner.d.ts +0 -41
  102. package/src/router/server/fs-router-scanner.js +0 -161
  103. package/src/router/server/fs-router.d.ts +0 -26
  104. package/src/router/server/fs-router.js +0 -100
  105. package/src/services/runtime-state/runtime-specifier-registry.service.d.ts +0 -69
  106. package/src/services/runtime-state/runtime-specifier-registry.service.js +0 -37
package/CHANGELOG.md CHANGED
@@ -13,6 +13,24 @@ All notable changes to `@ecopages/core` are documented here.
13
13
 
14
14
  ### Refactoring
15
15
 
16
+ - Renamed route-renderer ownership and foreign-child contracts across core so ownership planning, foreign-subtree payloads, and queued foreign-subtree resolution now use the simplified terminology.
17
+ - Introduced a single `RouteRenderFlow` owner for route render preparation and execution, removing the separate execution service seam while keeping boundary planning shared.
18
+ - Narrowed route-render orchestration onto an explicit `RouteRenderFlowAdapter` seam and one structural Html finalization plan, reducing callback-bag plumbing between `RouteRenderFlow` and `IntegrationRenderer`.
19
+ - Renamed renderer-owned page browser asset preparation onto an explicit `buildPageBrowserGraph()` seam so route orchestration no longer treats emitted browser dependencies as a flat route-asset append.
20
+ - Removed the generic HMR runtime-specifier registry and plugin registration seam so core no longer carries import-map-era runtime state that integrations no longer use.
21
+ - Moved foreign-boundary ownership validation out of boundary-plan construction so route root graphs are validated before dependency and data preparation.
22
+ - Moved page-package classification into the asset-processing module so render orchestration no longer carries a dedicated packaging service wrapper.
23
+ - Split file-route page middleware onto its own context contract so page middleware no longer exposes handler-only `ctx.render()` helpers and the pipeline stops carrying fake render traps.
24
+ - Narrowed route-renderer consumers onto explicit resolver contracts, moved filesystem custom 404 rendering back under the filesystem matcher, and shared explicit static render preparation between runtime and static generation.
25
+
26
+ - Added the `@ecopages/core/dev/host-runtime` seam so host integrations such as the Vite plugin use one explicit development bridge instead of importing host-module-loader and invalidation internals directly.
27
+ - Moved extension-facing merge and assertion helpers behind the integration and processor plugin entrypoints so MDX and image processing no longer depend on raw `utils/deep-merge` or `utils/invariant` package paths.
28
+ - Re-exported shared build-plugin authoring types through the integration and processor plugin entrypoints so extension packages depend on plugin surfaces instead of the raw `build/build-types` module.
29
+ - Removed the legacy `@ecopages/core/errors/locals-access-error` and `@ecopages/core/adapters/bun/client-bridge` exports after moving their remaining consumers to the public `errors` and root type surfaces.
30
+ - Removed the unused `@ecopages/core/utils/parse-cli-args` and `@ecopages/core/services/module-loading/app-server-module-transpiler.service` exports from the published package surface.
31
+ - Removed the unused `@ecopages/core/bun/create-app` and `@ecopages/core/route-renderer/template-serialization` exports to keep the published package surface aligned with the documented entrypoints.
32
+ - Removed the legacy `@ecopages/core/internal-types` export now that the public root package exposes the supported `EcoPagesAppConfig` contract.
33
+ - Removed the duplicate `@ecopages/core/router/client/navigation-coordinator` export in favor of the canonical `@ecopages/core/router/navigation-coordinator` subpath.
16
34
  - Bundled page-local component stylesheets and standard file scripts into page-owned assets before processing, reducing per-page asset fan-out in emitted HTML.
17
35
  - Grouped Ecopages JSX page and lazy dependency entries into one multi-entry browser build so shared chunks can be emitted once without relying on the runtime alias vendor path.
18
36
  - Removed the transitional flat dependency write from render preparation so final HTML injection now follows the structured page-package path only.
@@ -22,9 +40,14 @@ All notable changes to `@ecopages/core` are documented here.
22
40
  - Moved shared queued boundary resolution to attachment-policy payloads and constructor-injectable planning services.
23
41
  - Extracted shared page, layout, and document-shell composition into a narrow `RouteShellComposer` while keeping renderer-owned boundary handoff in `IntegrationRenderer`.
24
42
  - Removed marker-era compatibility capture, the shared route-level fallback resolver, deprecated `@ecopages/core/node*` escape hatches, and other dead route-renderer internals.
43
+ - Replaced the split `FSRouter` and `FSRouterScanner` flow with one `RouteRegistry` seam for filesystem route discovery, request matching, and static-generation planning.
25
44
 
26
45
  ### Bug Fixes
27
46
 
47
+ - Fixed integration registry typing so `ConfigBuilder.setIntegrations()` accepts heterogeneous framework plugins without rejecting valid JSX or React integrations at type-check time.
48
+ - Fixed page-owned dependency packaging so final Html output suppresses bundled source stylesheet assets that were reintroduced later during shell-time asset merging.
49
+ - Fixed development page dependency packaging so script Dependencies stay source-backed for HMR instead of being collapsed into one page-owned script bundle.
50
+ - Fixed Bun preview builds to start the static preview server only after static generation releases the live build server port, preventing preview mode from double-binding the configured port.
28
51
  - Fixed router-owned HMR current-page reloads to clear persisted layout caches so active shared layouts pick up updated implementations during development.
29
52
  - Fixed router-owned HMR layout refreshes to reuse the active HMR page entry instead of stale static bootstrap assets during persisted-layout reloads.
30
53
  - Fixed fetch-mode static generation to normalize absolute routes onto the active build runtime origin, restoring preview prerendering for routes discovered from absolute router entries.
@@ -50,12 +73,14 @@ All notable changes to `@ecopages/core` are documented here.
50
73
  ### Documentation
51
74
 
52
75
  - Added architecture and API documentation for config, plugins, services, adapters, HMR, routing, and rendering.
76
+ - Documented that Html-owned dependency assets stay shared while page, layout, and component dependency assets are packaged per route.
53
77
 
54
78
  ### Tests
55
79
 
56
80
  - Added regression coverage for app-owned runtime services, Node fallback paths, and cross-runtime invalidation behavior.
57
81
  - Strengthened the core ghtml integration tests so route and explicit render paths await real outcomes and cover `renderToResponse` behavior.
58
82
  - Added core regression coverage for boundary plans, payload contracts, and typed mixed-boundary context flow.
83
+ - Added router and static-generation regression coverage for `RouteRegistry`, explicit static route expansion, and file-response fallbacks.
59
84
 
60
85
  ---
61
86
 
package/README.md CHANGED
@@ -31,14 +31,14 @@ flowchart TD
31
31
  B --> D[App build manifest]
32
32
  B --> E[Build executor]
33
33
  B --> F[Dev graph service]
34
- B --> G[Runtime specifier registry]
35
- B --> H[Host module loader boundary]
36
- H --> I[PageModuleImportService]
34
+ B --> G[Host module loader boundary]
35
+ G --> H[PageModuleImportService]
36
+ E --> H
37
37
  E --> I
38
- E --> J[BrowserBundleService]
39
- I --> K[Runtime app adapter]
40
- K --> L[Bun adapter or Node adapter]
41
- D --> J
38
+ E --> I[BrowserBundleService]
39
+ H --> J[Runtime app adapter]
40
+ J --> K[Bun adapter or Node adapter]
41
+ D --> I
42
42
  ```
43
43
 
44
44
  ### Development Invalidation And HMR Flow
@@ -178,6 +178,12 @@ export const MyButton = eco.component({
178
178
  });
179
179
  ```
180
180
 
181
+ Dependency ownership affects final asset packaging:
182
+
183
+ - Stylesheets and scripts declared from `eco.html()` stay Html-owned and can be emitted as shared app-wide assets.
184
+ - Stylesheets and scripts declared from Pages, Layouts, or Components are resolved into page-owned assets for the rendered route.
185
+ - This split is intentional. Shared Html assets can be cached across routes, while page-owned assets can change without invalidating the global shell.
186
+
181
187
  ### 5. API Handlers
182
188
 
183
189
  Add server-side routes using `defineApiHandler`. Register them on your `app` instance before starting:
@@ -228,3 +234,53 @@ import { defineApiHandler, defineGroupHandler, eco } from '@ecopages/core';
228
234
  Use runtime-specific subpaths only when you explicitly need Bun-native APIs that bypass the universal abstractions:
229
235
 
230
236
  - `@ecopages/core/bun`
237
+
238
+ ## Entry Point Roles
239
+
240
+ The published subpaths are grouped by architectural role rather than by source folder.
241
+
242
+ ### App Authoring
243
+
244
+ Use these entrypoints when building an Ecopages app:
245
+
246
+ - `@ecopages/core`
247
+ - `@ecopages/core/create-app`
248
+ - `@ecopages/core/config-builder`
249
+ - `@ecopages/core/errors`
250
+ - `@ecopages/core/html`
251
+ - `@ecopages/core/hash`
252
+ - `@ecopages/core/declarations`
253
+ - `@ecopages/core/env`
254
+ - `@ecopages/core/bun`
255
+
256
+ ### Browser Navigation
257
+
258
+ Use these entrypoints when a browser runtime needs to coordinate document ownership and link intent:
259
+
260
+ - `@ecopages/core/router/navigation-coordinator`
261
+ - `@ecopages/core/router/link-intent`
262
+
263
+ ### Extension Authoring
264
+
265
+ Use these entrypoints when implementing integrations, processors, or source transforms:
266
+
267
+ - `@ecopages/core/plugins/integration-plugin`
268
+ - `@ecopages/core/plugins/processor`
269
+ - `@ecopages/core/plugins/source-transform`
270
+ - `@ecopages/core/route-renderer/integration-renderer`
271
+ - `@ecopages/core/services/asset-processing-service`
272
+ - `@ecopages/core/hmr/hmr-strategy`
273
+ - `@ecopages/core/integrations/ghtml`
274
+
275
+ ### Host And Runtime Composition
276
+
277
+ Use these entrypoints only when implementing host adapters or framework-owned bundling seams:
278
+
279
+ - `@ecopages/core/dev/host-runtime`
280
+ - `@ecopages/core/build/build-adapter`
281
+ - `@ecopages/core/build/build-types`
282
+ - `@ecopages/core/build/runtime-specifier-alias-plugin`
283
+ - `@ecopages/core/build/runtime-specifier-aliases`
284
+ - `@ecopages/core/plugins/foreign-jsx-override-plugin`
285
+
286
+ These host-facing entrypoints are narrower compatibility seams. App code and most extensions should prefer the app-authoring or extension-authoring surfaces.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecopages/core",
3
- "version": "0.2.0-alpha.26",
3
+ "version": "0.2.0-alpha.28",
4
4
  "description": "Core package for Ecopages",
5
5
  "keywords": [
6
6
  "ecopages",
@@ -17,7 +17,7 @@
17
17
  "directory": "packages/core"
18
18
  },
19
19
  "dependencies": {
20
- "@ecopages/file-system": "0.2.0-alpha.26",
20
+ "@ecopages/file-system": "0.2.0-alpha.28",
21
21
  "@ecopages/logger": "^0.2.3",
22
22
  "@ecopages/scripts-injector": "^0.1.3",
23
23
  "@worker-tools/html-rewriter": "0.1.0-pre.19",
@@ -51,23 +51,11 @@
51
51
  "types": "./src/router/client/link-intent.d.ts",
52
52
  "default": "./src/router/client/link-intent.js"
53
53
  },
54
- "./router/client/navigation-coordinator": {
55
- "types": "./src/router/client/navigation-coordinator.d.ts",
56
- "default": "./src/router/client/navigation-coordinator.js"
57
- },
58
- "./errors/locals-access-error": {
59
- "types": "./src/errors/locals-access-error.d.ts",
60
- "default": "./src/errors/locals-access-error.js"
61
- },
62
54
  "./eco": {
63
55
  "browser": "./src/eco/eco.browser.js",
64
56
  "types": "./src/eco/eco.d.ts",
65
57
  "default": "./src/eco/eco.js"
66
58
  },
67
- "./route-renderer/template-serialization": {
68
- "types": "./src/route-renderer/orchestration/template-serialization.d.ts",
69
- "default": "./src/route-renderer/orchestration/template-serialization.js"
70
- },
71
59
  "./declarations": {
72
60
  "types": "./src/declarations.d.ts"
73
61
  },
@@ -86,45 +74,18 @@
86
74
  "types": "./src/adapters/bun/index.d.ts",
87
75
  "default": "./src/adapters/bun/index.js"
88
76
  },
89
- "./bun/create-app": {
90
- "types": "./src/adapters/bun/create-app.d.ts",
91
- "default": "./src/adapters/bun/create-app.js"
92
- },
93
77
  "./hmr/hmr-strategy": {
94
78
  "types": "./src/hmr/hmr-strategy.d.ts",
95
79
  "default": "./src/hmr/hmr-strategy.js"
96
80
  },
97
- "./internal-types": {
98
- "types": "./src/types/internal-types.d.ts"
81
+ "./dev/host-runtime": {
82
+ "types": "./src/dev/host-runtime.d.ts",
83
+ "default": "./src/dev/host-runtime.js"
99
84
  },
100
85
  "./services/asset-processing-service": {
101
86
  "types": "./src/services/assets/asset-processing-service/index.d.ts",
102
87
  "default": "./src/services/assets/asset-processing-service/index.js"
103
88
  },
104
- "./services/invalidation/development-invalidation.service": {
105
- "types": "./src/services/invalidation/development-invalidation.service.d.ts",
106
- "default": "./src/services/invalidation/development-invalidation.service.js"
107
- },
108
- "./services/module-loading/app-server-module-transpiler.service": {
109
- "types": "./src/services/module-loading/app-server-module-transpiler.service.d.ts",
110
- "default": "./src/services/module-loading/app-server-module-transpiler.service.js"
111
- },
112
- "./host-module-loader": {
113
- "types": "./src/services/module-loading/host-module-loader-registry.d.ts",
114
- "default": "./src/services/module-loading/host-module-loader-registry.js"
115
- },
116
- "./utils/deep-merge": {
117
- "types": "./src/utils/deep-merge.d.ts",
118
- "default": "./src/utils/deep-merge.js"
119
- },
120
- "./utils/invariant": {
121
- "types": "./src/utils/invariant.d.ts",
122
- "default": "./src/utils/invariant.js"
123
- },
124
- "./utils/parse-cli-args": {
125
- "types": "./src/utils/parse-cli-args.d.ts",
126
- "default": "./src/utils/parse-cli-args.js"
127
- },
128
89
  "./plugins/processor": {
129
90
  "types": "./src/plugins/processor.d.ts",
130
91
  "default": "./src/plugins/processor.js"
@@ -157,10 +118,6 @@
157
118
  "types": "./src/plugins/foreign-jsx-override-plugin.d.ts",
158
119
  "default": "./src/plugins/foreign-jsx-override-plugin.js"
159
120
  },
160
- "./adapters/bun/client-bridge": {
161
- "types": "./src/adapters/bun/client-bridge.d.ts",
162
- "default": "./src/adapters/bun/client-bridge.js"
163
- },
164
121
  "./html": {
165
122
  "import": "./src/utils/html.js",
166
123
  "default": "./src/utils/html.js",
@@ -196,23 +153,11 @@
196
153
  "types": "./src/router/client/link-intent.d.ts",
197
154
  "default": "./src/router/client/link-intent.js"
198
155
  },
199
- "./router/client/navigation-coordinator.ts": {
200
- "types": "./src/router/client/navigation-coordinator.d.ts",
201
- "default": "./src/router/client/navigation-coordinator.js"
202
- },
203
- "./errors/locals-access-error.ts": {
204
- "types": "./src/errors/locals-access-error.d.ts",
205
- "default": "./src/errors/locals-access-error.js"
206
- },
207
156
  "./eco.ts": {
208
157
  "browser": "./src/eco/eco.browser.js",
209
158
  "types": "./src/eco/eco.d.ts",
210
159
  "default": "./src/eco/eco.js"
211
160
  },
212
- "./route-renderer/template-serialization.ts": {
213
- "types": "./src/route-renderer/orchestration/template-serialization.d.ts",
214
- "default": "./src/route-renderer/orchestration/template-serialization.js"
215
- },
216
161
  "./declarations.ts": {
217
162
  "types": "./src/declarations.d.ts"
218
163
  },
@@ -231,45 +176,18 @@
231
176
  "types": "./src/adapters/bun/index.d.ts",
232
177
  "default": "./src/adapters/bun/index.js"
233
178
  },
234
- "./bun/create-app.ts": {
235
- "types": "./src/adapters/bun/create-app.d.ts",
236
- "default": "./src/adapters/bun/create-app.js"
237
- },
238
179
  "./hmr/hmr-strategy.ts": {
239
180
  "types": "./src/hmr/hmr-strategy.d.ts",
240
181
  "default": "./src/hmr/hmr-strategy.js"
241
182
  },
242
- "./internal-types.ts": {
243
- "types": "./src/types/internal-types.d.ts"
183
+ "./dev/host-runtime.ts": {
184
+ "types": "./src/dev/host-runtime.d.ts",
185
+ "default": "./src/dev/host-runtime.js"
244
186
  },
245
187
  "./services/asset-processing-service.ts": {
246
188
  "types": "./src/services/assets/asset-processing-service/index.d.ts",
247
189
  "default": "./src/services/assets/asset-processing-service/index.js"
248
190
  },
249
- "./services/invalidation/development-invalidation.service.ts": {
250
- "types": "./src/services/invalidation/development-invalidation.service.d.ts",
251
- "default": "./src/services/invalidation/development-invalidation.service.js"
252
- },
253
- "./services/module-loading/app-server-module-transpiler.service.ts": {
254
- "types": "./src/services/module-loading/app-server-module-transpiler.service.d.ts",
255
- "default": "./src/services/module-loading/app-server-module-transpiler.service.js"
256
- },
257
- "./host-module-loader.ts": {
258
- "types": "./src/services/module-loading/host-module-loader-registry.d.ts",
259
- "default": "./src/services/module-loading/host-module-loader-registry.js"
260
- },
261
- "./utils/deep-merge.ts": {
262
- "types": "./src/utils/deep-merge.d.ts",
263
- "default": "./src/utils/deep-merge.js"
264
- },
265
- "./utils/invariant.ts": {
266
- "types": "./src/utils/invariant.d.ts",
267
- "default": "./src/utils/invariant.js"
268
- },
269
- "./utils/parse-cli-args.ts": {
270
- "types": "./src/utils/parse-cli-args.d.ts",
271
- "default": "./src/utils/parse-cli-args.js"
272
- },
273
191
  "./plugins/processor.ts": {
274
192
  "types": "./src/plugins/processor.d.ts",
275
193
  "default": "./src/plugins/processor.js"
@@ -302,10 +220,6 @@
302
220
  "types": "./src/plugins/foreign-jsx-override-plugin.d.ts",
303
221
  "default": "./src/plugins/foreign-jsx-override-plugin.js"
304
222
  },
305
- "./adapters/bun/client-bridge.ts": {
306
- "types": "./src/adapters/bun/client-bridge.d.ts",
307
- "default": "./src/adapters/bun/client-bridge.js"
308
- },
309
223
  "./html.ts": {
310
224
  "import": "./src/utils/html.js",
311
225
  "default": "./src/utils/html.js",
@@ -29,6 +29,7 @@ export type BunRouteGroupBuilder<WebSocketData = undefined, TContext extends Api
29
29
  export declare class BunEcopagesApp<WebSocketData = undefined> extends SharedApplicationAdapter<EcopagesAppOptions, Server<WebSocketData>, Request> {
30
30
  serverAdapter: BunServerAdapterResult | undefined;
31
31
  private server;
32
+ private startStaticPreviewServer;
32
33
  fetch(request: Request): Promise<Response>;
33
34
  /**
34
35
  * Complete the initialization of the server adapter by processing dynamic routes
@@ -1,4 +1,5 @@
1
1
  import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT } from "../../config/constants.js";
2
+ import { StaticContentServer } from "../../dev/sc-server.js";
2
3
  import { appLogger } from "../../global/app-logger.js";
3
4
  import { getBunRuntime } from "../../utils/runtime.js";
4
5
  import { SharedApplicationAdapter } from "../shared/application-adapter.js";
@@ -6,6 +7,31 @@ import { createBunServerAdapter } from "./server-adapter.js";
6
7
  class BunEcopagesApp extends SharedApplicationAdapter {
7
8
  serverAdapter;
8
9
  server = null;
10
+ async startStaticPreviewServer(port, hostname) {
11
+ await new Promise((resolve) => setTimeout(resolve, 100));
12
+ for (let attempt = 0; attempt < 20; attempt += 1) {
13
+ try {
14
+ const previewServer = StaticContentServer.createServer({
15
+ appConfig: this.appConfig,
16
+ options: { port }
17
+ });
18
+ if (previewServer.server?.port) {
19
+ appLogger.info(`Preview running at http://${hostname}:${previewServer.server.port}`);
20
+ return;
21
+ }
22
+ break;
23
+ } catch (error) {
24
+ const errorMessage = error instanceof Error ? error.message : String(error);
25
+ const errorCode = typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
26
+ const isPortReleaseRace = errorCode === "EADDRINUSE" || errorMessage.includes("EADDRINUSE");
27
+ if (!isPortReleaseRace || attempt === 19) {
28
+ throw error;
29
+ }
30
+ await new Promise((resolve) => setTimeout(resolve, 100));
31
+ }
32
+ }
33
+ appLogger.error("Failed to start preview server");
34
+ }
9
35
  async fetch(request) {
10
36
  if (!this.serverAdapter) {
11
37
  this.serverAdapter = await this.initializeServerAdapter();
@@ -82,11 +108,17 @@ class BunEcopagesApp extends SharedApplicationAdapter {
82
108
  }
83
109
  const enableHmr = dev || !preview && !build;
84
110
  const serverOptions = this.serverAdapter.getServerOptions({ enableHmr });
111
+ const configuredHostname = String(serverOptions.hostname ?? DEFAULT_ECOPAGES_HOSTNAME);
112
+ const configuredPort = Number(serverOptions.port ?? DEFAULT_ECOPAGES_PORT);
113
+ const runtimeServerOptions = (preview || build) && requiresFetchRuntime ? {
114
+ ...serverOptions,
115
+ port: 0
116
+ } : serverOptions;
85
117
  const bun = getBunRuntime();
86
118
  if (!bun) {
87
119
  throw new Error("Bun runtime is required for the Bun adapter");
88
120
  }
89
- const bunServer = bun.serve(serverOptions);
121
+ const bunServer = bun.serve(runtimeServerOptions);
90
122
  this.server = bunServer;
91
123
  await this.serverAdapter.completeInitialization(this.server).catch((error) => {
92
124
  appLogger.error(`Failed to complete initialization: ${error}`);
@@ -97,8 +129,13 @@ class BunEcopagesApp extends SharedApplicationAdapter {
97
129
  appLogger.info(`Server running at http://${this.server.hostname}:${this.server.port}`);
98
130
  if (build || preview) {
99
131
  appLogger.debugTime("Building static pages");
100
- await this.serverAdapter.buildStatic({ preview });
132
+ await this.serverAdapter.buildStatic({ preview: false });
101
133
  this.server.stop(true);
134
+ if (preview) {
135
+ const previewHostname = configuredHostname;
136
+ const previewPort = configuredPort;
137
+ await this.startStaticPreviewServer(previewPort, previewHostname);
138
+ }
102
139
  appLogger.debugTimeEnd("Building static pages");
103
140
  if (build) {
104
141
  process.exit(0);
@@ -36,7 +36,6 @@ export declare class HmrManager implements IHmrManager {
36
36
  private readonly entrypointRegistrar;
37
37
  private readonly browserBundleService;
38
38
  private readonly entrypointDependencyGraph;
39
- private readonly runtimeSpecifierRegistry;
40
39
  private readonly serverModuleTranspiler;
41
40
  private wsHandler;
42
41
  constructor({ appConfig, bridge }: HmrManagerParams);
@@ -70,16 +69,6 @@ export declare class HmrManager implements IHmrManager {
70
69
  setPlugins(plugins: EcoBuildPlugin[]): void;
71
70
  setEnabled(enabled: boolean): void;
72
71
  isEnabled(): boolean;
73
- /**
74
- * Registers runtime bare-specifier mappings exposed by integrations.
75
- *
76
- * @remarks
77
- * These mappings are consumed by framework-owned HMR strategies that preserve
78
- * shared runtime imports in browser bundles. The registry stays generic so
79
- * these mappings can later support broader import-map-style runtime features
80
- * without moving integration semantics into core.
81
- */
82
- registerSpecifierMap(map: Record<string, string>): void;
83
72
  getWebSocketHandler(): BunSocketHandler;
84
73
  /**
85
74
  * Builds the client-side HMR runtime script.
@@ -90,7 +79,6 @@ export declare class HmrManager implements IHmrManager {
90
79
  handleFileChange(filePath: string, options?: HandleFileChangeOptions): Promise<void>;
91
80
  getOutputUrl(entrypointPath: string): string | undefined;
92
81
  getWatchedFiles(): Map<string, string>;
93
- getSpecifierMap(): Map<string, string>;
94
82
  getDistDir(): string;
95
83
  getPlugins(): EcoBuildPlugin[];
96
84
  getDefaultContext(): DefaultHmrContext;
@@ -136,7 +124,7 @@ export declare class HmrManager implements IHmrManager {
136
124
  * @remarks
137
125
  * Emitted `_hmr` files remain on disk because parallel app processes may share
138
126
  * the same dist directory. The in-memory indexes are cleared so stale
139
- * entrypoints and specifier maps cannot leak through a reused manager object.
127
+ * entrypoints cannot leak through a reused manager object.
140
128
  */
141
129
  stop(): void;
142
130
  }
@@ -15,7 +15,6 @@ import {
15
15
  NoopEntrypointDependencyGraph,
16
16
  setAppEntrypointDependencyGraph
17
17
  } from "../../services/runtime-state/entrypoint-dependency-graph.service.js";
18
- import { getAppRuntimeSpecifierRegistry } from "../../services/runtime-state/runtime-specifier-registry.service.js";
19
18
  import { resolveInternalExecutionDir, resolveInternalWorkDir } from "../../utils/resolve-work-dir.js";
20
19
  class HmrManager {
21
20
  static entrypointRegistrationTimeoutMs = 4e3;
@@ -33,7 +32,6 @@ class HmrManager {
33
32
  entrypointRegistrar;
34
33
  browserBundleService;
35
34
  entrypointDependencyGraph;
36
- runtimeSpecifierRegistry;
37
35
  serverModuleTranspiler;
38
36
  wsHandler;
39
37
  constructor({ appConfig, bridge }) {
@@ -52,7 +50,6 @@ class HmrManager {
52
50
  const existingEntrypointDependencyGraph = getAppEntrypointDependencyGraph(appConfig);
53
51
  this.entrypointDependencyGraph = existingEntrypointDependencyGraph instanceof NoopEntrypointDependencyGraph ? existingEntrypointDependencyGraph : new NoopEntrypointDependencyGraph();
54
52
  setAppEntrypointDependencyGraph(this.appConfig, this.entrypointDependencyGraph);
55
- this.runtimeSpecifierRegistry = getAppRuntimeSpecifierRegistry(this.appConfig);
56
53
  this.serverModuleTranspiler = getAppServerModuleTranspiler(this.appConfig);
57
54
  this.cleanDistDir();
58
55
  this.initializeStrategies();
@@ -94,7 +91,6 @@ class HmrManager {
94
91
  initializeStrategies() {
95
92
  const jsContext = {
96
93
  getWatchedFiles: () => this.watchedFiles,
97
- getSpecifierMap: () => this.runtimeSpecifierRegistry.getAll(),
98
94
  getDistDir: () => this.distDir,
99
95
  getPlugins: () => this.plugins,
100
96
  getSrcDir: () => this.appConfig.absolutePaths.srcDir,
@@ -124,18 +120,6 @@ class HmrManager {
124
120
  isEnabled() {
125
121
  return this.enabled;
126
122
  }
127
- /**
128
- * Registers runtime bare-specifier mappings exposed by integrations.
129
- *
130
- * @remarks
131
- * These mappings are consumed by framework-owned HMR strategies that preserve
132
- * shared runtime imports in browser bundles. The registry stays generic so
133
- * these mappings can later support broader import-map-style runtime features
134
- * without moving integration semantics into core.
135
- */
136
- registerSpecifierMap(map) {
137
- this.runtimeSpecifierRegistry.register(map);
138
- }
139
123
  getWebSocketHandler() {
140
124
  const open = (ws) => {
141
125
  this.bridge.subscribe(ws);
@@ -211,9 +195,6 @@ class HmrManager {
211
195
  getWatchedFiles() {
212
196
  return this.watchedFiles;
213
197
  }
214
- getSpecifierMap() {
215
- return this.runtimeSpecifierRegistry.getAll();
216
- }
217
198
  getDistDir() {
218
199
  return this.distDir;
219
200
  }
@@ -223,7 +204,6 @@ class HmrManager {
223
204
  getDefaultContext() {
224
205
  return {
225
206
  getWatchedFiles: () => this.watchedFiles,
226
- getSpecifierMap: () => this.runtimeSpecifierRegistry.getAll(),
227
207
  getDistDir: () => this.distDir,
228
208
  getPlugins: () => this.plugins,
229
209
  getSrcDir: () => this.appConfig.absolutePaths.srcDir,
@@ -314,7 +294,7 @@ class HmrManager {
314
294
  * @remarks
315
295
  * Emitted `_hmr` files remain on disk because parallel app processes may share
316
296
  * the same dist directory. The in-memory indexes are cleared so stale
317
- * entrypoints and specifier maps cannot leak through a reused manager object.
297
+ * entrypoints cannot leak through a reused manager object.
318
298
  */
319
299
  stop() {
320
300
  this.entrypointRegistrations.clear();
@@ -323,7 +303,6 @@ class HmrManager {
323
303
  }
324
304
  this.watchers.clear();
325
305
  this.watchedFiles.clear();
326
- this.runtimeSpecifierRegistry.clear();
327
306
  this.entrypointDependencyGraph.reset();
328
307
  this.plugins = [];
329
308
  }
@@ -6,6 +6,7 @@ import { fileSystem } from "@ecopages/file-system";
6
6
  import { SharedServerAdapter } from "../shared/server-adapter.js";
7
7
  import { ApiResponseBuilder } from "../shared/api-response.js";
8
8
  import { installSharedRuntimeBuildExecutor } from "../shared/runtime-bootstrap.js";
9
+ import { StaticContentServer } from "../../dev/sc-server.js";
9
10
  import { ServerRouteHandler } from "../shared/server-route-handler.js";
10
11
  import { ServerStaticBuilder } from "../shared/server-static-builder.js";
11
12
  import {
@@ -253,11 +254,29 @@ class BunServerAdapter extends SharedServerAdapter {
253
254
  hmrManager: this.hmrManager
254
255
  });
255
256
  }
256
- await this.staticBuilder.build(options, {
257
- router: this.router,
258
- routeRendererFactory: this.routeRendererFactory,
259
- staticRoutes: this.staticRoutes
257
+ const buildRuntimeOrigin = this.serverInstance ? `http://${this.serverInstance.hostname || DEFAULT_ECOPAGES_HOSTNAME}:${this.serverInstance.port || DEFAULT_ECOPAGES_PORT}` : void 0;
258
+ await this.staticBuilder.build(
259
+ { ...options, preview: false, baseUrl: buildRuntimeOrigin },
260
+ {
261
+ router: this.router,
262
+ routeRendererFactory: this.routeRendererFactory,
263
+ staticRoutes: this.staticRoutes
264
+ }
265
+ );
266
+ if (!options?.preview) {
267
+ return;
268
+ }
269
+ const previewHostname = this.serveOptions.hostname || DEFAULT_ECOPAGES_HOSTNAME;
270
+ const previewPort = Number(this.serveOptions.port || DEFAULT_ECOPAGES_PORT);
271
+ const previewServer = StaticContentServer.createServer({
272
+ appConfig: this.appConfig,
273
+ options: { port: previewPort }
260
274
  });
275
+ if (previewServer.server?.port) {
276
+ appLogger.info(`Preview running at http://${previewHostname}:${previewServer.server.port}`);
277
+ return;
278
+ }
279
+ appLogger.error("Failed to start preview server");
261
280
  }
262
281
  /**
263
282
  * Initializes the server with dynamic routes after server creation.
@@ -36,7 +36,6 @@ export declare class NodeHmrManager implements IHmrManager {
36
36
  private readonly entrypointRegistrar;
37
37
  private readonly browserBundleService;
38
38
  private readonly entrypointDependencyGraph;
39
- private readonly runtimeSpecifierRegistry;
40
39
  private readonly serverModuleTranspiler;
41
40
  constructor({ appConfig, bridge }: NodeHmrManagerParams);
42
41
  /**
@@ -60,23 +59,12 @@ export declare class NodeHmrManager implements IHmrManager {
60
59
  setPlugins(plugins: EcoBuildPlugin[]): void;
61
60
  setEnabled(enabled: boolean): void;
62
61
  isEnabled(): boolean;
63
- /**
64
- * Registers runtime bare-specifier mappings exposed by integrations.
65
- *
66
- * @remarks
67
- * These mappings are consumed by framework-owned HMR strategies such as the
68
- * React integration strategy when they rewrite browser bundles. The registry
69
- * stays generic so the same mappings can support broader import-map-style
70
- * runtime features later without moving integration semantics into core.
71
- */
72
- registerSpecifierMap(map: Record<string, string>): void;
73
62
  buildRuntime(): Promise<void>;
74
63
  getRuntimePath(): string;
75
64
  broadcast(event: ClientBridgeEvent): void;
76
65
  handleFileChange(filePath: string, options?: HandleFileChangeOptions): Promise<void>;
77
66
  getOutputUrl(entrypointPath: string): string | undefined;
78
67
  getWatchedFiles(): Map<string, string>;
79
- getSpecifierMap(): Map<string, string>;
80
68
  getDistDir(): string;
81
69
  getPlugins(): EcoBuildPlugin[];
82
70
  getDefaultContext(): DefaultHmrContext;
@@ -125,8 +113,8 @@ export declare class NodeHmrManager implements IHmrManager {
125
113
  * @remarks
126
114
  * The manager intentionally does not remove emitted `_hmr` files from disk
127
115
  * because multiple app processes may share the same dist directory during test
128
- * runs. It does clear in-memory indexes so old entrypoints, dependencies, and
129
- * specifier maps cannot leak across a reused manager instance.
116
+ * runs. It does clear in-memory indexes so old entrypoints and dependencies
117
+ * cannot leak across a reused manager instance.
130
118
  */
131
119
  stop(): void;
132
120
  }