@ecopages/core 0.2.0-alpha.4 → 0.2.0-alpha.6
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.
- package/README.md +213 -12
- package/package.json +100 -188
- package/src/adapters/README.md +39 -0
- package/src/adapters/bun/hmr-manager.test.ts +267 -0
- package/src/adapters/bun/hmr-manager.ts +181 -68
- package/src/adapters/bun/index.ts +1 -2
- package/src/adapters/bun/server-adapter.ts +41 -34
- package/src/adapters/bun/server-lifecycle.ts +40 -70
- package/src/adapters/index.ts +1 -1
- package/src/adapters/node/bootstrap-dependency-resolver.test.ts +282 -0
- package/src/adapters/node/bootstrap-dependency-resolver.ts +301 -0
- package/src/adapters/node/index.ts +7 -0
- package/src/adapters/node/node-client-bridge.test.ts +198 -0
- package/src/adapters/node/node-hmr-manager.test.ts +322 -0
- package/src/adapters/node/node-hmr-manager.ts +208 -116
- package/src/adapters/node/runtime-adapter.test.ts +868 -0
- package/src/adapters/node/runtime-adapter.ts +439 -0
- package/src/adapters/node/server-adapter.ts +31 -104
- package/src/adapters/node/static-content-server.test.ts +60 -0
- package/src/adapters/node/static-content-server.ts +36 -0
- package/src/adapters/node/write-runtime-manifest.ts +38 -0
- package/src/adapters/shared/api-response.test.ts +97 -0
- package/src/{define-api-handler.ts → adapters/shared/define-api-handler.ts} +1 -1
- package/src/adapters/shared/explicit-static-route-matcher.test.ts +381 -0
- package/src/adapters/shared/explicit-static-route-matcher.ts +7 -1
- package/src/adapters/shared/file-route-middleware-pipeline.test.ts +90 -0
- package/src/adapters/shared/file-route-middleware-pipeline.ts +6 -2
- package/src/adapters/shared/fs-server-response-factory.test.ts +187 -0
- package/src/adapters/shared/fs-server-response-matcher.test.ts +286 -0
- package/src/adapters/shared/fs-server-response-matcher.ts +17 -10
- package/src/adapters/shared/hmr-entrypoint-registrar.ts +149 -0
- package/src/adapters/shared/hmr-html-response.ts +52 -0
- package/src/adapters/shared/hmr-manager.contract.test.ts +196 -0
- package/src/adapters/shared/hmr-manager.dispatch.test.ts +220 -0
- package/src/adapters/shared/render-context.test.ts +146 -0
- package/src/adapters/shared/render-context.ts +21 -6
- package/src/adapters/shared/runtime-bootstrap.ts +79 -0
- package/src/adapters/shared/server-adapter.test.ts +77 -0
- package/src/adapters/shared/server-adapter.ts +51 -4
- package/src/adapters/shared/server-route-handler.test.ts +110 -0
- package/src/adapters/shared/server-route-handler.ts +5 -18
- package/src/adapters/shared/server-static-builder.test.ts +316 -0
- package/src/adapters/shared/server-static-builder.ts +92 -8
- package/src/build/README.md +101 -0
- package/src/build/build-adapter-serialization.test.ts +268 -0
- package/src/build/build-adapter.test.ts +815 -0
- package/src/build/build-adapter.ts +235 -6
- package/src/build/build-manifest.ts +54 -0
- package/src/build/dev-build-coordinator.ts +221 -0
- package/src/build/esbuild-build-adapter.ts +132 -83
- package/src/build/runtime-build-executor.ts +34 -0
- package/src/build/runtime-specifier-alias-plugin.test.ts +43 -0
- package/src/build/runtime-specifier-alias-plugin.ts +58 -0
- package/src/config/README.md +33 -0
- package/src/config/config-builder.test.ts +410 -0
- package/src/config/config-builder.ts +281 -49
- package/src/constants.ts +15 -0
- package/src/declarations.d.ts +18 -13
- package/src/eco/README.md +70 -16
- package/src/eco/component-render-context.ts +39 -17
- package/src/eco/eco.test.ts +678 -0
- package/src/eco/eco.ts +29 -8
- package/src/eco/eco.types.ts +20 -1
- package/src/eco/eco.utils.test.ts +124 -0
- package/src/eco/global-injector-map.test.ts +42 -0
- package/src/eco/lazy-injector-map.test.ts +66 -0
- package/src/eco/module-dependencies.test.ts +30 -0
- package/src/errors/http-error.test.ts +134 -0
- package/src/global/utils.test.ts +12 -0
- package/src/hmr/README.md +26 -0
- package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-have-HMR-script-injected-in-page-1.png +0 -0
- package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-load-fixture-app-page-1.png +0 -0
- package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-WebSocket-Connection-should-connect-to-correct-HMR-endpoint-1.png +0 -0
- package/src/hmr/client/hmr-runtime.ts +38 -7
- package/src/hmr/hmr-strategy.test.ts +124 -0
- package/src/hmr/hmr.postcss.test.e2e.ts +41 -0
- package/src/hmr/hmr.test.e2e.ts +29 -38
- package/src/hmr/strategies/js-hmr-strategy.test.ts +335 -0
- package/src/hmr/strategies/js-hmr-strategy.ts +115 -115
- package/src/index.ts +1 -1
- package/src/integrations/ghtml/ghtml-renderer.test.ts +63 -0
- package/src/integrations/ghtml/ghtml-renderer.ts +4 -1
- package/src/internal-types.ts +39 -19
- package/src/plugins/README.md +34 -0
- package/src/plugins/alias-resolver-plugin.test.ts +41 -0
- package/src/plugins/alias-resolver-plugin.ts +21 -3
- package/src/plugins/eco-component-meta-plugin.test.ts +380 -0
- package/src/plugins/eco-component-meta-plugin.ts +10 -3
- package/src/plugins/integration-plugin.test.ts +111 -0
- package/src/plugins/integration-plugin.ts +45 -3
- package/src/plugins/processor.test.ts +148 -0
- package/src/plugins/processor.ts +22 -2
- package/src/plugins/runtime-capability.ts +14 -0
- package/src/public-types.ts +73 -16
- package/src/route-renderer/GRAPH.md +16 -20
- package/src/route-renderer/README.md +8 -21
- package/src/route-renderer/component-graph/component-graph-executor.test.ts +41 -0
- package/src/route-renderer/component-graph/component-graph.test.ts +63 -0
- package/src/route-renderer/component-graph/component-marker.test.ts +73 -0
- package/src/route-renderer/component-graph/component-reference.ts +29 -0
- package/src/route-renderer/component-graph/marker-graph-resolver.test.ts +135 -0
- package/src/route-renderer/{marker-graph-resolver.ts → component-graph/marker-graph-resolver.ts} +11 -9
- package/src/route-renderer/orchestration/integration-renderer.test.ts +936 -0
- package/src/route-renderer/{integration-renderer.ts → orchestration/integration-renderer.ts} +113 -19
- package/src/route-renderer/orchestration/render-execution.service.test.ts +97 -0
- package/src/route-renderer/{render-execution.service.ts → orchestration/render-execution.service.ts} +109 -37
- package/src/route-renderer/orchestration/render-preparation.service.test.ts +235 -0
- package/src/route-renderer/{render-preparation.service.ts → orchestration/render-preparation.service.ts} +127 -9
- package/src/route-renderer/page-loading/dependency-resolver.test.ts +345 -0
- package/src/route-renderer/{dependency-resolver.ts → page-loading/dependency-resolver.ts} +28 -12
- package/src/route-renderer/page-loading/page-module-loader.test.ts +96 -0
- package/src/route-renderer/{page-module-loader.ts → page-loading/page-module-loader.ts} +49 -21
- package/src/route-renderer/route-renderer.ts +36 -1
- package/src/router/README.md +26 -0
- package/src/router/client/link-intent.d.ts +53 -0
- package/src/router/client/link-intent.test.browser.ts +51 -0
- package/src/router/client/link-intent.ts +92 -0
- package/src/router/client/navigation-coordinator.test.ts +237 -0
- package/src/router/client/navigation-coordinator.ts +433 -0
- package/src/router/server/fs-router-scanner.test.ts +83 -0
- package/src/router/{fs-router-scanner.ts → server/fs-router-scanner.ts} +12 -10
- package/src/router/server/fs-router.test.ts +214 -0
- package/src/router/{fs-router.ts → server/fs-router.ts} +2 -2
- package/src/services/README.md +29 -0
- package/src/services/assets/asset-processing-service/asset-processing.service.test.ts +385 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/asset-processing.service.ts +101 -6
- package/src/services/assets/asset-processing-service/asset.factory.test.ts +63 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/asset.factory.ts +2 -2
- package/src/services/{asset-processing-service → assets/asset-processing-service}/assets.types.ts +2 -1
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.test.ts +72 -0
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.ts +95 -0
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.test.ts +67 -0
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.ts +78 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/index.ts +2 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.interface.ts +1 -1
- package/src/services/assets/asset-processing-service/processors/base/base-processor.test.ts +59 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-processor.ts +11 -5
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-script-processor.ts +17 -27
- package/src/services/assets/asset-processing-service/processors/script/file-script.processor.test.ts +286 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/file-script.processor.ts +3 -3
- package/src/services/assets/asset-processing-service/processors/script/node-module-script.processor.test.ts +227 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/node-module-script.processor.ts +5 -4
- package/src/services/assets/asset-processing-service/processors/stylesheet/content-stylesheet.processor.test.ts +199 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/file-stylesheet.processor.ts +4 -1
- package/src/services/assets/browser-bundle.service.test.ts +36 -0
- package/src/services/assets/browser-bundle.service.ts +53 -0
- package/src/services/cache/index.ts +3 -3
- package/src/services/cache/memory-cache-store.test.ts +225 -0
- package/src/services/cache/memory-cache-store.ts +1 -1
- package/src/services/cache/page-cache-service.test.ts +175 -0
- package/src/services/cache/page-cache-service.ts +3 -3
- package/src/services/cache/page-request-cache-coordinator.service.test.ts +79 -0
- package/src/services/{page-request-cache-coordinator.service.ts → cache/page-request-cache-coordinator.service.ts} +9 -6
- package/src/services/html/html-rewriter-provider.service.test.ts +183 -0
- package/src/services/html/html-rewriter-provider.service.ts +103 -0
- package/src/services/html/html-transformer.service.test.ts +378 -0
- package/src/services/html/html-transformer.service.ts +279 -0
- package/src/services/invalidation/development-invalidation.service.test.ts +77 -0
- package/src/services/invalidation/development-invalidation.service.ts +261 -0
- package/src/services/module-loading/app-server-module-transpiler.service.ts +52 -0
- package/src/services/module-loading/page-module-import.service.test.ts +253 -0
- package/src/services/module-loading/page-module-import.service.ts +200 -0
- package/src/services/module-loading/server-loader.service.test.ts +161 -0
- package/src/services/module-loading/server-loader.service.ts +130 -0
- package/src/services/module-loading/server-module-transpiler.service.test.ts +115 -0
- package/src/services/module-loading/server-module-transpiler.service.ts +105 -0
- package/src/services/runtime-manifest/node-runtime-manifest.service.test.ts +95 -0
- package/src/services/runtime-manifest/node-runtime-manifest.service.ts +101 -0
- package/src/services/runtime-state/dev-graph.service.ts +217 -0
- package/src/services/runtime-state/entrypoint-dependency-graph.service.ts +136 -0
- package/src/services/runtime-state/runtime-specifier-registry.service.ts +96 -0
- package/src/services/runtime-state/server-invalidation-state.service.ts +68 -0
- package/src/services/validation/schema-validation-service.test.ts +223 -0
- package/src/services/{schema-validation-service.ts → validation/schema-validation-service.ts} +1 -1
- package/src/static-site-generator/README.md +26 -0
- package/src/static-site-generator/static-site-generator.test.ts +307 -0
- package/src/static-site-generator/static-site-generator.ts +109 -6
- package/src/utils/deep-merge.test.ts +114 -0
- package/src/utils/invariant.test.ts +22 -0
- package/src/utils/path-utils.test.ts +15 -0
- package/src/utils/resolve-work-dir.ts +45 -0
- package/src/utils/server-utils.test.ts +38 -0
- package/src/watchers/project-watcher.integration.test.ts +337 -0
- package/src/watchers/project-watcher.test-helpers.ts +1 -1
- package/src/watchers/project-watcher.test.ts +678 -0
- package/src/watchers/project-watcher.ts +130 -111
- package/CHANGELOG.md +0 -91
- package/src/adapters/abstract/application-adapter.d.ts +0 -168
- package/src/adapters/abstract/application-adapter.js +0 -109
- package/src/adapters/abstract/router-adapter.d.ts +0 -26
- package/src/adapters/abstract/router-adapter.js +0 -5
- package/src/adapters/abstract/server-adapter.d.ts +0 -69
- package/src/adapters/abstract/server-adapter.js +0 -15
- package/src/adapters/bun/client-bridge.d.ts +0 -34
- package/src/adapters/bun/client-bridge.js +0 -48
- package/src/adapters/bun/create-app.d.ts +0 -60
- package/src/adapters/bun/create-app.js +0 -117
- package/src/adapters/bun/define-api-handler.d.ts +0 -61
- package/src/adapters/bun/define-api-handler.js +0 -15
- package/src/adapters/bun/define-api-handler.ts +0 -114
- package/src/adapters/bun/hmr-manager.d.ts +0 -85
- package/src/adapters/bun/hmr-manager.js +0 -240
- package/src/adapters/bun/index.d.ts +0 -3
- package/src/adapters/bun/index.js +0 -8
- package/src/adapters/bun/server-adapter.d.ts +0 -155
- package/src/adapters/bun/server-adapter.js +0 -368
- package/src/adapters/bun/server-lifecycle.d.ts +0 -52
- package/src/adapters/bun/server-lifecycle.js +0 -120
- package/src/adapters/index.d.ts +0 -6
- package/src/adapters/index.js +0 -14
- package/src/adapters/node/create-app.d.ts +0 -21
- package/src/adapters/node/create-app.js +0 -143
- package/src/adapters/node/index.d.ts +0 -4
- package/src/adapters/node/index.js +0 -8
- package/src/adapters/node/node-client-bridge.d.ts +0 -26
- package/src/adapters/node/node-client-bridge.js +0 -66
- package/src/adapters/node/node-hmr-manager.d.ts +0 -63
- package/src/adapters/node/node-hmr-manager.js +0 -237
- package/src/adapters/node/server-adapter.d.ts +0 -190
- package/src/adapters/node/server-adapter.js +0 -420
- package/src/adapters/node/static-content-server.d.ts +0 -24
- package/src/adapters/node/static-content-server.js +0 -166
- package/src/adapters/shared/api-response.d.ts +0 -52
- package/src/adapters/shared/api-response.js +0 -96
- package/src/adapters/shared/application-adapter.d.ts +0 -18
- package/src/adapters/shared/application-adapter.js +0 -90
- package/src/adapters/shared/explicit-static-route-matcher.d.ts +0 -38
- package/src/adapters/shared/explicit-static-route-matcher.js +0 -100
- package/src/adapters/shared/file-route-middleware-pipeline.d.ts +0 -65
- package/src/adapters/shared/file-route-middleware-pipeline.js +0 -98
- package/src/adapters/shared/fs-server-response-factory.d.ts +0 -19
- package/src/adapters/shared/fs-server-response-factory.js +0 -97
- package/src/adapters/shared/fs-server-response-matcher.d.ts +0 -71
- package/src/adapters/shared/fs-server-response-matcher.js +0 -155
- package/src/adapters/shared/render-context.d.ts +0 -14
- package/src/adapters/shared/render-context.js +0 -69
- package/src/adapters/shared/server-adapter.d.ts +0 -87
- package/src/adapters/shared/server-adapter.js +0 -353
- package/src/adapters/shared/server-route-handler.d.ts +0 -89
- package/src/adapters/shared/server-route-handler.js +0 -120
- package/src/adapters/shared/server-static-builder.d.ts +0 -38
- package/src/adapters/shared/server-static-builder.js +0 -46
- package/src/build/build-adapter.d.ts +0 -74
- package/src/build/build-adapter.js +0 -54
- package/src/build/build-types.d.ts +0 -57
- package/src/build/build-types.js +0 -0
- package/src/build/esbuild-build-adapter.d.ts +0 -69
- package/src/build/esbuild-build-adapter.js +0 -390
- package/src/config/config-builder.d.ts +0 -227
- package/src/config/config-builder.js +0 -392
- package/src/constants.d.ts +0 -32
- package/src/constants.js +0 -21
- package/src/create-app.d.ts +0 -17
- package/src/create-app.js +0 -66
- package/src/define-api-handler.d.ts +0 -25
- package/src/define-api-handler.js +0 -15
- package/src/dev/sc-server.d.ts +0 -30
- package/src/dev/sc-server.js +0 -111
- package/src/eco/component-render-context.d.ts +0 -105
- package/src/eco/component-render-context.js +0 -77
- package/src/eco/eco.d.ts +0 -9
- package/src/eco/eco.js +0 -110
- package/src/eco/eco.types.d.ts +0 -170
- package/src/eco/eco.types.js +0 -0
- package/src/eco/eco.utils.d.ts +0 -40
- package/src/eco/eco.utils.js +0 -40
- package/src/eco/global-injector-map.d.ts +0 -16
- package/src/eco/global-injector-map.js +0 -80
- package/src/eco/lazy-injector-map.d.ts +0 -8
- package/src/eco/lazy-injector-map.js +0 -70
- package/src/eco/module-dependencies.d.ts +0 -18
- package/src/eco/module-dependencies.js +0 -49
- package/src/errors/http-error.d.ts +0 -31
- package/src/errors/http-error.js +0 -50
- package/src/errors/index.d.ts +0 -2
- package/src/errors/index.js +0 -4
- package/src/errors/locals-access-error.d.ts +0 -4
- package/src/errors/locals-access-error.js +0 -9
- package/src/global/app-logger.d.ts +0 -2
- package/src/global/app-logger.js +0 -6
- package/src/hmr/client/hmr-runtime.d.ts +0 -10
- package/src/hmr/client/hmr-runtime.js +0 -86
- package/src/hmr/hmr-strategy.d.ts +0 -159
- package/src/hmr/hmr-strategy.js +0 -29
- package/src/hmr/hmr.test.e2e.d.ts +0 -1
- package/src/hmr/hmr.test.e2e.js +0 -50
- package/src/hmr/strategies/default-hmr-strategy.d.ts +0 -43
- package/src/hmr/strategies/default-hmr-strategy.js +0 -34
- package/src/hmr/strategies/js-hmr-strategy.d.ts +0 -136
- package/src/hmr/strategies/js-hmr-strategy.js +0 -188
- package/src/index.browser.d.ts +0 -3
- package/src/index.browser.js +0 -4
- package/src/index.d.ts +0 -5
- package/src/index.js +0 -10
- package/src/integrations/ghtml/ghtml-renderer.d.ts +0 -15
- package/src/integrations/ghtml/ghtml-renderer.js +0 -60
- package/src/integrations/ghtml/ghtml.plugin.d.ts +0 -20
- package/src/integrations/ghtml/ghtml.plugin.js +0 -21
- package/src/internal-types.d.ts +0 -200
- package/src/internal-types.js +0 -0
- package/src/plugins/alias-resolver-plugin.d.ts +0 -2
- package/src/plugins/alias-resolver-plugin.js +0 -39
- package/src/plugins/eco-component-meta-plugin.d.ts +0 -95
- package/src/plugins/eco-component-meta-plugin.js +0 -157
- package/src/plugins/integration-plugin.d.ts +0 -102
- package/src/plugins/integration-plugin.js +0 -100
- package/src/plugins/processor.d.ts +0 -82
- package/src/plugins/processor.js +0 -122
- package/src/public-types.d.ts +0 -1098
- package/src/public-types.js +0 -0
- package/src/route-renderer/component-graph-executor.d.ts +0 -32
- package/src/route-renderer/component-graph-executor.js +0 -31
- package/src/route-renderer/component-graph.d.ts +0 -42
- package/src/route-renderer/component-graph.js +0 -72
- package/src/route-renderer/component-marker.d.ts +0 -52
- package/src/route-renderer/component-marker.js +0 -46
- package/src/route-renderer/dependency-resolver.d.ts +0 -24
- package/src/route-renderer/dependency-resolver.js +0 -428
- package/src/route-renderer/html-post-processing.service.d.ts +0 -40
- package/src/route-renderer/html-post-processing.service.js +0 -86
- package/src/route-renderer/html-post-processing.service.ts +0 -103
- package/src/route-renderer/integration-renderer.d.ts +0 -339
- package/src/route-renderer/integration-renderer.js +0 -526
- package/src/route-renderer/marker-graph-resolver.d.ts +0 -76
- package/src/route-renderer/marker-graph-resolver.js +0 -93
- package/src/route-renderer/page-module-loader.d.ts +0 -61
- package/src/route-renderer/page-module-loader.js +0 -102
- package/src/route-renderer/render-execution.service.d.ts +0 -69
- package/src/route-renderer/render-execution.service.js +0 -91
- package/src/route-renderer/render-preparation.service.d.ts +0 -112
- package/src/route-renderer/render-preparation.service.js +0 -243
- package/src/route-renderer/route-renderer.d.ts +0 -26
- package/src/route-renderer/route-renderer.js +0 -68
- package/src/router/fs-router-scanner.d.ts +0 -41
- package/src/router/fs-router-scanner.js +0 -155
- package/src/router/fs-router.d.ts +0 -26
- package/src/router/fs-router.js +0 -100
- package/src/services/asset-processing-service/asset-processing.service.d.ts +0 -41
- package/src/services/asset-processing-service/asset-processing.service.js +0 -250
- package/src/services/asset-processing-service/asset.factory.d.ts +0 -17
- package/src/services/asset-processing-service/asset.factory.js +0 -82
- package/src/services/asset-processing-service/assets.types.d.ts +0 -88
- package/src/services/asset-processing-service/assets.types.js +0 -0
- package/src/services/asset-processing-service/index.d.ts +0 -3
- package/src/services/asset-processing-service/index.js +0 -3
- package/src/services/asset-processing-service/processor.interface.d.ts +0 -22
- package/src/services/asset-processing-service/processor.interface.js +0 -6
- package/src/services/asset-processing-service/processor.registry.d.ts +0 -8
- package/src/services/asset-processing-service/processor.registry.js +0 -15
- package/src/services/asset-processing-service/processors/base/base-processor.d.ts +0 -24
- package/src/services/asset-processing-service/processors/base/base-processor.js +0 -59
- package/src/services/asset-processing-service/processors/base/base-script-processor.d.ts +0 -16
- package/src/services/asset-processing-service/processors/base/base-script-processor.js +0 -80
- package/src/services/asset-processing-service/processors/index.d.ts +0 -5
- package/src/services/asset-processing-service/processors/index.js +0 -5
- package/src/services/asset-processing-service/processors/script/content-script.processor.d.ts +0 -5
- package/src/services/asset-processing-service/processors/script/content-script.processor.js +0 -57
- package/src/services/asset-processing-service/processors/script/file-script.processor.d.ts +0 -8
- package/src/services/asset-processing-service/processors/script/file-script.processor.js +0 -76
- package/src/services/asset-processing-service/processors/script/node-module-script.processor.d.ts +0 -7
- package/src/services/asset-processing-service/processors/script/node-module-script.processor.js +0 -74
- package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +0 -5
- package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +0 -25
- package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +0 -9
- package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +0 -63
- package/src/services/cache/cache.types.d.ts +0 -107
- package/src/services/cache/cache.types.js +0 -0
- package/src/services/cache/index.d.ts +0 -7
- package/src/services/cache/index.js +0 -7
- package/src/services/cache/memory-cache-store.d.ts +0 -42
- package/src/services/cache/memory-cache-store.js +0 -98
- package/src/services/cache/page-cache-service.d.ts +0 -70
- package/src/services/cache/page-cache-service.js +0 -152
- package/src/services/html-transformer.service.d.ts +0 -50
- package/src/services/html-transformer.service.js +0 -163
- package/src/services/html-transformer.service.ts +0 -217
- package/src/services/page-module-import.service.d.ts +0 -37
- package/src/services/page-module-import.service.js +0 -88
- package/src/services/page-module-import.service.ts +0 -129
- package/src/services/page-request-cache-coordinator.service.d.ts +0 -75
- package/src/services/page-request-cache-coordinator.service.js +0 -107
- package/src/services/schema-validation-service.d.ts +0 -122
- package/src/services/schema-validation-service.js +0 -101
- package/src/services/validation/standard-schema.types.d.ts +0 -65
- package/src/services/validation/standard-schema.types.js +0 -0
- package/src/static-site-generator/static-site-generator.d.ts +0 -57
- package/src/static-site-generator/static-site-generator.js +0 -272
- package/src/utils/css.d.ts +0 -1
- package/src/utils/css.js +0 -7
- package/src/utils/deep-merge.d.ts +0 -14
- package/src/utils/deep-merge.js +0 -32
- package/src/utils/hash.d.ts +0 -1
- package/src/utils/hash.js +0 -7
- package/src/utils/html.d.ts +0 -1
- package/src/utils/html.js +0 -4
- package/src/utils/invariant.d.ts +0 -5
- package/src/utils/invariant.js +0 -11
- package/src/utils/locals-utils.d.ts +0 -15
- package/src/utils/locals-utils.js +0 -24
- package/src/utils/parse-cli-args.d.ts +0 -24
- package/src/utils/parse-cli-args.js +0 -47
- package/src/utils/path-utils.module.d.ts +0 -5
- package/src/utils/path-utils.module.js +0 -14
- package/src/utils/runtime.d.ts +0 -11
- package/src/utils/runtime.js +0 -40
- package/src/utils/server-utils.module.d.ts +0 -19
- package/src/utils/server-utils.module.js +0 -56
- package/src/watchers/project-watcher.d.ts +0 -125
- package/src/watchers/project-watcher.js +0 -265
- package/src/watchers/project-watcher.test-helpers.d.ts +0 -4
- package/src/watchers/project-watcher.test-helpers.js +0 -52
- /package/src/route-renderer/{component-graph-executor.ts → component-graph/component-graph-executor.ts} +0 -0
- /package/src/route-renderer/{component-graph.ts → component-graph/component-graph.ts} +0 -0
- /package/src/route-renderer/{component-marker.ts → component-graph/component-marker.ts} +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.registry.ts +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/index.ts +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/content-script.processor.ts +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/content-stylesheet.processor.ts +0 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { afterEach, test, vi } from 'vitest';
|
|
6
|
+
import { ConfigBuilder } from '../../config/config-builder.ts';
|
|
7
|
+
import { resolveInternalExecutionDir, resolveInternalWorkDir } from '../../utils/resolve-work-dir.ts';
|
|
8
|
+
import { HmrManager } from './hmr-manager.ts';
|
|
9
|
+
|
|
10
|
+
const tempRoots: string[] = [];
|
|
11
|
+
|
|
12
|
+
function createTempRoot(prefix: string): string {
|
|
13
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), `${prefix}-`));
|
|
14
|
+
tempRoots.push(root);
|
|
15
|
+
return root;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
for (const root of tempRoots.splice(0)) {
|
|
20
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
21
|
+
}
|
|
22
|
+
vi.restoreAllMocks();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('HmrManager shares one in-flight entrypoint registration across concurrent callers', async () => {
|
|
26
|
+
const rootDir = createTempRoot('ecopages-bun-hmr-register');
|
|
27
|
+
const srcDir = path.join(rootDir, 'src');
|
|
28
|
+
const pagesDir = path.join(srcDir, 'pages');
|
|
29
|
+
fs.mkdirSync(pagesDir, { recursive: true });
|
|
30
|
+
|
|
31
|
+
const entrypointPath = path.join(pagesDir, 'react-lab.tsx');
|
|
32
|
+
fs.writeFileSync(entrypointPath, 'export default function Page() { return null; }', 'utf8');
|
|
33
|
+
|
|
34
|
+
const config = await new ConfigBuilder().setRootDir(rootDir).build();
|
|
35
|
+
const manager = new HmrManager({
|
|
36
|
+
appConfig: config,
|
|
37
|
+
bridge: {
|
|
38
|
+
subscriberCount: 0,
|
|
39
|
+
broadcast: () => {},
|
|
40
|
+
subscribe: () => {},
|
|
41
|
+
unsubscribe: () => {},
|
|
42
|
+
} as any,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const relativePathJs = path
|
|
46
|
+
.relative(config.absolutePaths.srcDir, entrypointPath)
|
|
47
|
+
.replace(/\.(tsx?|jsx?|mdx?)$/, '.js');
|
|
48
|
+
const encodedPathJs = relativePathJs.replace(/\[([^\]]+)\]/g, '_$1_');
|
|
49
|
+
const outputPath = path.join(resolveInternalWorkDir(config), 'assets', '_hmr', encodedPathJs);
|
|
50
|
+
|
|
51
|
+
const handleFileChange = vi.spyOn(manager, 'handleFileChange').mockImplementation(async () => {
|
|
52
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
53
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
54
|
+
fs.writeFileSync(outputPath, 'export default 1;', 'utf8');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const [firstUrl, secondUrl] = await Promise.all([
|
|
58
|
+
manager.registerEntrypoint(entrypointPath),
|
|
59
|
+
manager.registerEntrypoint(entrypointPath),
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
assert.equal(firstUrl, '/assets/_hmr/pages/react-lab.js');
|
|
63
|
+
assert.equal(secondUrl, '/assets/_hmr/pages/react-lab.js');
|
|
64
|
+
assert.equal(handleFileChange.mock.calls.length, 1);
|
|
65
|
+
assert.equal(fs.existsSync(outputPath), true);
|
|
66
|
+
|
|
67
|
+
manager.stop();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('HmrManager clears timed-out entrypoint registrations so later requests can retry', async () => {
|
|
71
|
+
const rootDir = createTempRoot('ecopages-bun-hmr-timeout-register');
|
|
72
|
+
const srcDir = path.join(rootDir, 'src');
|
|
73
|
+
const pagesDir = path.join(srcDir, 'pages');
|
|
74
|
+
fs.mkdirSync(pagesDir, { recursive: true });
|
|
75
|
+
|
|
76
|
+
const entrypointPath = path.join(pagesDir, 'stuck-page.tsx');
|
|
77
|
+
fs.writeFileSync(entrypointPath, 'export default function Page() { return null; }', 'utf8');
|
|
78
|
+
|
|
79
|
+
const config = await new ConfigBuilder().setRootDir(rootDir).build();
|
|
80
|
+
const manager = new HmrManager({
|
|
81
|
+
appConfig: config,
|
|
82
|
+
bridge: {
|
|
83
|
+
subscriberCount: 0,
|
|
84
|
+
broadcast: () => {},
|
|
85
|
+
subscribe: () => {},
|
|
86
|
+
unsubscribe: () => {},
|
|
87
|
+
} as any,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const previousNodeEnv = process.env.NODE_ENV;
|
|
91
|
+
process.env.NODE_ENV = 'development';
|
|
92
|
+
|
|
93
|
+
const handleFileChange = vi.spyOn(manager, 'handleFileChange').mockImplementation(async () => {
|
|
94
|
+
await new Promise(() => undefined);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
await assert.rejects(() => manager.registerEntrypoint(entrypointPath), /Timed out registering entrypoint/);
|
|
99
|
+
|
|
100
|
+
const registrations = (manager as unknown as { entrypointRegistrations: Map<string, Promise<string>> })
|
|
101
|
+
.entrypointRegistrations;
|
|
102
|
+
const watchedFiles = manager.getWatchedFiles();
|
|
103
|
+
assert.equal(registrations.size, 0);
|
|
104
|
+
assert.equal(watchedFiles.has(entrypointPath), false);
|
|
105
|
+
|
|
106
|
+
handleFileChange.mockImplementationOnce(async () => {
|
|
107
|
+
const relativePathJs = path
|
|
108
|
+
.relative(config.absolutePaths.srcDir, entrypointPath)
|
|
109
|
+
.replace(/\.(tsx?|jsx?|mdx?)$/, '.js');
|
|
110
|
+
const encodedPathJs = relativePathJs.replace(/\[([^\]]+)\]/g, '_$1_');
|
|
111
|
+
const outputPath = path.join(resolveInternalWorkDir(config), 'assets', '_hmr', encodedPathJs);
|
|
112
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
113
|
+
fs.writeFileSync(outputPath, 'export default 2;', 'utf8');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const retriedUrl = await manager.registerEntrypoint(entrypointPath);
|
|
117
|
+
assert.equal(retriedUrl, '/assets/_hmr/pages/stuck-page.js');
|
|
118
|
+
assert.equal(watchedFiles.get(entrypointPath), retriedUrl);
|
|
119
|
+
} finally {
|
|
120
|
+
process.env.NODE_ENV = previousNodeEnv;
|
|
121
|
+
manager.stop();
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('HmrManager fails strict entrypoint registration when the owning integration emits no output', async () => {
|
|
126
|
+
const rootDir = createTempRoot('ecopages-bun-hmr-strict-fail');
|
|
127
|
+
const srcDir = path.join(rootDir, 'src');
|
|
128
|
+
const pagesDir = path.join(srcDir, 'pages');
|
|
129
|
+
fs.mkdirSync(pagesDir, { recursive: true });
|
|
130
|
+
|
|
131
|
+
const entrypointPath = path.join(pagesDir, 'react-content.mdx');
|
|
132
|
+
fs.writeFileSync(entrypointPath, '# Hello', 'utf8');
|
|
133
|
+
|
|
134
|
+
const config = await new ConfigBuilder().setRootDir(rootDir).build();
|
|
135
|
+
const manager = new HmrManager({
|
|
136
|
+
appConfig: config,
|
|
137
|
+
bridge: {
|
|
138
|
+
subscriberCount: 0,
|
|
139
|
+
broadcast: () => {},
|
|
140
|
+
subscribe: () => {},
|
|
141
|
+
unsubscribe: () => {},
|
|
142
|
+
} as any,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
vi.spyOn(manager, 'handleFileChange').mockImplementation(async () => {});
|
|
146
|
+
|
|
147
|
+
await assert.rejects(() => manager.registerEntrypoint(entrypointPath), /Integration failed to emit entrypoint/);
|
|
148
|
+
assert.equal(manager.getWatchedFiles().has(path.resolve(entrypointPath)), false);
|
|
149
|
+
|
|
150
|
+
manager.stop();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('HmrManager uses the generic build path for script entrypoints when no strategy emits output', async () => {
|
|
154
|
+
const rootDir = createTempRoot('ecopages-bun-hmr-script-fallback');
|
|
155
|
+
const srcDir = path.join(rootDir, 'src');
|
|
156
|
+
fs.mkdirSync(srcDir, { recursive: true });
|
|
157
|
+
|
|
158
|
+
const entrypointPath = path.join(srcDir, 'script.ts');
|
|
159
|
+
fs.writeFileSync(entrypointPath, 'console.log("hello");', 'utf8');
|
|
160
|
+
|
|
161
|
+
const config = await new ConfigBuilder().setRootDir(rootDir).build();
|
|
162
|
+
const manager = new HmrManager({
|
|
163
|
+
appConfig: config,
|
|
164
|
+
bridge: {
|
|
165
|
+
subscriberCount: 0,
|
|
166
|
+
broadcast: () => {},
|
|
167
|
+
subscribe: () => {},
|
|
168
|
+
unsubscribe: () => {},
|
|
169
|
+
} as any,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const outputPath = path.join(resolveInternalWorkDir(config), 'assets', '_hmr', 'script.js');
|
|
173
|
+
const buildCalls: string[] = [];
|
|
174
|
+
config.runtime!.buildExecutor = {
|
|
175
|
+
build: vi.fn(async (options) => {
|
|
176
|
+
buildCalls.push(options.entrypoints[0] as string);
|
|
177
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
178
|
+
fs.writeFileSync(outputPath, 'fresh-output', 'utf8');
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
success: true,
|
|
182
|
+
logs: [],
|
|
183
|
+
outputs: [{ path: outputPath }],
|
|
184
|
+
};
|
|
185
|
+
}),
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
vi.spyOn(manager, 'handleFileChange').mockImplementation(async () => {});
|
|
189
|
+
|
|
190
|
+
const outputUrl = await manager.registerScriptEntrypoint(entrypointPath);
|
|
191
|
+
|
|
192
|
+
assert.equal(outputUrl, '/assets/_hmr/script.js');
|
|
193
|
+
assert.deepEqual(buildCalls, [entrypointPath]);
|
|
194
|
+
assert.equal(fs.readFileSync(outputPath, 'utf8'), 'fresh-output');
|
|
195
|
+
|
|
196
|
+
manager.stop();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test('HmrManager stop clears retained registration state', async () => {
|
|
200
|
+
const rootDir = createTempRoot('ecopages-bun-hmr-stop-cleanup');
|
|
201
|
+
const srcDir = path.join(rootDir, 'src');
|
|
202
|
+
const pagesDir = path.join(srcDir, 'pages');
|
|
203
|
+
fs.mkdirSync(pagesDir, { recursive: true });
|
|
204
|
+
|
|
205
|
+
const entrypointPath = path.join(pagesDir, 'react-content.tsx');
|
|
206
|
+
fs.writeFileSync(entrypointPath, 'export default function Page() { return null; }', 'utf8');
|
|
207
|
+
|
|
208
|
+
const config = await new ConfigBuilder().setRootDir(rootDir).build();
|
|
209
|
+
const manager = new HmrManager({
|
|
210
|
+
appConfig: config,
|
|
211
|
+
bridge: {
|
|
212
|
+
subscriberCount: 0,
|
|
213
|
+
broadcast: () => {},
|
|
214
|
+
subscribe: () => {},
|
|
215
|
+
unsubscribe: () => {},
|
|
216
|
+
} as any,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const relativePathJs = path
|
|
220
|
+
.relative(config.absolutePaths.srcDir, entrypointPath)
|
|
221
|
+
.replace(/\.(tsx?|jsx?|mdx?)$/, '.js');
|
|
222
|
+
const encodedPathJs = relativePathJs.replace(/\[([^\]]+)\]/g, '_$1_');
|
|
223
|
+
const outputPath = path.join(resolveInternalWorkDir(config), 'assets', '_hmr', encodedPathJs);
|
|
224
|
+
|
|
225
|
+
vi.spyOn(manager, 'handleFileChange').mockImplementation(async () => {
|
|
226
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
227
|
+
fs.writeFileSync(outputPath, 'export default 1;', 'utf8');
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
manager.registerSpecifierMap({ react: '/assets/vendors/react.js' });
|
|
231
|
+
await manager.registerEntrypoint(entrypointPath);
|
|
232
|
+
|
|
233
|
+
manager.stop();
|
|
234
|
+
|
|
235
|
+
assert.equal(manager.getWatchedFiles().size, 0);
|
|
236
|
+
assert.equal(manager.getSpecifierMap().size, 0);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test('HmrManager keeps internal browser and server-module outputs out of distDir', async () => {
|
|
240
|
+
const rootDir = createTempRoot('ecopages-bun-hmr-internal-paths');
|
|
241
|
+
const config = await new ConfigBuilder().setRootDir(rootDir).build();
|
|
242
|
+
const manager = new HmrManager({
|
|
243
|
+
appConfig: config,
|
|
244
|
+
bridge: {
|
|
245
|
+
subscriberCount: 0,
|
|
246
|
+
broadcast: () => {},
|
|
247
|
+
subscribe: () => {},
|
|
248
|
+
unsubscribe: () => {},
|
|
249
|
+
} as any,
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
assert.equal(manager.getDistDir(), path.join(resolveInternalWorkDir(config), 'assets', '_hmr'));
|
|
253
|
+
|
|
254
|
+
const importModule = vi.fn(async (_options: { outdir: string }) => ({}));
|
|
255
|
+
(manager as unknown as { serverModuleTranspiler: { importModule: typeof importModule } }).serverModuleTranspiler = {
|
|
256
|
+
importModule,
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
await manager.getDefaultContext().importServerModule(path.join(config.absolutePaths.srcDir, 'pages', 'index.tsx'));
|
|
260
|
+
|
|
261
|
+
assert.equal(
|
|
262
|
+
importModule.mock.calls[0]?.[0]?.outdir,
|
|
263
|
+
path.join(resolveInternalExecutionDir(config), '.server-modules'),
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
manager.stop();
|
|
267
|
+
});
|
|
@@ -2,17 +2,27 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import type { ServerWebSocket, WebSocketHandler } from 'bun';
|
|
4
4
|
import { RESOLVED_ASSETS_DIR } from '../../constants';
|
|
5
|
-
import {
|
|
5
|
+
import { getAppBuildExecutor } from '../../build/build-adapter.ts';
|
|
6
6
|
import type { DefaultHmrContext, EcoPagesAppConfig, IHmrManager } from '../../internal-types';
|
|
7
7
|
import type { EcoBuildPlugin } from '../../build/build-types.ts';
|
|
8
8
|
import { fileSystem } from '@ecopages/file-system';
|
|
9
|
-
import type
|
|
10
|
-
import { HmrStrategyType } from '../../hmr/hmr-strategy';
|
|
9
|
+
import { HmrStrategyType, type HmrStrategy } from '../../hmr/hmr-strategy';
|
|
11
10
|
import { DefaultHmrStrategy } from '../../hmr/strategies/default-hmr-strategy';
|
|
12
11
|
import { JsHmrStrategy } from '../../hmr/strategies/js-hmr-strategy';
|
|
13
12
|
import { appLogger } from '../../global/app-logger';
|
|
14
13
|
import type { ClientBridge } from './client-bridge';
|
|
15
14
|
import type { ClientBridgeEvent } from '../../public-types';
|
|
15
|
+
import { HmrEntrypointRegistrar } from '../shared/hmr-entrypoint-registrar.ts';
|
|
16
|
+
import { BrowserBundleService } from '../../services/assets/browser-bundle.service.ts';
|
|
17
|
+
import { getAppServerModuleTranspiler } from '../../services/module-loading/app-server-module-transpiler.service';
|
|
18
|
+
import {
|
|
19
|
+
getAppEntrypointDependencyGraph,
|
|
20
|
+
NoopEntrypointDependencyGraph,
|
|
21
|
+
setAppEntrypointDependencyGraph,
|
|
22
|
+
} from '../../services/runtime-state/entrypoint-dependency-graph.service.ts';
|
|
23
|
+
import { getAppRuntimeSpecifierRegistry } from '../../services/runtime-state/runtime-specifier-registry.service.ts';
|
|
24
|
+
import type { ServerModuleTranspiler } from '../../services/module-loading/server-module-transpiler.service';
|
|
25
|
+
import { resolveInternalExecutionDir, resolveInternalWorkDir } from '../../utils/resolve-work-dir.ts';
|
|
16
26
|
|
|
17
27
|
type BunSocket = ServerWebSocket<unknown>;
|
|
18
28
|
type BunSocketHandler = WebSocketHandler<unknown>;
|
|
@@ -22,19 +32,36 @@ export interface HmrManagerParams {
|
|
|
22
32
|
bridge: ClientBridge;
|
|
23
33
|
}
|
|
24
34
|
|
|
35
|
+
type HandleFileChangeOptions = {
|
|
36
|
+
broadcast?: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Bun development HMR manager.
|
|
41
|
+
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* Bun shares the same public contract as the Node manager: page entrypoints are
|
|
44
|
+
* strict integration-owned registrations, while generic script assets use their
|
|
45
|
+
* own explicit registration path.
|
|
46
|
+
*/
|
|
25
47
|
export class HmrManager implements IHmrManager {
|
|
48
|
+
private static readonly entrypointRegistrationTimeoutMs = 4000;
|
|
26
49
|
public readonly appConfig: EcoPagesAppConfig;
|
|
27
50
|
private readonly bridge: ClientBridge;
|
|
28
51
|
/** Keep track of watchers */
|
|
29
52
|
private watchers = new Map<string, fs.FSWatcher>();
|
|
30
53
|
/** entrypoint -> output path */
|
|
31
54
|
private watchedFiles = new Map<string, string>();
|
|
32
|
-
|
|
33
|
-
private specifierMap = new Map<string, string>();
|
|
55
|
+
private entrypointRegistrations = new Map<string, Promise<string>>();
|
|
34
56
|
private distDir: string;
|
|
35
57
|
private plugins: EcoBuildPlugin[] = [];
|
|
36
58
|
private enabled = true;
|
|
37
59
|
private strategies: HmrStrategy[] = [];
|
|
60
|
+
private readonly entrypointRegistrar: HmrEntrypointRegistrar;
|
|
61
|
+
private readonly browserBundleService: BrowserBundleService;
|
|
62
|
+
private readonly entrypointDependencyGraph: ReturnType<typeof getAppEntrypointDependencyGraph>;
|
|
63
|
+
private readonly runtimeSpecifierRegistry: ReturnType<typeof getAppRuntimeSpecifierRegistry>;
|
|
64
|
+
private readonly serverModuleTranspiler: ServerModuleTranspiler;
|
|
38
65
|
private wsHandler!: {
|
|
39
66
|
open: (ws: BunSocket) => void;
|
|
40
67
|
close: (ws: BunSocket) => void;
|
|
@@ -43,7 +70,24 @@ export class HmrManager implements IHmrManager {
|
|
|
43
70
|
constructor({ appConfig, bridge }: HmrManagerParams) {
|
|
44
71
|
this.appConfig = appConfig;
|
|
45
72
|
this.bridge = bridge;
|
|
46
|
-
this.distDir = path.join(this.appConfig
|
|
73
|
+
this.distDir = path.join(resolveInternalWorkDir(this.appConfig), RESOLVED_ASSETS_DIR, '_hmr');
|
|
74
|
+
this.entrypointRegistrar = new HmrEntrypointRegistrar({
|
|
75
|
+
srcDir: this.appConfig.absolutePaths.srcDir,
|
|
76
|
+
distDir: this.distDir,
|
|
77
|
+
entrypointRegistrations: this.entrypointRegistrations,
|
|
78
|
+
watchedFiles: this.watchedFiles,
|
|
79
|
+
clearFailedRegistration: (entrypointPath) => this.clearFailedEntrypointRegistration(entrypointPath),
|
|
80
|
+
registrationTimeoutMs: HmrManager.entrypointRegistrationTimeoutMs,
|
|
81
|
+
});
|
|
82
|
+
this.browserBundleService = new BrowserBundleService(appConfig);
|
|
83
|
+
const existingEntrypointDependencyGraph = getAppEntrypointDependencyGraph(appConfig);
|
|
84
|
+
this.entrypointDependencyGraph =
|
|
85
|
+
existingEntrypointDependencyGraph instanceof NoopEntrypointDependencyGraph
|
|
86
|
+
? existingEntrypointDependencyGraph
|
|
87
|
+
: new NoopEntrypointDependencyGraph();
|
|
88
|
+
setAppEntrypointDependencyGraph(this.appConfig, this.entrypointDependencyGraph);
|
|
89
|
+
this.runtimeSpecifierRegistry = getAppRuntimeSpecifierRegistry(this.appConfig);
|
|
90
|
+
this.serverModuleTranspiler = getAppServerModuleTranspiler(this.appConfig);
|
|
47
91
|
this.cleanDistDir();
|
|
48
92
|
this.initializeStrategies();
|
|
49
93
|
}
|
|
@@ -58,6 +102,29 @@ export class HmrManager implements IHmrManager {
|
|
|
58
102
|
fileSystem.ensureDir(this.distDir);
|
|
59
103
|
}
|
|
60
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Returns whether the generic JS strategy may rebuild an entrypoint.
|
|
107
|
+
*
|
|
108
|
+
* @remarks
|
|
109
|
+
* Integration-owned page entrypoints are excluded so a shared dependency
|
|
110
|
+
* invalidation cannot replace framework-owned browser output with a generic JS
|
|
111
|
+
* rebuild.
|
|
112
|
+
*/
|
|
113
|
+
private shouldJsStrategyProcessEntrypoint(entrypointPath: string): boolean {
|
|
114
|
+
return !this.strategies.some((strategy) => {
|
|
115
|
+
if (strategy.type !== HmrStrategyType.INTEGRATION || strategy.priority <= HmrStrategyType.SCRIPT) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
return strategy.matches(entrypointPath);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
appLogger.error(error);
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
61
128
|
/**
|
|
62
129
|
* Initializes core HMR strategies.
|
|
63
130
|
* Strategies are evaluated in priority order (highest first).
|
|
@@ -65,10 +132,16 @@ export class HmrManager implements IHmrManager {
|
|
|
65
132
|
private initializeStrategies(): void {
|
|
66
133
|
const jsContext = {
|
|
67
134
|
getWatchedFiles: () => this.watchedFiles,
|
|
68
|
-
getSpecifierMap: () => this.
|
|
135
|
+
getSpecifierMap: () => this.runtimeSpecifierRegistry.getAll(),
|
|
69
136
|
getDistDir: () => this.distDir,
|
|
70
137
|
getPlugins: () => this.plugins,
|
|
71
138
|
getSrcDir: () => this.appConfig.absolutePaths.srcDir,
|
|
139
|
+
getPagesDir: () => this.appConfig.absolutePaths.pagesDir,
|
|
140
|
+
getLayoutsDir: () => this.appConfig.absolutePaths.layoutsDir,
|
|
141
|
+
getTemplateExtensions: () => this.appConfig.templatesExt,
|
|
142
|
+
getBrowserBundleService: () => this.browserBundleService,
|
|
143
|
+
getEntrypointDependencyGraph: () => this.entrypointDependencyGraph,
|
|
144
|
+
shouldProcessEntrypoint: (entrypointPath: string) => this.shouldJsStrategyProcessEntrypoint(entrypointPath),
|
|
72
145
|
};
|
|
73
146
|
|
|
74
147
|
this.strategies = [new JsHmrStrategy(jsContext), new DefaultHmrStrategy()];
|
|
@@ -96,14 +169,16 @@ export class HmrManager implements IHmrManager {
|
|
|
96
169
|
}
|
|
97
170
|
|
|
98
171
|
/**
|
|
99
|
-
* Registers
|
|
100
|
-
*
|
|
101
|
-
* @
|
|
172
|
+
* Registers runtime bare-specifier mappings exposed by integrations.
|
|
173
|
+
*
|
|
174
|
+
* @remarks
|
|
175
|
+
* These mappings are consumed by framework-owned HMR strategies that preserve
|
|
176
|
+
* shared runtime imports in browser bundles. The registry stays generic so
|
|
177
|
+
* these mappings can later support broader import-map-style runtime features
|
|
178
|
+
* without moving integration semantics into core.
|
|
102
179
|
*/
|
|
103
180
|
public registerSpecifierMap(map: Record<string, string>): void {
|
|
104
|
-
|
|
105
|
-
this.specifierMap.set(specifier, url);
|
|
106
|
-
}
|
|
181
|
+
this.runtimeSpecifierRegistry.register(map);
|
|
107
182
|
}
|
|
108
183
|
|
|
109
184
|
public getWebSocketHandler(): BunSocketHandler {
|
|
@@ -134,12 +209,12 @@ export class HmrManager implements IHmrManager {
|
|
|
134
209
|
public async buildRuntime(): Promise<void> {
|
|
135
210
|
const runtimeSource = path.resolve(import.meta.dirname, '../../hmr/client/hmr-runtime.ts');
|
|
136
211
|
|
|
137
|
-
const result = await
|
|
212
|
+
const result = await this.browserBundleService.bundle({
|
|
213
|
+
profile: 'hmr-runtime',
|
|
138
214
|
entrypoints: [runtimeSource],
|
|
139
215
|
outdir: this.distDir,
|
|
140
216
|
naming: '_hmr_runtime.js',
|
|
141
217
|
minify: false,
|
|
142
|
-
...defaultBuildAdapter.getTranspileOptions('hmr-runtime'),
|
|
143
218
|
plugins: this.plugins,
|
|
144
219
|
});
|
|
145
220
|
|
|
@@ -159,32 +234,13 @@ export class HmrManager implements IHmrManager {
|
|
|
159
234
|
this.bridge.broadcast(event);
|
|
160
235
|
}
|
|
161
236
|
|
|
162
|
-
public
|
|
163
|
-
const sorted = [...this.strategies].sort((a, b) => b.priority - a.priority);
|
|
164
|
-
const strategy = sorted.find((candidate) => {
|
|
165
|
-
try {
|
|
166
|
-
return candidate.matches(filePath);
|
|
167
|
-
} catch (err) {
|
|
168
|
-
appLogger.error(`[HmrManager] Error checking match for ${candidate.constructor.name}:`, err as Error);
|
|
169
|
-
return false;
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
return strategy !== undefined && strategy.type !== HmrStrategyType.FALLBACK;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Handles file changes using registered HMR strategies.
|
|
178
|
-
* Strategies are evaluated in priority order until one matches.
|
|
179
|
-
* @param filePath - Absolute path to the changed file
|
|
180
|
-
*/
|
|
181
|
-
public async handleFileChange(filePath: string): Promise<void> {
|
|
237
|
+
public async handleFileChange(filePath: string, options: HandleFileChangeOptions = {}): Promise<void> {
|
|
182
238
|
const sorted = [...this.strategies].sort((a, b) => b.priority - a.priority);
|
|
183
239
|
const strategy = sorted.find((s) => {
|
|
184
240
|
try {
|
|
185
241
|
return s.matches(filePath);
|
|
186
242
|
} catch (err) {
|
|
187
|
-
appLogger.error(
|
|
243
|
+
appLogger.error(err);
|
|
188
244
|
return false;
|
|
189
245
|
}
|
|
190
246
|
});
|
|
@@ -197,8 +253,9 @@ export class HmrManager implements IHmrManager {
|
|
|
197
253
|
appLogger.debug(`[HmrManager] Selected strategy: ${strategy.constructor.name}`);
|
|
198
254
|
|
|
199
255
|
const action = await strategy.process(filePath);
|
|
256
|
+
const shouldBroadcast = options.broadcast ?? true;
|
|
200
257
|
|
|
201
|
-
if (action.type === 'broadcast') {
|
|
258
|
+
if (shouldBroadcast && action.type === 'broadcast') {
|
|
202
259
|
if (action.events) {
|
|
203
260
|
for (const event of action.events) {
|
|
204
261
|
this.broadcast(event);
|
|
@@ -207,9 +264,6 @@ export class HmrManager implements IHmrManager {
|
|
|
207
264
|
}
|
|
208
265
|
}
|
|
209
266
|
|
|
210
|
-
/**
|
|
211
|
-
* Registers a client entrypoint to be built and watched by Bun.
|
|
212
|
-
*/
|
|
213
267
|
public getOutputUrl(entrypointPath: string): string | undefined {
|
|
214
268
|
return this.watchedFiles.get(entrypointPath);
|
|
215
269
|
}
|
|
@@ -219,7 +273,7 @@ export class HmrManager implements IHmrManager {
|
|
|
219
273
|
}
|
|
220
274
|
|
|
221
275
|
public getSpecifierMap(): Map<string, string> {
|
|
222
|
-
return this.
|
|
276
|
+
return this.runtimeSpecifierRegistry.getAll();
|
|
223
277
|
}
|
|
224
278
|
|
|
225
279
|
public getDistDir(): string {
|
|
@@ -233,64 +287,123 @@ export class HmrManager implements IHmrManager {
|
|
|
233
287
|
public getDefaultContext(): DefaultHmrContext {
|
|
234
288
|
return {
|
|
235
289
|
getWatchedFiles: () => this.watchedFiles,
|
|
236
|
-
getSpecifierMap: () => this.
|
|
290
|
+
getSpecifierMap: () => this.runtimeSpecifierRegistry.getAll(),
|
|
237
291
|
getDistDir: () => this.distDir,
|
|
238
292
|
getPlugins: () => this.plugins,
|
|
239
293
|
getSrcDir: () => this.appConfig.absolutePaths.srcDir,
|
|
240
294
|
getLayoutsDir: () => this.appConfig.absolutePaths.layoutsDir,
|
|
241
295
|
getPagesDir: () => this.appConfig.absolutePaths.pagesDir,
|
|
296
|
+
getBuildExecutor: () => getAppBuildExecutor(this.appConfig),
|
|
297
|
+
getBrowserBundleService: () => this.browserBundleService,
|
|
298
|
+
importServerModule: async <T>(filePath: string) =>
|
|
299
|
+
await this.serverModuleTranspiler.importModule<T>({
|
|
300
|
+
filePath,
|
|
301
|
+
outdir: path.join(resolveInternalExecutionDir(this.appConfig), '.server-modules'),
|
|
302
|
+
externalPackages: true,
|
|
303
|
+
}),
|
|
242
304
|
};
|
|
243
305
|
}
|
|
244
306
|
|
|
307
|
+
private clearFailedEntrypointRegistration(entrypointPath: string): void {
|
|
308
|
+
this.watchedFiles.delete(entrypointPath);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Registers one integration-owned page entrypoint.
|
|
313
|
+
*
|
|
314
|
+
* @remarks
|
|
315
|
+
* Concurrent callers share one in-flight registration. The registration is
|
|
316
|
+
* cleared from the dedupe map when it settles so later callers cannot inherit a
|
|
317
|
+
* stale promise.
|
|
318
|
+
*/
|
|
245
319
|
public async registerEntrypoint(entrypointPath: string): Promise<string> {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
320
|
+
return await this.entrypointRegistrar.registerEntrypoint(entrypointPath, {
|
|
321
|
+
emit: async (normalizedEntrypoint, outputPath) =>
|
|
322
|
+
await this.emitStrictEntrypoint(normalizedEntrypoint, outputPath),
|
|
323
|
+
getMissingOutputError: (normalizedEntrypoint, outputPath) =>
|
|
324
|
+
new Error(
|
|
325
|
+
`[HMR] Integration failed to emit entrypoint ${normalizedEntrypoint} to ${outputPath}. Page entrypoints must be produced by their owning integration.`,
|
|
326
|
+
),
|
|
327
|
+
});
|
|
328
|
+
}
|
|
249
329
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
330
|
+
/**
|
|
331
|
+
* Registers one generic script entrypoint.
|
|
332
|
+
*
|
|
333
|
+
* @remarks
|
|
334
|
+
* This explicit path keeps the page-entrypoint contract strict while still
|
|
335
|
+
* allowing generic script assets to use the fallback build path.
|
|
336
|
+
*/
|
|
337
|
+
public async registerScriptEntrypoint(entrypointPath: string): Promise<string> {
|
|
338
|
+
return await this.entrypointRegistrar.registerEntrypoint(entrypointPath, {
|
|
339
|
+
emit: async (normalizedEntrypoint, outputPath) =>
|
|
340
|
+
await this.emitScriptEntrypoint(normalizedEntrypoint, outputPath),
|
|
341
|
+
getMissingOutputError: (normalizedEntrypoint) =>
|
|
342
|
+
new Error(`[HMR] Failed to register script entrypoint: ${normalizedEntrypoint}`),
|
|
343
|
+
});
|
|
344
|
+
}
|
|
254
345
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
346
|
+
/**
|
|
347
|
+
* Performs strict integration-owned registration for one normalized path.
|
|
348
|
+
*
|
|
349
|
+
* @remarks
|
|
350
|
+
* The manager reserves the output URL, removes any stale emitted file, runs
|
|
351
|
+
* strategy processing without broadcasting, and then verifies that the owning
|
|
352
|
+
* integration emitted the expected file.
|
|
353
|
+
*/
|
|
354
|
+
private async emitStrictEntrypoint(entrypointPath: string, _outputPath: string): Promise<void> {
|
|
355
|
+
await this.handleFileChange(entrypointPath, { broadcast: false });
|
|
356
|
+
}
|
|
258
357
|
|
|
259
|
-
|
|
358
|
+
/**
|
|
359
|
+
* Performs registration for a generic script asset.
|
|
360
|
+
*
|
|
361
|
+
* @remarks
|
|
362
|
+
* Strategies get the first chance to emit output. If no output exists after
|
|
363
|
+
* that pass, Bun falls back to the generic browser build for this explicit
|
|
364
|
+
* script-only path.
|
|
365
|
+
*/
|
|
366
|
+
private async emitScriptEntrypoint(entrypointPath: string, outputPath: string): Promise<void> {
|
|
367
|
+
const naming = path.relative(this.distDir, outputPath).split(path.sep).join('/');
|
|
260
368
|
|
|
261
|
-
await this.handleFileChange(entrypointPath);
|
|
369
|
+
await this.handleFileChange(entrypointPath, { broadcast: false });
|
|
262
370
|
|
|
263
371
|
if (!fileSystem.exists(outputPath)) {
|
|
264
|
-
const
|
|
372
|
+
const buildResult = await this.browserBundleService.bundle({
|
|
373
|
+
profile: 'hmr-entrypoint',
|
|
265
374
|
entrypoints: [entrypointPath],
|
|
266
375
|
outdir: this.distDir,
|
|
267
|
-
naming
|
|
376
|
+
naming,
|
|
268
377
|
minify: false,
|
|
269
|
-
external: Array.from(this.specifierMap.keys()),
|
|
270
|
-
...defaultBuildAdapter.getTranspileOptions('hmr-entrypoint'),
|
|
271
378
|
plugins: this.plugins,
|
|
272
379
|
});
|
|
273
380
|
|
|
274
|
-
if (!
|
|
275
|
-
appLogger.error(
|
|
381
|
+
if (!buildResult.success) {
|
|
382
|
+
appLogger.error(
|
|
383
|
+
`[HMR] Generic script entrypoint build failed for ${entrypointPath}:`,
|
|
384
|
+
buildResult.logs,
|
|
385
|
+
);
|
|
276
386
|
}
|
|
277
387
|
}
|
|
278
|
-
|
|
279
|
-
return outputUrl;
|
|
280
388
|
}
|
|
281
389
|
|
|
282
390
|
/**
|
|
283
|
-
*
|
|
284
|
-
*
|
|
391
|
+
* Stops active watchers and releases retained registration state.
|
|
392
|
+
*
|
|
393
|
+
* @remarks
|
|
394
|
+
* Emitted `_hmr` files remain on disk because parallel app processes may share
|
|
395
|
+
* the same dist directory. The in-memory indexes are cleared so stale
|
|
396
|
+
* entrypoints and specifier maps cannot leak through a reused manager object.
|
|
285
397
|
*/
|
|
286
|
-
private encodeDynamicSegments(filepath: string): string {
|
|
287
|
-
return filepath.replace(/\[([^\]]+)\]/g, '_$1_');
|
|
288
|
-
}
|
|
289
|
-
|
|
290
398
|
public stop() {
|
|
399
|
+
this.entrypointRegistrations.clear();
|
|
291
400
|
for (const watcher of this.watchers.values()) {
|
|
292
401
|
watcher.close();
|
|
293
402
|
}
|
|
294
403
|
this.watchers.clear();
|
|
404
|
+
this.watchedFiles.clear();
|
|
405
|
+
this.runtimeSpecifierRegistry.clear();
|
|
406
|
+
this.entrypointDependencyGraph.reset();
|
|
407
|
+
this.plugins = [];
|
|
295
408
|
}
|
|
296
409
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
export { EcopagesApp, createApp } from './create-app.ts';
|
|
2
|
-
export { defineApiHandler, defineGroupHandler } from '
|
|
3
|
-
export type { GroupHandler } from './define-api-handler.ts';
|
|
2
|
+
export { defineApiHandler, defineGroupHandler, type GroupHandler } from '../shared/define-api-handler.ts';
|