@ecopages/core 0.2.0-alpha.1 → 0.2.0-alpha.10
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/CHANGELOG.md +13 -70
- package/README.md +213 -12
- package/package.json +50 -18
- package/src/adapters/README.md +39 -0
- package/src/adapters/bun/hmr-manager.d.ts +77 -18
- package/src/adapters/bun/hmr-manager.js +159 -52
- package/src/adapters/bun/index.d.ts +1 -2
- package/src/adapters/bun/index.js +1 -1
- package/src/adapters/bun/server-adapter.js +35 -30
- package/src/adapters/bun/server-lifecycle.d.ts +24 -13
- package/src/adapters/bun/server-lifecycle.js +32 -60
- package/src/adapters/index.d.ts +1 -1
- package/src/adapters/index.js +1 -1
- package/src/adapters/node/bootstrap-dependency-resolver.d.ts +44 -0
- package/src/adapters/node/bootstrap-dependency-resolver.js +172 -0
- package/src/adapters/node/index.d.ts +2 -0
- package/src/adapters/node/index.js +3 -0
- package/src/adapters/node/node-hmr-manager.d.ts +87 -16
- package/src/adapters/node/node-hmr-manager.js +179 -88
- package/src/adapters/node/runtime-adapter.d.ts +46 -0
- package/src/adapters/node/runtime-adapter.js +306 -0
- package/src/adapters/node/server-adapter.d.ts +2 -31
- package/src/adapters/node/server-adapter.js +31 -93
- package/src/adapters/node/static-content-server.d.ts +36 -0
- package/src/adapters/node/static-content-server.js +28 -0
- package/src/adapters/node/write-runtime-manifest.d.ts +26 -0
- package/src/adapters/node/write-runtime-manifest.js +12 -0
- package/src/{define-api-handler.d.ts → adapters/shared/define-api-handler.d.ts} +1 -1
- package/src/adapters/shared/explicit-static-route-matcher.js +4 -1
- package/src/adapters/shared/file-route-middleware-pipeline.js +1 -0
- package/src/adapters/shared/fs-server-response-matcher.d.ts +9 -5
- package/src/adapters/shared/fs-server-response-matcher.js +13 -8
- package/src/adapters/shared/hmr-entrypoint-registrar.d.ts +55 -0
- package/src/adapters/shared/hmr-entrypoint-registrar.js +87 -0
- package/src/adapters/shared/hmr-html-response.d.ts +22 -0
- package/src/adapters/shared/hmr-html-response.js +32 -0
- package/src/adapters/shared/render-context.js +3 -2
- package/src/adapters/shared/runtime-bootstrap.d.ts +38 -0
- package/src/adapters/shared/runtime-bootstrap.js +43 -0
- package/src/adapters/shared/server-adapter.d.ts +12 -2
- package/src/adapters/shared/server-adapter.js +37 -4
- package/src/adapters/shared/server-route-handler.d.ts +1 -1
- package/src/adapters/shared/server-route-handler.js +4 -13
- package/src/adapters/shared/server-static-builder.d.ts +35 -3
- package/src/adapters/shared/server-static-builder.js +59 -6
- package/src/build/README.md +101 -0
- package/src/build/build-adapter.d.ts +114 -2
- package/src/build/build-adapter.js +119 -5
- package/src/build/build-manifest.d.ts +27 -0
- package/src/build/build-manifest.js +30 -0
- package/src/build/dev-build-coordinator.d.ts +74 -0
- package/src/build/dev-build-coordinator.js +161 -0
- package/src/build/esbuild-build-adapter.d.ts +9 -6
- package/src/build/esbuild-build-adapter.js +103 -71
- package/src/build/runtime-build-executor.d.ts +13 -0
- package/src/build/runtime-build-executor.js +20 -0
- package/src/build/runtime-specifier-alias-plugin.d.ts +15 -0
- package/src/build/runtime-specifier-alias-plugin.js +31 -0
- package/src/config/README.md +33 -0
- package/src/config/config-builder.d.ts +28 -17
- package/src/config/config-builder.js +221 -48
- package/src/constants.d.ts +13 -0
- package/src/constants.js +4 -0
- package/src/declarations.d.ts +18 -13
- package/src/eco/README.md +70 -16
- package/src/eco/component-render-context.d.ts +1 -1
- package/src/eco/component-render-context.js +26 -16
- package/src/eco/eco.js +16 -12
- package/src/eco/eco.types.d.ts +12 -4
- package/src/hmr/README.md +26 -0
- package/src/hmr/client/hmr-runtime.d.ts +1 -6
- package/src/hmr/client/hmr-runtime.js +30 -7
- package/src/hmr/hmr.postcss.test.e2e.d.ts +1 -0
- package/src/hmr/hmr.postcss.test.e2e.js +31 -0
- package/src/hmr/hmr.test.e2e.js +26 -33
- package/src/hmr/strategies/js-hmr-strategy.d.ts +45 -42
- package/src/hmr/strategies/js-hmr-strategy.js +70 -71
- package/src/index.d.ts +1 -1
- package/src/index.js +1 -1
- package/src/integrations/ghtml/ghtml-renderer.d.ts +1 -1
- package/src/integrations/ghtml/ghtml-renderer.js +3 -1
- package/src/internal-types.d.ts +39 -18
- package/src/plugins/README.md +34 -0
- package/src/plugins/alias-resolver-plugin.js +17 -3
- package/src/plugins/eco-component-meta-plugin.d.ts +2 -0
- package/src/plugins/eco-component-meta-plugin.js +1 -1
- package/src/plugins/integration-plugin.d.ts +38 -4
- package/src/plugins/integration-plugin.js +34 -1
- package/src/plugins/processor.d.ts +14 -1
- package/src/plugins/processor.js +15 -1
- package/src/plugins/runtime-capability.d.ts +9 -0
- package/src/public-types.d.ts +65 -10
- package/src/route-renderer/GRAPH.md +16 -20
- package/src/route-renderer/README.md +8 -21
- package/src/route-renderer/component-graph/component-reference.d.ts +10 -0
- package/src/route-renderer/component-graph/component-reference.js +19 -0
- package/src/route-renderer/{marker-graph-resolver.d.ts → component-graph/marker-graph-resolver.d.ts} +6 -5
- package/src/route-renderer/{marker-graph-resolver.js → component-graph/marker-graph-resolver.js} +10 -8
- package/src/route-renderer/{integration-renderer.d.ts → orchestration/integration-renderer.d.ts} +45 -12
- package/src/route-renderer/{integration-renderer.js → orchestration/integration-renderer.js} +79 -16
- package/src/route-renderer/{render-execution.service.d.ts → orchestration/render-execution.service.d.ts} +39 -5
- package/src/route-renderer/{render-execution.service.js → orchestration/render-execution.service.js} +58 -28
- package/src/route-renderer/{render-preparation.service.d.ts → orchestration/render-preparation.service.d.ts} +13 -4
- package/src/route-renderer/{render-preparation.service.js → orchestration/render-preparation.service.js} +92 -3
- package/src/route-renderer/{dependency-resolver.d.ts → page-loading/dependency-resolver.d.ts} +15 -4
- package/src/route-renderer/{dependency-resolver.js → page-loading/dependency-resolver.js} +18 -4
- package/src/route-renderer/page-loading/page-module-loader.d.ts +87 -0
- package/src/route-renderer/{page-module-loader.js → page-loading/page-module-loader.js} +36 -14
- package/src/route-renderer/route-renderer.d.ts +36 -1
- package/src/route-renderer/route-renderer.js +19 -0
- package/src/router/README.md +26 -0
- package/src/router/client/link-intent.d.ts +53 -0
- package/src/router/client/link-intent.js +34 -0
- package/src/router/client/link-intent.test.browser.d.ts +1 -0
- package/src/router/client/link-intent.test.browser.js +43 -0
- package/src/router/client/navigation-coordinator.d.ts +149 -0
- package/src/router/client/navigation-coordinator.js +215 -0
- package/src/router/{fs-router-scanner.d.ts → server/fs-router-scanner.d.ts} +3 -3
- package/src/router/{fs-router-scanner.js → server/fs-router-scanner.js} +8 -7
- package/src/router/{fs-router.d.ts → server/fs-router.d.ts} +1 -1
- package/src/router/{fs-router.js → server/fs-router.js} +1 -1
- package/src/services/README.md +29 -0
- package/src/services/assets/asset-processing-service/asset-processing.service.d.ts +120 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/asset-processing.service.js +88 -7
- package/src/services/{asset-processing-service → assets/asset-processing-service}/asset.factory.js +2 -2
- package/src/services/{asset-processing-service → assets/asset-processing-service}/assets.types.d.ts +2 -1
- package/src/services/assets/asset-processing-service/assets.types.js +0 -0
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.d.ts +55 -0
- package/src/services/assets/asset-processing-service/browser-runtime-asset.factory.js +48 -0
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.d.ts +20 -0
- package/src/services/assets/asset-processing-service/browser-runtime-entry.factory.js +41 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/index.d.ts +2 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/index.js +2 -0
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.interface.d.ts +1 -1
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-processor.d.ts +1 -1
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-processor.js +9 -4
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-script-processor.d.ts +3 -2
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/base/base-script-processor.js +14 -22
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/file-script.processor.d.ts +1 -1
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/file-script.processor.js +2 -2
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/node-module-script.processor.js +5 -4
- package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/file-stylesheet.processor.js +4 -1
- package/src/services/assets/browser-bundle.service.d.ts +32 -0
- package/src/services/assets/browser-bundle.service.js +33 -0
- package/src/services/{page-request-cache-coordinator.service.d.ts → cache/page-request-cache-coordinator.service.d.ts} +2 -2
- package/src/services/{page-request-cache-coordinator.service.js → cache/page-request-cache-coordinator.service.js} +3 -1
- package/src/services/html/html-rewriter-provider.service.d.ts +37 -0
- package/src/services/html/html-rewriter-provider.service.js +65 -0
- package/src/services/html/html-transformer.service.d.ts +77 -0
- package/src/services/html/html-transformer.service.js +221 -0
- package/src/services/invalidation/development-invalidation.service.d.ts +74 -0
- package/src/services/invalidation/development-invalidation.service.js +189 -0
- package/src/services/module-loading/app-server-module-transpiler.service.d.ts +16 -0
- package/src/services/module-loading/app-server-module-transpiler.service.js +34 -0
- package/src/services/module-loading/page-module-import.service.d.ts +71 -0
- package/src/services/module-loading/page-module-import.service.js +132 -0
- package/src/services/module-loading/server-loader.service.d.ts +96 -0
- package/src/services/module-loading/server-loader.service.js +32 -0
- package/src/services/module-loading/server-module-transpiler.service.d.ts +69 -0
- package/src/services/module-loading/server-module-transpiler.service.js +61 -0
- package/src/services/runtime-manifest/node-runtime-manifest.service.d.ts +35 -0
- package/src/services/runtime-manifest/node-runtime-manifest.service.js +60 -0
- package/src/services/runtime-state/dev-graph.service.d.ts +118 -0
- package/src/services/runtime-state/dev-graph.service.js +162 -0
- package/src/services/runtime-state/entrypoint-dependency-graph.service.d.ts +41 -0
- package/src/services/runtime-state/entrypoint-dependency-graph.service.js +85 -0
- package/src/services/runtime-state/runtime-specifier-registry.service.d.ts +69 -0
- package/src/services/runtime-state/runtime-specifier-registry.service.js +37 -0
- package/src/services/runtime-state/server-invalidation-state.service.d.ts +26 -0
- package/src/services/runtime-state/server-invalidation-state.service.js +35 -0
- package/src/services/{schema-validation-service.d.ts → validation/schema-validation-service.d.ts} +1 -1
- package/src/static-site-generator/README.md +26 -0
- package/src/static-site-generator/static-site-generator.d.ts +53 -1
- package/src/static-site-generator/static-site-generator.js +86 -5
- package/src/utils/resolve-work-dir.d.ts +11 -0
- package/src/utils/resolve-work-dir.js +31 -0
- package/src/watchers/project-watcher.d.ts +37 -21
- package/src/watchers/project-watcher.js +109 -66
- package/src/watchers/project-watcher.test-helpers.js +1 -0
- package/src/adapters/abstract/application-adapter.ts +0 -337
- package/src/adapters/abstract/router-adapter.ts +0 -30
- package/src/adapters/abstract/server-adapter.ts +0 -79
- package/src/adapters/bun/client-bridge.ts +0 -62
- package/src/adapters/bun/create-app.ts +0 -189
- package/src/adapters/bun/define-api-handler.d.ts +0 -61
- package/src/adapters/bun/define-api-handler.ts +0 -114
- package/src/adapters/bun/hmr-manager.ts +0 -281
- package/src/adapters/bun/index.ts +0 -3
- package/src/adapters/bun/server-adapter.ts +0 -492
- package/src/adapters/bun/server-lifecycle.ts +0 -154
- package/src/adapters/index.ts +0 -6
- package/src/adapters/node/create-app.ts +0 -179
- package/src/adapters/node/index.ts +0 -9
- package/src/adapters/node/node-client-bridge.ts +0 -79
- package/src/adapters/node/node-hmr-manager.ts +0 -271
- package/src/adapters/node/server-adapter.ts +0 -561
- package/src/adapters/node/static-content-server.ts +0 -203
- package/src/adapters/shared/api-response.ts +0 -104
- package/src/adapters/shared/application-adapter.ts +0 -199
- package/src/adapters/shared/explicit-static-route-matcher.ts +0 -134
- package/src/adapters/shared/file-route-middleware-pipeline.ts +0 -123
- package/src/adapters/shared/fs-server-response-factory.ts +0 -118
- package/src/adapters/shared/fs-server-response-matcher.ts +0 -198
- package/src/adapters/shared/render-context.ts +0 -105
- package/src/adapters/shared/server-adapter.ts +0 -442
- package/src/adapters/shared/server-route-handler.ts +0 -166
- package/src/adapters/shared/server-static-builder.ts +0 -82
- package/src/build/build-adapter.ts +0 -132
- package/src/build/build-types.ts +0 -83
- package/src/build/esbuild-build-adapter.ts +0 -510
- package/src/config/config-builder.ts +0 -474
- package/src/constants.ts +0 -39
- package/src/create-app.ts +0 -87
- package/src/define-api-handler.js +0 -15
- package/src/define-api-handler.ts +0 -66
- package/src/dev/sc-server.ts +0 -143
- package/src/eco/component-render-context.ts +0 -202
- package/src/eco/eco.ts +0 -221
- package/src/eco/eco.types.ts +0 -202
- package/src/eco/eco.utils.ts +0 -89
- package/src/eco/global-injector-map.ts +0 -112
- package/src/eco/lazy-injector-map.ts +0 -120
- package/src/eco/module-dependencies.ts +0 -75
- package/src/errors/http-error.ts +0 -72
- package/src/errors/index.ts +0 -2
- package/src/errors/locals-access-error.ts +0 -7
- package/src/global/app-logger.ts +0 -4
- 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 +0 -121
- package/src/hmr/hmr-strategy.ts +0 -172
- package/src/hmr/hmr.test.e2e.ts +0 -75
- package/src/hmr/strategies/default-hmr-strategy.ts +0 -60
- package/src/hmr/strategies/js-hmr-strategy.ts +0 -308
- package/src/index.browser.ts +0 -3
- package/src/index.ts +0 -5
- package/src/integrations/ghtml/ghtml-renderer.ts +0 -93
- package/src/integrations/ghtml/ghtml.plugin.ts +0 -32
- package/src/internal-types.ts +0 -212
- package/src/plugins/alias-resolver-plugin.ts +0 -45
- package/src/plugins/eco-component-meta-plugin.ts +0 -474
- package/src/plugins/integration-plugin.ts +0 -184
- package/src/plugins/processor.ts +0 -220
- package/src/public-types.ts +0 -1255
- package/src/route-renderer/component-graph-executor.ts +0 -84
- package/src/route-renderer/component-graph.ts +0 -159
- package/src/route-renderer/component-marker.ts +0 -117
- package/src/route-renderer/dependency-resolver.ts +0 -596
- 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.ts +0 -696
- package/src/route-renderer/marker-graph-resolver.ts +0 -153
- package/src/route-renderer/page-module-loader.d.ts +0 -61
- package/src/route-renderer/page-module-loader.ts +0 -153
- package/src/route-renderer/render-execution.service.ts +0 -158
- package/src/route-renderer/render-preparation.service.ts +0 -358
- package/src/route-renderer/route-renderer.ts +0 -80
- package/src/router/fs-router-scanner.ts +0 -217
- package/src/router/fs-router.ts +0 -122
- package/src/services/asset-processing-service/asset-processing.service.d.ts +0 -41
- package/src/services/asset-processing-service/asset-processing.service.ts +0 -306
- package/src/services/asset-processing-service/asset.factory.ts +0 -105
- package/src/services/asset-processing-service/assets.types.ts +0 -112
- package/src/services/asset-processing-service/index.ts +0 -3
- package/src/services/asset-processing-service/processor.interface.ts +0 -27
- package/src/services/asset-processing-service/processor.registry.ts +0 -18
- package/src/services/asset-processing-service/processors/base/base-processor.ts +0 -76
- package/src/services/asset-processing-service/processors/base/base-script-processor.ts +0 -105
- package/src/services/asset-processing-service/processors/index.ts +0 -5
- package/src/services/asset-processing-service/processors/script/content-script.processor.ts +0 -66
- package/src/services/asset-processing-service/processors/script/file-script.processor.ts +0 -88
- package/src/services/asset-processing-service/processors/script/node-module-script.processor.ts +0 -84
- package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.ts +0 -27
- package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.ts +0 -77
- package/src/services/cache/cache.types.ts +0 -126
- package/src/services/cache/index.ts +0 -18
- package/src/services/cache/memory-cache-store.ts +0 -130
- package/src/services/cache/page-cache-service.ts +0 -202
- 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.ts +0 -128
- package/src/services/schema-validation-service.ts +0 -204
- package/src/services/validation/standard-schema.types.ts +0 -68
- package/src/static-site-generator/static-site-generator.ts +0 -359
- package/src/utils/css.ts +0 -5
- package/src/utils/deep-merge.ts +0 -47
- package/src/utils/hash.ts +0 -5
- package/src/utils/html.ts +0 -1
- package/src/utils/invariant.ts +0 -15
- package/src/utils/locals-utils.ts +0 -37
- package/src/utils/parse-cli-args.ts +0 -83
- package/src/utils/path-utils.module.ts +0 -14
- package/src/utils/runtime.ts +0 -44
- package/src/utils/server-utils.module.ts +0 -67
- package/src/watchers/project-watcher.test-helpers.ts +0 -40
- package/src/watchers/project-watcher.ts +0 -306
- /package/src/adapters/{bun → shared}/define-api-handler.js +0 -0
- /package/src/{services/asset-processing-service/assets.types.js → plugins/runtime-capability.js} +0 -0
- /package/src/route-renderer/{component-graph-executor.d.ts → component-graph/component-graph-executor.d.ts} +0 -0
- /package/src/route-renderer/{component-graph-executor.js → component-graph/component-graph-executor.js} +0 -0
- /package/src/route-renderer/{component-graph.d.ts → component-graph/component-graph.d.ts} +0 -0
- /package/src/route-renderer/{component-graph.js → component-graph/component-graph.js} +0 -0
- /package/src/route-renderer/{component-marker.d.ts → component-graph/component-marker.d.ts} +0 -0
- /package/src/route-renderer/{component-marker.js → component-graph/component-marker.js} +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/asset.factory.d.ts +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.interface.js +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.registry.d.ts +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processor.registry.js +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/index.d.ts +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/index.js +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/content-script.processor.d.ts +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/content-script.processor.js +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/script/node-module-script.processor.d.ts +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/content-stylesheet.processor.d.ts +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/content-stylesheet.processor.js +0 -0
- /package/src/services/{asset-processing-service → assets/asset-processing-service}/processors/stylesheet/file-stylesheet.processor.d.ts +0 -0
- /package/src/services/{schema-validation-service.js → validation/schema-validation-service.js} +0 -0
|
@@ -1,15 +1,50 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_ECOPAGES_DIST_DIR,
|
|
4
|
+
DEFAULT_ECOPAGES_HOSTNAME,
|
|
5
|
+
DEFAULT_ECOPAGES_PORT,
|
|
6
|
+
DEFAULT_ECOPAGES_WORK_DIR
|
|
7
|
+
} from "../constants.js";
|
|
8
|
+
import {
|
|
9
|
+
collectConfiguredAppBuildManifestContributions,
|
|
10
|
+
createBuildAdapter,
|
|
11
|
+
getAppServerBuildPlugins,
|
|
12
|
+
setAppBuildAdapter,
|
|
13
|
+
setAppBuildExecutor,
|
|
14
|
+
updateAppBuildManifest
|
|
15
|
+
} from "../build/build-adapter.js";
|
|
16
|
+
import { createAppBuildExecutor } from "../build/dev-build-coordinator.js";
|
|
3
17
|
import { GHTML_PLUGIN_NAME, ghtmlPlugin } from "../integrations/ghtml/ghtml.plugin.js";
|
|
4
18
|
import { createEcoComponentMetaPlugin } from "../plugins/eco-component-meta-plugin.js";
|
|
19
|
+
import {
|
|
20
|
+
NoopEntrypointDependencyGraph,
|
|
21
|
+
setAppEntrypointDependencyGraph
|
|
22
|
+
} from "../services/runtime-state/entrypoint-dependency-graph.service.js";
|
|
23
|
+
import {
|
|
24
|
+
createNodeRuntimeManifest,
|
|
25
|
+
setAppNodeRuntimeManifest
|
|
26
|
+
} from "../services/runtime-manifest/node-runtime-manifest.service.js";
|
|
27
|
+
import {
|
|
28
|
+
InMemoryRuntimeSpecifierRegistry,
|
|
29
|
+
setAppRuntimeSpecifierRegistry
|
|
30
|
+
} from "../services/runtime-state/runtime-specifier-registry.service.js";
|
|
31
|
+
import {
|
|
32
|
+
CounterServerInvalidationState,
|
|
33
|
+
setAppServerInvalidationState
|
|
34
|
+
} from "../services/runtime-state/server-invalidation-state.service.js";
|
|
5
35
|
import { invariant } from "../utils/invariant.js";
|
|
6
36
|
import { appLogger } from "../global/app-logger.js";
|
|
37
|
+
import { fileSystem } from "@ecopages/file-system";
|
|
7
38
|
const CONFIG_BUILDER_ERRORS = {
|
|
8
39
|
DUPLICATE_INTEGRATION_NAMES: "Integrations names must be unique",
|
|
9
40
|
DUPLICATE_INTEGRATION_EXTENSIONS: "Integrations extensions must be unique",
|
|
10
41
|
MIXED_JSX_ENGINES: "Both kitajs and react integrations are enabled. Use per-file JSX import source/pragma consistently (e.g. `/** @jsxImportSource react */` for React files and `/** @jsxImportSource @kitajs/html */` for Kita files).",
|
|
11
42
|
duplicateProcessorName: (name) => `Processor with name "${name}" already exists`,
|
|
12
|
-
duplicateLoaderName: (name) => `Loader with name "${name}" already exists
|
|
43
|
+
duplicateLoaderName: (name) => `Loader with name "${name}" already exists`,
|
|
44
|
+
duplicateSemanticTemplate: (kind, matches) => `Multiple ${kind} templates found: ${matches.join(", ")}`,
|
|
45
|
+
incompatibleRuntimeCapability: (kind, name, runtime, reason) => `Cannot enable ${kind} "${name}" on ${runtime}: ${reason}`,
|
|
46
|
+
unsupportedRuntimeVersion: (kind, name, runtime, current, min) => `Cannot enable ${kind} "${name}" on ${runtime} ${current}: requires runtime version ${min} or newer`,
|
|
47
|
+
invalidRuntimeVersion: (kind, name, version) => `Cannot validate ${kind} "${name}" runtimeCapability.minRuntimeVersion "${version}" because it is not a dot-separated numeric version`
|
|
13
48
|
};
|
|
14
49
|
class ConfigBuilder {
|
|
15
50
|
config = {
|
|
@@ -21,12 +56,6 @@ class ConfigBuilder {
|
|
|
21
56
|
componentsDir: "components",
|
|
22
57
|
layoutsDir: "layouts",
|
|
23
58
|
publicDir: "public",
|
|
24
|
-
includesTemplates: {
|
|
25
|
-
head: "head.ghtml.ts",
|
|
26
|
-
html: "html.ghtml.ts",
|
|
27
|
-
seo: "seo.ghtml.ts"
|
|
28
|
-
},
|
|
29
|
-
error404Template: "404.ghtml.ts",
|
|
30
59
|
robotsTxt: {
|
|
31
60
|
preferences: {
|
|
32
61
|
"*": []
|
|
@@ -34,7 +63,7 @@ class ConfigBuilder {
|
|
|
34
63
|
},
|
|
35
64
|
integrations: [],
|
|
36
65
|
integrationsDependencies: [],
|
|
37
|
-
distDir:
|
|
66
|
+
distDir: DEFAULT_ECOPAGES_DIST_DIR,
|
|
38
67
|
defaultMetadata: {
|
|
39
68
|
title: "Ecopages",
|
|
40
69
|
description: "This is a static site generated with Ecopages"
|
|
@@ -45,6 +74,7 @@ class ConfigBuilder {
|
|
|
45
74
|
config: "",
|
|
46
75
|
componentsDir: "",
|
|
47
76
|
distDir: "",
|
|
77
|
+
workDir: "",
|
|
48
78
|
includesDir: "",
|
|
49
79
|
layoutsDir: "",
|
|
50
80
|
pagesDir: "",
|
|
@@ -55,7 +85,8 @@ class ConfigBuilder {
|
|
|
55
85
|
error404TemplatePath: ""
|
|
56
86
|
},
|
|
57
87
|
processors: /* @__PURE__ */ new Map(),
|
|
58
|
-
loaders: /* @__PURE__ */ new Map()
|
|
88
|
+
loaders: /* @__PURE__ */ new Map(),
|
|
89
|
+
workDir: DEFAULT_ECOPAGES_WORK_DIR
|
|
59
90
|
};
|
|
60
91
|
/**
|
|
61
92
|
* Sets the base URL for the application.
|
|
@@ -145,27 +176,6 @@ class ConfigBuilder {
|
|
|
145
176
|
this.config.publicDir = publicDir;
|
|
146
177
|
return this;
|
|
147
178
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Sets the templates used for includes.
|
|
150
|
-
* These templates are used to build the HTML structure of pages.
|
|
151
|
-
*
|
|
152
|
-
* @param includesTemplates - An object containing the template file names
|
|
153
|
-
* @returns The ConfigBuilder instance for method chaining
|
|
154
|
-
*/
|
|
155
|
-
setIncludesTemplates(includesTemplates) {
|
|
156
|
-
this.config.includesTemplates = includesTemplates;
|
|
157
|
-
return this;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Sets the template file for the 404 error page.
|
|
161
|
-
*
|
|
162
|
-
* @param error404Template - The file name of the 404 error template (default: '404.ghtml.ts')
|
|
163
|
-
* @returns The ConfigBuilder instance for method chaining
|
|
164
|
-
*/
|
|
165
|
-
setError404Template(error404Template) {
|
|
166
|
-
this.config.error404Template = error404Template;
|
|
167
|
-
return this;
|
|
168
|
-
}
|
|
169
179
|
/**
|
|
170
180
|
* Sets the robots.txt configuration.
|
|
171
181
|
* This determines which paths are allowed/disallowed for search engines.
|
|
@@ -191,13 +201,28 @@ class ConfigBuilder {
|
|
|
191
201
|
/**
|
|
192
202
|
* Sets the output directory for the built application.
|
|
193
203
|
*
|
|
194
|
-
* @param distDir - The distribution directory name (default: '
|
|
204
|
+
* @param distDir - The distribution directory name (default: 'dist')
|
|
195
205
|
* @returns The ConfigBuilder instance for method chaining
|
|
196
206
|
*/
|
|
197
207
|
setDistDir(distDir) {
|
|
198
208
|
this.config.distDir = distDir;
|
|
199
209
|
return this;
|
|
200
210
|
}
|
|
211
|
+
/**
|
|
212
|
+
* Sets the internal work directory for runtime-only artifacts.
|
|
213
|
+
*
|
|
214
|
+
* @remarks
|
|
215
|
+
* Use this when deployable output should stay clean while Ecopages still
|
|
216
|
+
* needs a separate workspace for server transpilation caches, runtime
|
|
217
|
+
* manifests, and other internal build products.
|
|
218
|
+
*
|
|
219
|
+
* @param workDir - The internal work directory name
|
|
220
|
+
* @returns The ConfigBuilder instance for method chaining
|
|
221
|
+
*/
|
|
222
|
+
setWorkDir(workDir) {
|
|
223
|
+
this.config.workDir = workDir;
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
201
226
|
/**
|
|
202
227
|
* Sets the default metadata for pages.
|
|
203
228
|
* This is used when a page doesn't specify its own metadata.
|
|
@@ -294,35 +319,44 @@ class ConfigBuilder {
|
|
|
294
319
|
return this;
|
|
295
320
|
}
|
|
296
321
|
createAbsolutePaths(config) {
|
|
297
|
-
const {
|
|
298
|
-
srcDir,
|
|
299
|
-
componentsDir,
|
|
300
|
-
includesDir,
|
|
301
|
-
layoutsDir,
|
|
302
|
-
pagesDir,
|
|
303
|
-
publicDir,
|
|
304
|
-
distDir,
|
|
305
|
-
includesTemplates,
|
|
306
|
-
error404Template
|
|
307
|
-
} = config;
|
|
322
|
+
const { srcDir, componentsDir, includesDir, layoutsDir, pagesDir, publicDir, distDir, workDir } = config;
|
|
308
323
|
const projectDir = config.rootDir;
|
|
309
324
|
const absoluteSrcDir = path.resolve(projectDir, srcDir);
|
|
310
325
|
const absoluteDistDir = path.resolve(projectDir, distDir);
|
|
326
|
+
const absoluteWorkDir = path.resolve(projectDir, workDir);
|
|
327
|
+
const absoluteIncludesDir = path.join(absoluteSrcDir, includesDir);
|
|
328
|
+
const absolutePagesDir = path.join(absoluteSrcDir, pagesDir);
|
|
311
329
|
this.config.absolutePaths = {
|
|
312
330
|
config: path.join(projectDir, "eco.config.ts"),
|
|
313
331
|
projectDir,
|
|
314
332
|
srcDir: absoluteSrcDir,
|
|
315
333
|
distDir: absoluteDistDir,
|
|
334
|
+
workDir: absoluteWorkDir,
|
|
316
335
|
componentsDir: path.join(absoluteSrcDir, componentsDir),
|
|
317
|
-
includesDir:
|
|
336
|
+
includesDir: absoluteIncludesDir,
|
|
318
337
|
layoutsDir: path.join(absoluteSrcDir, layoutsDir),
|
|
319
|
-
pagesDir:
|
|
338
|
+
pagesDir: absolutePagesDir,
|
|
320
339
|
publicDir: path.join(absoluteSrcDir, publicDir),
|
|
321
|
-
htmlTemplatePath:
|
|
322
|
-
|
|
340
|
+
htmlTemplatePath: this.resolveSemanticTemplatePath({
|
|
341
|
+
dirPath: absoluteIncludesDir,
|
|
342
|
+
basename: "html"
|
|
343
|
+
}),
|
|
344
|
+
error404TemplatePath: this.resolveSemanticTemplatePath({
|
|
345
|
+
dirPath: absolutePagesDir,
|
|
346
|
+
basename: "404"
|
|
347
|
+
})
|
|
323
348
|
};
|
|
324
349
|
return this;
|
|
325
350
|
}
|
|
351
|
+
resolveSemanticTemplatePath({ dirPath, basename }) {
|
|
352
|
+
const extensions = this.config.templatesExt.length > 0 ? this.config.templatesExt : [".ghtml.ts"];
|
|
353
|
+
const matches = extensions.map((extension) => path.join(dirPath, `${basename}${extension}`)).filter((candidate) => fileSystem.exists(candidate));
|
|
354
|
+
invariant(matches.length <= 1, CONFIG_BUILDER_ERRORS.duplicateSemanticTemplate(basename, matches));
|
|
355
|
+
if (matches.length === 1) {
|
|
356
|
+
return matches[0];
|
|
357
|
+
}
|
|
358
|
+
return path.join(dirPath, `${basename}${extensions[0]}`);
|
|
359
|
+
}
|
|
326
360
|
createIntegrationTemplatesExt(integrations) {
|
|
327
361
|
const integrationName = integrations.map((integration) => integration.name);
|
|
328
362
|
const uniqueName = new Set(integrationName);
|
|
@@ -345,6 +379,129 @@ class ConfigBuilder {
|
|
|
345
379
|
processor.setContext(this.config);
|
|
346
380
|
}
|
|
347
381
|
}
|
|
382
|
+
validateRuntimeCapabilities() {
|
|
383
|
+
const runtimeEnvironment = this.detectRuntimeEnvironment();
|
|
384
|
+
const contributors = [
|
|
385
|
+
...this.config.integrations.map((integration) => ({
|
|
386
|
+
kind: "integration",
|
|
387
|
+
name: integration.name,
|
|
388
|
+
runtimeCapability: integration.runtimeCapability
|
|
389
|
+
})),
|
|
390
|
+
...Array.from(this.config.processors.values(), (processor) => ({
|
|
391
|
+
kind: "processor",
|
|
392
|
+
name: processor.name,
|
|
393
|
+
runtimeCapability: processor.runtimeCapability
|
|
394
|
+
}))
|
|
395
|
+
];
|
|
396
|
+
for (const contributor of contributors) {
|
|
397
|
+
this.validateRuntimeCapability(contributor, runtimeEnvironment);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
validateRuntimeCapability(contributor, environment) {
|
|
401
|
+
const declaration = contributor.runtimeCapability;
|
|
402
|
+
if (!declaration) {
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
for (const tag of declaration.tags) {
|
|
406
|
+
if (environment.supportedTags.has(tag)) {
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
throw new Error(
|
|
410
|
+
CONFIG_BUILDER_ERRORS.incompatibleRuntimeCapability(
|
|
411
|
+
contributor.kind,
|
|
412
|
+
contributor.name,
|
|
413
|
+
environment.runtime,
|
|
414
|
+
this.describeUnsupportedRuntimeTag(tag)
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
if (!declaration.minRuntimeVersion) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
const minVersion = this.parseVersion(declaration.minRuntimeVersion);
|
|
422
|
+
if (!minVersion) {
|
|
423
|
+
throw new Error(
|
|
424
|
+
CONFIG_BUILDER_ERRORS.invalidRuntimeVersion(
|
|
425
|
+
contributor.kind,
|
|
426
|
+
contributor.name,
|
|
427
|
+
declaration.minRuntimeVersion
|
|
428
|
+
)
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
const currentVersion = this.parseVersion(environment.version);
|
|
432
|
+
if (!currentVersion) {
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
435
|
+
if (this.compareVersions(currentVersion, minVersion) >= 0) {
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
throw new Error(
|
|
439
|
+
CONFIG_BUILDER_ERRORS.unsupportedRuntimeVersion(
|
|
440
|
+
contributor.kind,
|
|
441
|
+
contributor.name,
|
|
442
|
+
environment.runtime,
|
|
443
|
+
environment.version,
|
|
444
|
+
declaration.minRuntimeVersion
|
|
445
|
+
)
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
detectRuntimeEnvironment() {
|
|
449
|
+
const bunVersion = this.getBunVersion();
|
|
450
|
+
if (bunVersion) {
|
|
451
|
+
return {
|
|
452
|
+
runtime: "bun",
|
|
453
|
+
version: bunVersion,
|
|
454
|
+
supportedTags: /* @__PURE__ */ new Set([
|
|
455
|
+
"bun-only",
|
|
456
|
+
"node-compatible",
|
|
457
|
+
"requires-native-bun-api",
|
|
458
|
+
"requires-node-builtins"
|
|
459
|
+
])
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
runtime: "node",
|
|
464
|
+
version: process.versions.node,
|
|
465
|
+
supportedTags: /* @__PURE__ */ new Set(["node-compatible", "requires-node-builtins"])
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
getBunVersion() {
|
|
469
|
+
const bun = globalThis;
|
|
470
|
+
return typeof bun.Bun?.version === "string" ? bun.Bun.version : void 0;
|
|
471
|
+
}
|
|
472
|
+
describeUnsupportedRuntimeTag(tag) {
|
|
473
|
+
switch (tag) {
|
|
474
|
+
case "bun-only":
|
|
475
|
+
return "it is Bun-only";
|
|
476
|
+
case "requires-native-bun-api":
|
|
477
|
+
return "it requires the native Bun API";
|
|
478
|
+
case "requires-node-builtins":
|
|
479
|
+
return "it requires Node builtins";
|
|
480
|
+
case "node-compatible":
|
|
481
|
+
return "it requires a Node-compatible runtime";
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
parseVersion(version) {
|
|
485
|
+
const normalized = version.trim().replace(/^v/i, "");
|
|
486
|
+
if (!/^\d+(?:\.\d+)*$/.test(normalized)) {
|
|
487
|
+
return void 0;
|
|
488
|
+
}
|
|
489
|
+
return normalized.split(".").map((segment) => Number(segment));
|
|
490
|
+
}
|
|
491
|
+
compareVersions(left, right) {
|
|
492
|
+
const maxLength = Math.max(left.length, right.length);
|
|
493
|
+
for (let index = 0; index < maxLength; index += 1) {
|
|
494
|
+
const leftValue = left[index] ?? 0;
|
|
495
|
+
const rightValue = right[index] ?? 0;
|
|
496
|
+
if (leftValue > rightValue) {
|
|
497
|
+
return 1;
|
|
498
|
+
}
|
|
499
|
+
if (leftValue < rightValue) {
|
|
500
|
+
return -1;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return 0;
|
|
504
|
+
}
|
|
348
505
|
/**
|
|
349
506
|
* Initializes default loaders that are required for EcoPages to function.
|
|
350
507
|
* This includes the eco-component-meta-plugin which auto-injects __eco metadata into component configs.
|
|
@@ -379,10 +536,26 @@ class ConfigBuilder {
|
|
|
379
536
|
if (!this.config.integrations.some((integration) => integration.name === GHTML_PLUGIN_NAME)) {
|
|
380
537
|
this.config.integrations.push(ghtmlPlugin());
|
|
381
538
|
}
|
|
382
|
-
this.createAbsolutePaths(this.config);
|
|
383
539
|
this.createIntegrationTemplatesExt(this.config.integrations);
|
|
540
|
+
this.createAbsolutePaths(this.config);
|
|
384
541
|
await this.initializeDefaultLoaders();
|
|
385
542
|
this.initializeProcessors();
|
|
543
|
+
this.validateRuntimeCapabilities();
|
|
544
|
+
const buildAdapter = createBuildAdapter();
|
|
545
|
+
setAppBuildAdapter(this.config, buildAdapter);
|
|
546
|
+
updateAppBuildManifest(this.config, await collectConfiguredAppBuildManifestContributions(this.config));
|
|
547
|
+
setAppServerInvalidationState(this.config, new CounterServerInvalidationState());
|
|
548
|
+
setAppEntrypointDependencyGraph(this.config, new NoopEntrypointDependencyGraph());
|
|
549
|
+
setAppRuntimeSpecifierRegistry(this.config, new InMemoryRuntimeSpecifierRegistry());
|
|
550
|
+
setAppBuildExecutor(
|
|
551
|
+
this.config,
|
|
552
|
+
createAppBuildExecutor({
|
|
553
|
+
development: false,
|
|
554
|
+
adapter: buildAdapter,
|
|
555
|
+
getPlugins: () => getAppServerBuildPlugins(this.config)
|
|
556
|
+
})
|
|
557
|
+
);
|
|
558
|
+
setAppNodeRuntimeManifest(this.config, createNodeRuntimeManifest(this.config));
|
|
386
559
|
return this.config;
|
|
387
560
|
}
|
|
388
561
|
}
|
package/src/constants.d.ts
CHANGED
|
@@ -30,3 +30,16 @@ export declare const GENERATED_BASE_PATHS: {
|
|
|
30
30
|
};
|
|
31
31
|
export declare const DEFAULT_ECOPAGES_PORT = 3000;
|
|
32
32
|
export declare const DEFAULT_ECOPAGES_HOSTNAME = "localhost";
|
|
33
|
+
/**
|
|
34
|
+
* Default directory used for deployable output.
|
|
35
|
+
*/
|
|
36
|
+
export declare const DEFAULT_ECOPAGES_DIST_DIR = "dist";
|
|
37
|
+
/**
|
|
38
|
+
* Default internal working directory used for runtime-only artifacts.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* This directory is a local tool workspace and is not intended for deployment.
|
|
42
|
+
* It owns transpiled server modules, runtime manifests, and processor caches
|
|
43
|
+
* so the export directory can remain a clean deployable tree.
|
|
44
|
+
*/
|
|
45
|
+
export declare const DEFAULT_ECOPAGES_WORK_DIR = ".eco";
|
package/src/constants.js
CHANGED
|
@@ -10,9 +10,13 @@ const GENERATED_BASE_PATHS = {
|
|
|
10
10
|
};
|
|
11
11
|
const DEFAULT_ECOPAGES_PORT = 3e3;
|
|
12
12
|
const DEFAULT_ECOPAGES_HOSTNAME = "localhost";
|
|
13
|
+
const DEFAULT_ECOPAGES_DIST_DIR = "dist";
|
|
14
|
+
const DEFAULT_ECOPAGES_WORK_DIR = ".eco";
|
|
13
15
|
export {
|
|
16
|
+
DEFAULT_ECOPAGES_DIST_DIR,
|
|
14
17
|
DEFAULT_ECOPAGES_HOSTNAME,
|
|
15
18
|
DEFAULT_ECOPAGES_PORT,
|
|
19
|
+
DEFAULT_ECOPAGES_WORK_DIR,
|
|
16
20
|
GENERATED_BASE_PATHS,
|
|
17
21
|
IS_BUN,
|
|
18
22
|
RESOLVED_ASSETS_DIR,
|
package/src/declarations.d.ts
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import type { EcoPagesAppConfig } from './internal-types';
|
|
2
|
+
import type { EcoNavigationRuntime } from './router/client/navigation-coordinator';
|
|
2
3
|
|
|
3
4
|
type HMRHandler = (url: string) => Promise<void>;
|
|
4
|
-
|
|
5
|
-
type
|
|
5
|
+
type CleanupPageRootFunction = () => void;
|
|
6
|
+
type EcoPageRoot = { render: (node: unknown) => void; unmount: () => void };
|
|
7
|
+
type EcoPageData = {
|
|
8
|
+
module: string;
|
|
9
|
+
props: Record<string, unknown>;
|
|
10
|
+
};
|
|
11
|
+
type EcoPagesWindowRuntime = {
|
|
12
|
+
hmrHandlers?: Record<string, HMRHandler>;
|
|
13
|
+
navigation?: EcoNavigationRuntime;
|
|
14
|
+
react?: {
|
|
15
|
+
cleanupPageRoot?: CleanupPageRootFunction;
|
|
16
|
+
pageRoot?: EcoPageRoot | null;
|
|
17
|
+
};
|
|
18
|
+
page?: EcoPageData;
|
|
19
|
+
};
|
|
6
20
|
|
|
7
21
|
declare global {
|
|
8
|
-
var ecoConfig: EcoPagesAppConfig;
|
|
9
|
-
|
|
10
22
|
interface Window {
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
/** Function to reload the current page, used for layout updates */
|
|
14
|
-
__ecopages_reload_current_page__?: ReloadPageFunction;
|
|
15
|
-
/** Page data registry - contains module path and props for current page */
|
|
16
|
-
__ECO_PAGE__?: {
|
|
17
|
-
module: string;
|
|
18
|
-
props: Record<string, unknown>;
|
|
19
|
-
};
|
|
23
|
+
/** Shared Ecopages browser runtime state */
|
|
24
|
+
__ECO_PAGES__?: EcoPagesWindowRuntime;
|
|
20
25
|
}
|
|
21
26
|
}
|
|
22
27
|
|
package/src/eco/README.md
CHANGED
|
@@ -7,10 +7,12 @@ A unified API for defining components, pages, and page data in EcoPages.
|
|
|
7
7
|
The `eco` namespace provides a consistent, type-safe interface for:
|
|
8
8
|
|
|
9
9
|
1. **`eco.component()`** - Factory for defining reusable components with dependencies and optional lazy-loading
|
|
10
|
-
2. **`eco.
|
|
11
|
-
3. **`eco.
|
|
12
|
-
4. **`eco.
|
|
13
|
-
5. **`eco.
|
|
10
|
+
2. **`eco.html()`** - Semantic alias for the document shell component (the outermost HTML wrapper)
|
|
11
|
+
3. **`eco.layout()`** - Semantic alias for route layout components (page-level wrappers)
|
|
12
|
+
4. **`eco.page()`** - Factory for defining page components with optional inline `staticPaths`, `staticProps`, and `metadata`
|
|
13
|
+
5. **`eco.metadata()`** - Type-safe wrapper for page metadata (legacy pattern)
|
|
14
|
+
6. **`eco.staticPaths()`** - Type-safe wrapper for dynamic route generation (legacy pattern)
|
|
15
|
+
7. **`eco.staticProps()`** - Type-safe wrapper for static data fetching (legacy pattern)
|
|
14
16
|
|
|
15
17
|
## Component Patterns
|
|
16
18
|
|
|
@@ -42,9 +44,9 @@ export function Card({ children, class: className }: CardProps) {
|
|
|
42
44
|
|
|
43
45
|
> **Note:** If your component requires a dedicated CSS file, use `eco.component()` instead to manage the stylesheet dependency.
|
|
44
46
|
|
|
45
|
-
### Plain React Components
|
|
47
|
+
### Plain React Components
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
React components with hooks and Tailwind CSS work out of the box without `eco.component()`. Standard React components can be used directly:
|
|
48
50
|
|
|
49
51
|
```tsx
|
|
50
52
|
import { useEffect, useState } from 'react';
|
|
@@ -99,7 +101,6 @@ export function ThemeToggle() {
|
|
|
99
101
|
- React components with hooks (`useState`, `useEffect`, etc.)
|
|
100
102
|
- Components styled with Tailwind CSS classes
|
|
101
103
|
- Interactive UI that doesn't require external scripts or dedicated stylesheets
|
|
102
|
-
- Bun handles all imports automatically
|
|
103
104
|
|
|
104
105
|
> **Note:** Use `eco.component()` only when you need to manage external stylesheets, scripts, or lazy loading. For React components relying solely on hooks and Tailwind, plain functions are simpler and sufficient.
|
|
105
106
|
|
|
@@ -128,14 +129,14 @@ export const Counter = eco.component({
|
|
|
128
129
|
|
|
129
130
|
### Comparison
|
|
130
131
|
|
|
131
|
-
| Aspect | Simple JSX | Plain React
|
|
132
|
-
| -------------------- | ---------- |
|
|
133
|
-
| React hooks | No | Yes
|
|
134
|
-
| Scripts/Stylesheets | No | No
|
|
135
|
-
| Lazy loading | No | No
|
|
136
|
-
| Hydration strategies | No | No
|
|
137
|
-
| Runtime cost | Zero | Minimal
|
|
138
|
-
| Use case | Static UI | Interactive UI
|
|
132
|
+
| Aspect | Simple JSX | Plain React | `eco.component()` |
|
|
133
|
+
| -------------------- | ---------- | -------------- | ----------------- |
|
|
134
|
+
| React hooks | No | Yes | Yes |
|
|
135
|
+
| Scripts/Stylesheets | No | No | Yes |
|
|
136
|
+
| Lazy loading | No | No | Yes |
|
|
137
|
+
| Hydration strategies | No | No | Yes |
|
|
138
|
+
| Runtime cost | Zero | Minimal | Minimal |
|
|
139
|
+
| Use case | Static UI | Interactive UI | Advanced UI |
|
|
139
140
|
|
|
140
141
|
All patterns can coexist in the same project. Use the right tool for the job.
|
|
141
142
|
|
|
@@ -231,6 +232,53 @@ Both patterns work and can be mixed - the renderer checks for attached propertie
|
|
|
231
232
|
|
|
232
233
|
## API Reference
|
|
233
234
|
|
|
235
|
+
### `eco.html()`
|
|
236
|
+
|
|
237
|
+
Creates the document shell component — the outermost HTML wrapper rendered once per page. Semantically equivalent to `eco.component()` but signals intent to tooling and readers that this component owns the full document structure (`<html>`, `<head>`, `<body>`).
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
import { eco } from '@ecopages/core';
|
|
241
|
+
|
|
242
|
+
export const Document = eco.html({
|
|
243
|
+
dependencies: {
|
|
244
|
+
stylesheets: ['./document.css'],
|
|
245
|
+
},
|
|
246
|
+
render: ({ children, metadata }) => (
|
|
247
|
+
<html lang="en">
|
|
248
|
+
<head>
|
|
249
|
+
<title>{metadata?.title ?? 'EcoPages'}</title>
|
|
250
|
+
</head>
|
|
251
|
+
<body>{children}</body>
|
|
252
|
+
</html>
|
|
253
|
+
),
|
|
254
|
+
});
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### `eco.layout()`
|
|
258
|
+
|
|
259
|
+
Creates a route layout component — a wrapper rendered around page content. Semantically equivalent to `eco.component()` but clearly communicates that the component is intended to be used as a `layout` in `eco.page()`.
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
import { eco } from '@ecopages/core';
|
|
263
|
+
|
|
264
|
+
export const BaseLayout = eco.layout({
|
|
265
|
+
dependencies: {
|
|
266
|
+
stylesheets: ['./base-layout.css'],
|
|
267
|
+
scripts: ['./base-layout.script.ts'],
|
|
268
|
+
},
|
|
269
|
+
render: ({ children }) => <main>{children}</main>,
|
|
270
|
+
});
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Use `eco.layout()` components as the `layout` option in `eco.page()`:
|
|
274
|
+
|
|
275
|
+
```tsx
|
|
276
|
+
export default eco.page({
|
|
277
|
+
layout: BaseLayout,
|
|
278
|
+
render: () => <h1>Hello</h1>,
|
|
279
|
+
});
|
|
280
|
+
```
|
|
281
|
+
|
|
234
282
|
### `eco.component()`
|
|
235
283
|
|
|
236
284
|
Define a reusable component with dependencies.
|
|
@@ -516,12 +564,18 @@ interface EcoComponentDependencies {
|
|
|
516
564
|
components?: EcoComponent[];
|
|
517
565
|
}
|
|
518
566
|
|
|
567
|
+
// Shared base option shape used by component(), html(), and layout()
|
|
519
568
|
interface ComponentOptions<P, E = EcoPagesElement> {
|
|
520
569
|
componentDir?: string;
|
|
521
570
|
dependencies?: EcoComponentDependencies;
|
|
522
571
|
render: (props: P) => E;
|
|
523
572
|
}
|
|
524
573
|
|
|
574
|
+
// html() and layout() accept the same options as component() but return
|
|
575
|
+
// narrower types to signal intent (EcoHtmlComponent / EcoLayoutComponent).
|
|
576
|
+
type HtmlOptions<E = EcoPagesElement> = ComponentOptions<Record<string, unknown>, E>;
|
|
577
|
+
type LayoutOptions<E = EcoPagesElement> = ComponentOptions<{ children: E }, E>;
|
|
578
|
+
|
|
525
579
|
interface PageOptions<T, E = EcoPagesElement> {
|
|
526
580
|
componentDir?: string;
|
|
527
581
|
dependencies?: EcoComponentDependencies;
|
|
@@ -551,7 +605,7 @@ type PagePropsFor<T> =
|
|
|
551
605
|
```tsx
|
|
552
606
|
import { eco } from '@ecopages/core';
|
|
553
607
|
|
|
554
|
-
eco. // IDE shows: component, page, metadata, staticPaths, staticProps
|
|
608
|
+
eco. // IDE shows: component, html, layout, page, metadata, staticPaths, staticProps
|
|
555
609
|
```
|
|
556
610
|
|
|
557
611
|
### 2. Type Safety
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EcoComponent } from '../public-types.js';
|
|
2
|
-
import type { MarkerNodeId } from '../route-renderer/component-marker.js';
|
|
2
|
+
import type { MarkerNodeId } from '../route-renderer/component-graph/component-marker.js';
|
|
3
3
|
/**
|
|
4
4
|
* Outcome returned by boundary policy during one component render pass.
|
|
5
5
|
*
|
|
@@ -1,30 +1,39 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
const GLOBAL_COMPONENT_RENDER_CONTEXT_STATE_KEY = "__ECOPAGES_COMPONENT_RENDER_CONTEXT_STATE__";
|
|
2
|
+
function getComponentRenderContextState() {
|
|
3
|
+
const globalScope = globalThis;
|
|
4
|
+
globalScope[GLOBAL_COMPONENT_RENDER_CONTEXT_STATE_KEY] ??= {
|
|
5
|
+
contextStack: [],
|
|
6
|
+
nodeContextStorage: null,
|
|
7
|
+
nodeContextStorageLoader: null
|
|
8
|
+
};
|
|
9
|
+
return globalScope[GLOBAL_COMPONENT_RENDER_CONTEXT_STATE_KEY];
|
|
10
|
+
}
|
|
4
11
|
async function getContextStorage() {
|
|
5
|
-
|
|
6
|
-
|
|
12
|
+
const state = getComponentRenderContextState();
|
|
13
|
+
if (state.nodeContextStorage) {
|
|
14
|
+
return state.nodeContextStorage;
|
|
7
15
|
}
|
|
8
|
-
if (nodeContextStorageLoader) {
|
|
9
|
-
return nodeContextStorageLoader;
|
|
16
|
+
if (state.nodeContextStorageLoader) {
|
|
17
|
+
return state.nodeContextStorageLoader;
|
|
10
18
|
}
|
|
11
|
-
nodeContextStorageLoader = import("node:async_hooks").then((module) => {
|
|
19
|
+
state.nodeContextStorageLoader = import("node:async_hooks").then((module) => {
|
|
12
20
|
const storage = new module.AsyncLocalStorage();
|
|
13
|
-
nodeContextStorage = {
|
|
21
|
+
state.nodeContextStorage = {
|
|
14
22
|
getStore: () => storage.getStore(),
|
|
15
23
|
run: (store, callback) => storage.run(store, callback)
|
|
16
24
|
};
|
|
17
|
-
return nodeContextStorage;
|
|
25
|
+
return state.nodeContextStorage;
|
|
18
26
|
}).catch(() => {
|
|
19
|
-
nodeContextStorage = null;
|
|
27
|
+
state.nodeContextStorage = null;
|
|
20
28
|
return null;
|
|
21
29
|
}).finally(() => {
|
|
22
|
-
nodeContextStorageLoader = null;
|
|
30
|
+
state.nodeContextStorageLoader = null;
|
|
23
31
|
});
|
|
24
|
-
return nodeContextStorageLoader;
|
|
32
|
+
return state.nodeContextStorageLoader;
|
|
25
33
|
}
|
|
26
34
|
function getComponentRenderContext() {
|
|
27
|
-
|
|
35
|
+
const state = getComponentRenderContextState();
|
|
36
|
+
return state.nodeContextStorage?.getStore() ?? state.contextStack[state.contextStack.length - 1];
|
|
28
37
|
}
|
|
29
38
|
function createNodeId(context) {
|
|
30
39
|
context.nextNodeId += 1;
|
|
@@ -53,11 +62,12 @@ async function runWithComponentRenderContext(input, render) {
|
|
|
53
62
|
if (storage) {
|
|
54
63
|
value = await storage.run(context, render);
|
|
55
64
|
} else {
|
|
56
|
-
|
|
65
|
+
const state = getComponentRenderContextState();
|
|
66
|
+
state.contextStack.push(context);
|
|
57
67
|
try {
|
|
58
68
|
value = await render();
|
|
59
69
|
} finally {
|
|
60
|
-
contextStack.pop();
|
|
70
|
+
state.contextStack.pop();
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
73
|
return {
|