@ecopages/core 0.2.0-alpha.1
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 +89 -0
- package/LICENSE +21 -0
- package/README.md +32 -0
- package/package.json +279 -0
- package/src/adapters/abstract/application-adapter.d.ts +168 -0
- package/src/adapters/abstract/application-adapter.js +109 -0
- package/src/adapters/abstract/application-adapter.ts +337 -0
- package/src/adapters/abstract/router-adapter.d.ts +26 -0
- package/src/adapters/abstract/router-adapter.js +5 -0
- package/src/adapters/abstract/router-adapter.ts +30 -0
- package/src/adapters/abstract/server-adapter.d.ts +69 -0
- package/src/adapters/abstract/server-adapter.js +15 -0
- package/src/adapters/abstract/server-adapter.ts +79 -0
- package/src/adapters/bun/client-bridge.d.ts +34 -0
- package/src/adapters/bun/client-bridge.js +48 -0
- package/src/adapters/bun/client-bridge.ts +62 -0
- package/src/adapters/bun/create-app.d.ts +60 -0
- package/src/adapters/bun/create-app.js +117 -0
- package/src/adapters/bun/create-app.ts +189 -0
- package/src/adapters/bun/define-api-handler.d.ts +61 -0
- package/src/adapters/bun/define-api-handler.js +15 -0
- package/src/adapters/bun/define-api-handler.ts +114 -0
- package/src/adapters/bun/hmr-manager.d.ts +84 -0
- package/src/adapters/bun/hmr-manager.js +227 -0
- package/src/adapters/bun/hmr-manager.ts +281 -0
- package/src/adapters/bun/index.d.ts +3 -0
- package/src/adapters/bun/index.js +8 -0
- package/src/adapters/bun/index.ts +3 -0
- package/src/adapters/bun/server-adapter.d.ts +155 -0
- package/src/adapters/bun/server-adapter.js +368 -0
- package/src/adapters/bun/server-adapter.ts +492 -0
- package/src/adapters/bun/server-lifecycle.d.ts +52 -0
- package/src/adapters/bun/server-lifecycle.js +120 -0
- package/src/adapters/bun/server-lifecycle.ts +154 -0
- package/src/adapters/index.d.ts +6 -0
- package/src/adapters/index.js +14 -0
- package/src/adapters/index.ts +6 -0
- package/src/adapters/node/create-app.d.ts +21 -0
- package/src/adapters/node/create-app.js +143 -0
- package/src/adapters/node/create-app.ts +179 -0
- package/src/adapters/node/index.d.ts +4 -0
- package/src/adapters/node/index.js +8 -0
- package/src/adapters/node/index.ts +9 -0
- package/src/adapters/node/node-client-bridge.d.ts +26 -0
- package/src/adapters/node/node-client-bridge.js +66 -0
- package/src/adapters/node/node-client-bridge.ts +79 -0
- package/src/adapters/node/node-hmr-manager.d.ts +62 -0
- package/src/adapters/node/node-hmr-manager.js +221 -0
- package/src/adapters/node/node-hmr-manager.ts +271 -0
- package/src/adapters/node/server-adapter.d.ts +190 -0
- package/src/adapters/node/server-adapter.js +420 -0
- package/src/adapters/node/server-adapter.ts +561 -0
- package/src/adapters/node/static-content-server.d.ts +24 -0
- package/src/adapters/node/static-content-server.js +166 -0
- package/src/adapters/node/static-content-server.ts +203 -0
- package/src/adapters/shared/api-response.d.ts +52 -0
- package/src/adapters/shared/api-response.js +96 -0
- package/src/adapters/shared/api-response.ts +104 -0
- package/src/adapters/shared/application-adapter.d.ts +18 -0
- package/src/adapters/shared/application-adapter.js +90 -0
- package/src/adapters/shared/application-adapter.ts +199 -0
- package/src/adapters/shared/explicit-static-route-matcher.d.ts +38 -0
- package/src/adapters/shared/explicit-static-route-matcher.js +100 -0
- package/src/adapters/shared/explicit-static-route-matcher.ts +134 -0
- package/src/adapters/shared/file-route-middleware-pipeline.d.ts +65 -0
- package/src/adapters/shared/file-route-middleware-pipeline.js +98 -0
- package/src/adapters/shared/file-route-middleware-pipeline.ts +123 -0
- package/src/adapters/shared/fs-server-response-factory.d.ts +19 -0
- package/src/adapters/shared/fs-server-response-factory.js +97 -0
- package/src/adapters/shared/fs-server-response-factory.ts +118 -0
- package/src/adapters/shared/fs-server-response-matcher.d.ts +71 -0
- package/src/adapters/shared/fs-server-response-matcher.js +155 -0
- package/src/adapters/shared/fs-server-response-matcher.ts +198 -0
- package/src/adapters/shared/render-context.d.ts +14 -0
- package/src/adapters/shared/render-context.js +69 -0
- package/src/adapters/shared/render-context.ts +105 -0
- package/src/adapters/shared/server-adapter.d.ts +87 -0
- package/src/adapters/shared/server-adapter.js +353 -0
- package/src/adapters/shared/server-adapter.ts +442 -0
- package/src/adapters/shared/server-route-handler.d.ts +89 -0
- package/src/adapters/shared/server-route-handler.js +120 -0
- package/src/adapters/shared/server-route-handler.ts +166 -0
- package/src/adapters/shared/server-static-builder.d.ts +38 -0
- package/src/adapters/shared/server-static-builder.js +46 -0
- package/src/adapters/shared/server-static-builder.ts +82 -0
- package/src/build/build-adapter.d.ts +74 -0
- package/src/build/build-adapter.js +54 -0
- package/src/build/build-adapter.ts +132 -0
- package/src/build/build-types.d.ts +57 -0
- package/src/build/build-types.js +0 -0
- package/src/build/build-types.ts +83 -0
- package/src/build/esbuild-build-adapter.d.ts +69 -0
- package/src/build/esbuild-build-adapter.js +390 -0
- package/src/build/esbuild-build-adapter.ts +510 -0
- package/src/config/config-builder.d.ts +227 -0
- package/src/config/config-builder.js +392 -0
- package/src/config/config-builder.ts +474 -0
- package/src/constants.d.ts +32 -0
- package/src/constants.js +21 -0
- package/src/constants.ts +39 -0
- package/src/create-app.d.ts +17 -0
- package/src/create-app.js +66 -0
- package/src/create-app.ts +87 -0
- package/src/declarations.d.ts +26 -0
- package/src/define-api-handler.d.ts +25 -0
- package/src/define-api-handler.js +15 -0
- package/src/define-api-handler.ts +66 -0
- package/src/dev/sc-server.d.ts +30 -0
- package/src/dev/sc-server.js +111 -0
- package/src/dev/sc-server.ts +143 -0
- package/src/eco/README.md +636 -0
- package/src/eco/component-render-context.d.ts +105 -0
- package/src/eco/component-render-context.js +77 -0
- package/src/eco/component-render-context.ts +202 -0
- package/src/eco/eco.d.ts +9 -0
- package/src/eco/eco.js +110 -0
- package/src/eco/eco.ts +221 -0
- package/src/eco/eco.types.d.ts +170 -0
- package/src/eco/eco.types.js +0 -0
- package/src/eco/eco.types.ts +202 -0
- package/src/eco/eco.utils.d.ts +40 -0
- package/src/eco/eco.utils.js +40 -0
- package/src/eco/eco.utils.ts +89 -0
- package/src/eco/global-injector-map.d.ts +16 -0
- package/src/eco/global-injector-map.js +80 -0
- package/src/eco/global-injector-map.ts +112 -0
- package/src/eco/lazy-injector-map.d.ts +8 -0
- package/src/eco/lazy-injector-map.js +70 -0
- package/src/eco/lazy-injector-map.ts +120 -0
- package/src/eco/module-dependencies.d.ts +18 -0
- package/src/eco/module-dependencies.js +49 -0
- package/src/eco/module-dependencies.ts +75 -0
- package/src/env.d.ts +20 -0
- package/src/errors/http-error.d.ts +31 -0
- package/src/errors/http-error.js +50 -0
- package/src/errors/http-error.ts +72 -0
- package/src/errors/index.d.ts +2 -0
- package/src/errors/index.js +4 -0
- package/src/errors/index.ts +2 -0
- package/src/errors/locals-access-error.d.ts +4 -0
- package/src/errors/locals-access-error.js +9 -0
- package/src/errors/locals-access-error.ts +7 -0
- package/src/global/app-logger.d.ts +2 -0
- package/src/global/app-logger.js +6 -0
- package/src/global/app-logger.ts +4 -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.d.ts +10 -0
- package/src/hmr/client/hmr-runtime.js +86 -0
- package/src/hmr/client/hmr-runtime.ts +121 -0
- package/src/hmr/hmr-strategy.d.ts +159 -0
- package/src/hmr/hmr-strategy.js +29 -0
- package/src/hmr/hmr-strategy.ts +172 -0
- package/src/hmr/hmr.test.e2e.d.ts +1 -0
- package/src/hmr/hmr.test.e2e.js +50 -0
- package/src/hmr/hmr.test.e2e.ts +75 -0
- package/src/hmr/strategies/default-hmr-strategy.d.ts +43 -0
- package/src/hmr/strategies/default-hmr-strategy.js +34 -0
- package/src/hmr/strategies/default-hmr-strategy.ts +60 -0
- package/src/hmr/strategies/js-hmr-strategy.d.ts +136 -0
- package/src/hmr/strategies/js-hmr-strategy.js +179 -0
- package/src/hmr/strategies/js-hmr-strategy.ts +308 -0
- package/src/index.browser.d.ts +3 -0
- package/src/index.browser.js +4 -0
- package/src/index.browser.ts +3 -0
- package/src/index.d.ts +5 -0
- package/src/index.js +10 -0
- package/src/index.ts +5 -0
- package/src/integrations/ghtml/ghtml-renderer.d.ts +15 -0
- package/src/integrations/ghtml/ghtml-renderer.js +60 -0
- package/src/integrations/ghtml/ghtml-renderer.ts +93 -0
- package/src/integrations/ghtml/ghtml.plugin.d.ts +20 -0
- package/src/integrations/ghtml/ghtml.plugin.js +21 -0
- package/src/integrations/ghtml/ghtml.plugin.ts +32 -0
- package/src/internal-types.d.ts +200 -0
- package/src/internal-types.js +0 -0
- package/src/internal-types.ts +212 -0
- package/src/plugins/alias-resolver-plugin.d.ts +2 -0
- package/src/plugins/alias-resolver-plugin.js +39 -0
- package/src/plugins/alias-resolver-plugin.ts +45 -0
- package/src/plugins/eco-component-meta-plugin.d.ts +95 -0
- package/src/plugins/eco-component-meta-plugin.js +157 -0
- package/src/plugins/eco-component-meta-plugin.ts +474 -0
- package/src/plugins/integration-plugin.d.ts +102 -0
- package/src/plugins/integration-plugin.js +100 -0
- package/src/plugins/integration-plugin.ts +184 -0
- package/src/plugins/processor.d.ts +82 -0
- package/src/plugins/processor.js +122 -0
- package/src/plugins/processor.ts +220 -0
- package/src/public-types.d.ts +1094 -0
- package/src/public-types.js +0 -0
- package/src/public-types.ts +1255 -0
- package/src/route-renderer/GRAPH.md +387 -0
- package/src/route-renderer/README.md +135 -0
- package/src/route-renderer/component-graph-executor.d.ts +32 -0
- package/src/route-renderer/component-graph-executor.js +31 -0
- package/src/route-renderer/component-graph-executor.ts +84 -0
- package/src/route-renderer/component-graph.d.ts +42 -0
- package/src/route-renderer/component-graph.js +72 -0
- package/src/route-renderer/component-graph.ts +159 -0
- package/src/route-renderer/component-marker.d.ts +52 -0
- package/src/route-renderer/component-marker.js +46 -0
- package/src/route-renderer/component-marker.ts +117 -0
- package/src/route-renderer/dependency-resolver.d.ts +24 -0
- package/src/route-renderer/dependency-resolver.js +428 -0
- package/src/route-renderer/dependency-resolver.ts +596 -0
- package/src/route-renderer/html-post-processing.service.d.ts +40 -0
- package/src/route-renderer/html-post-processing.service.js +86 -0
- package/src/route-renderer/html-post-processing.service.ts +103 -0
- package/src/route-renderer/integration-renderer.d.ts +339 -0
- package/src/route-renderer/integration-renderer.js +526 -0
- package/src/route-renderer/integration-renderer.ts +696 -0
- package/src/route-renderer/marker-graph-resolver.d.ts +76 -0
- package/src/route-renderer/marker-graph-resolver.js +93 -0
- package/src/route-renderer/marker-graph-resolver.ts +153 -0
- package/src/route-renderer/page-module-loader.d.ts +61 -0
- package/src/route-renderer/page-module-loader.js +102 -0
- package/src/route-renderer/page-module-loader.ts +153 -0
- package/src/route-renderer/render-execution.service.d.ts +69 -0
- package/src/route-renderer/render-execution.service.js +91 -0
- package/src/route-renderer/render-execution.service.ts +158 -0
- package/src/route-renderer/render-preparation.service.d.ts +112 -0
- package/src/route-renderer/render-preparation.service.js +243 -0
- package/src/route-renderer/render-preparation.service.ts +358 -0
- package/src/route-renderer/route-renderer.d.ts +26 -0
- package/src/route-renderer/route-renderer.js +68 -0
- package/src/route-renderer/route-renderer.ts +80 -0
- package/src/router/fs-router-scanner.d.ts +41 -0
- package/src/router/fs-router-scanner.js +155 -0
- package/src/router/fs-router-scanner.ts +217 -0
- package/src/router/fs-router.d.ts +26 -0
- package/src/router/fs-router.js +100 -0
- package/src/router/fs-router.ts +122 -0
- package/src/services/asset-processing-service/asset-processing.service.d.ts +41 -0
- package/src/services/asset-processing-service/asset-processing.service.js +250 -0
- package/src/services/asset-processing-service/asset-processing.service.ts +306 -0
- package/src/services/asset-processing-service/asset.factory.d.ts +17 -0
- package/src/services/asset-processing-service/asset.factory.js +82 -0
- package/src/services/asset-processing-service/asset.factory.ts +105 -0
- package/src/services/asset-processing-service/assets.types.d.ts +88 -0
- package/src/services/asset-processing-service/assets.types.js +0 -0
- package/src/services/asset-processing-service/assets.types.ts +112 -0
- package/src/services/asset-processing-service/index.d.ts +3 -0
- package/src/services/asset-processing-service/index.js +3 -0
- package/src/services/asset-processing-service/index.ts +3 -0
- package/src/services/asset-processing-service/processor.interface.d.ts +22 -0
- package/src/services/asset-processing-service/processor.interface.js +6 -0
- package/src/services/asset-processing-service/processor.interface.ts +27 -0
- package/src/services/asset-processing-service/processor.registry.d.ts +8 -0
- package/src/services/asset-processing-service/processor.registry.js +15 -0
- package/src/services/asset-processing-service/processor.registry.ts +18 -0
- package/src/services/asset-processing-service/processors/base/base-processor.d.ts +24 -0
- package/src/services/asset-processing-service/processors/base/base-processor.js +59 -0
- package/src/services/asset-processing-service/processors/base/base-processor.ts +76 -0
- package/src/services/asset-processing-service/processors/base/base-script-processor.d.ts +16 -0
- package/src/services/asset-processing-service/processors/base/base-script-processor.js +80 -0
- package/src/services/asset-processing-service/processors/base/base-script-processor.ts +105 -0
- package/src/services/asset-processing-service/processors/index.d.ts +5 -0
- package/src/services/asset-processing-service/processors/index.js +5 -0
- package/src/services/asset-processing-service/processors/index.ts +5 -0
- package/src/services/asset-processing-service/processors/script/content-script.processor.d.ts +5 -0
- package/src/services/asset-processing-service/processors/script/content-script.processor.js +57 -0
- package/src/services/asset-processing-service/processors/script/content-script.processor.ts +66 -0
- package/src/services/asset-processing-service/processors/script/file-script.processor.d.ts +8 -0
- package/src/services/asset-processing-service/processors/script/file-script.processor.js +76 -0
- package/src/services/asset-processing-service/processors/script/file-script.processor.ts +88 -0
- package/src/services/asset-processing-service/processors/script/node-module-script.processor.d.ts +7 -0
- package/src/services/asset-processing-service/processors/script/node-module-script.processor.js +74 -0
- package/src/services/asset-processing-service/processors/script/node-module-script.processor.ts +84 -0
- package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +5 -0
- package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +25 -0
- package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.ts +27 -0
- package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +9 -0
- package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +63 -0
- package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.ts +77 -0
- package/src/services/cache/cache.types.d.ts +107 -0
- package/src/services/cache/cache.types.js +0 -0
- package/src/services/cache/cache.types.ts +126 -0
- package/src/services/cache/index.d.ts +7 -0
- package/src/services/cache/index.js +7 -0
- package/src/services/cache/index.ts +18 -0
- package/src/services/cache/memory-cache-store.d.ts +42 -0
- package/src/services/cache/memory-cache-store.js +98 -0
- package/src/services/cache/memory-cache-store.ts +130 -0
- package/src/services/cache/page-cache-service.d.ts +70 -0
- package/src/services/cache/page-cache-service.js +152 -0
- package/src/services/cache/page-cache-service.ts +202 -0
- package/src/services/html-transformer.service.d.ts +50 -0
- package/src/services/html-transformer.service.js +163 -0
- package/src/services/html-transformer.service.ts +217 -0
- package/src/services/page-module-import.service.d.ts +37 -0
- package/src/services/page-module-import.service.js +88 -0
- package/src/services/page-module-import.service.ts +129 -0
- package/src/services/page-request-cache-coordinator.service.d.ts +75 -0
- package/src/services/page-request-cache-coordinator.service.js +107 -0
- package/src/services/page-request-cache-coordinator.service.ts +128 -0
- package/src/services/schema-validation-service.d.ts +122 -0
- package/src/services/schema-validation-service.js +101 -0
- package/src/services/schema-validation-service.ts +204 -0
- package/src/services/validation/standard-schema.types.d.ts +65 -0
- package/src/services/validation/standard-schema.types.js +0 -0
- package/src/services/validation/standard-schema.types.ts +68 -0
- package/src/static-site-generator/static-site-generator.d.ts +57 -0
- package/src/static-site-generator/static-site-generator.js +272 -0
- package/src/static-site-generator/static-site-generator.ts +359 -0
- package/src/utils/css.d.ts +1 -0
- package/src/utils/css.js +7 -0
- package/src/utils/css.ts +5 -0
- package/src/utils/deep-merge.d.ts +14 -0
- package/src/utils/deep-merge.js +32 -0
- package/src/utils/deep-merge.ts +47 -0
- package/src/utils/hash.d.ts +1 -0
- package/src/utils/hash.js +7 -0
- package/src/utils/hash.ts +5 -0
- package/src/utils/html.d.ts +1 -0
- package/src/utils/html.js +4 -0
- package/src/utils/html.ts +1 -0
- package/src/utils/invariant.d.ts +5 -0
- package/src/utils/invariant.js +11 -0
- package/src/utils/invariant.ts +15 -0
- package/src/utils/locals-utils.d.ts +15 -0
- package/src/utils/locals-utils.js +24 -0
- package/src/utils/locals-utils.ts +37 -0
- package/src/utils/parse-cli-args.d.ts +24 -0
- package/src/utils/parse-cli-args.js +47 -0
- package/src/utils/parse-cli-args.ts +83 -0
- package/src/utils/path-utils.module.d.ts +5 -0
- package/src/utils/path-utils.module.js +14 -0
- package/src/utils/path-utils.module.ts +14 -0
- package/src/utils/runtime.d.ts +11 -0
- package/src/utils/runtime.js +40 -0
- package/src/utils/runtime.ts +44 -0
- package/src/utils/server-utils.module.d.ts +19 -0
- package/src/utils/server-utils.module.js +56 -0
- package/src/utils/server-utils.module.ts +67 -0
- package/src/watchers/project-watcher.d.ts +120 -0
- package/src/watchers/project-watcher.js +238 -0
- package/src/watchers/project-watcher.test-helpers.d.ts +4 -0
- package/src/watchers/project-watcher.test-helpers.js +51 -0
- package/src/watchers/project-watcher.test-helpers.ts +40 -0
- package/src/watchers/project-watcher.ts +306 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileSystem } from "@ecopages/file-system";
|
|
3
|
+
import { HmrStrategy, HmrStrategyType } from "../hmr-strategy";
|
|
4
|
+
import { appLogger } from "../../global/app-logger";
|
|
5
|
+
import { defaultBuildAdapter } from "../../build/build-adapter.js";
|
|
6
|
+
class JsHmrStrategy extends HmrStrategy {
|
|
7
|
+
constructor(context) {
|
|
8
|
+
super();
|
|
9
|
+
this.context = context;
|
|
10
|
+
}
|
|
11
|
+
type = HmrStrategyType.SCRIPT;
|
|
12
|
+
/**
|
|
13
|
+
* Determines if the file is a JS/TS file that could affect registered entrypoints.
|
|
14
|
+
*
|
|
15
|
+
* Matches if:
|
|
16
|
+
* 1. There are registered entrypoints to rebuild
|
|
17
|
+
* 2. The changed file is a JS/TS file in the src directory
|
|
18
|
+
*
|
|
19
|
+
* @param filePath - Absolute path to the changed file
|
|
20
|
+
* @returns True if this file should trigger entrypoint rebuilds
|
|
21
|
+
*/
|
|
22
|
+
matches(filePath) {
|
|
23
|
+
const watchedFiles = this.context.getWatchedFiles();
|
|
24
|
+
const isJsTs = /\.(ts|tsx|js|jsx)$/.test(filePath);
|
|
25
|
+
const isInSrc = filePath.startsWith(this.context.getSrcDir());
|
|
26
|
+
if (watchedFiles.size === 0) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return isJsTs && isInSrc;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Processes a file change by rebuilding affected entrypoints.
|
|
33
|
+
*
|
|
34
|
+
* @param filePath - Absolute path to the changed file
|
|
35
|
+
*
|
|
36
|
+
* @remarks
|
|
37
|
+
* If runtime-specific dependency graph hooks are unavailable, this strategy
|
|
38
|
+
* falls back to rebuilding all watched entrypoints.
|
|
39
|
+
* @returns Action to broadcast update events
|
|
40
|
+
*/
|
|
41
|
+
async process(filePath) {
|
|
42
|
+
appLogger.debug(`[JsHmrStrategy] Processing ${filePath}`);
|
|
43
|
+
const watchedFiles = this.context.getWatchedFiles();
|
|
44
|
+
if (watchedFiles.size === 0) {
|
|
45
|
+
appLogger.debug(`[JsHmrStrategy] No watched files to rebuild`);
|
|
46
|
+
return { type: "none" };
|
|
47
|
+
}
|
|
48
|
+
const updates = [];
|
|
49
|
+
let reloadRequired = false;
|
|
50
|
+
const dependencyHits = this.context.getDependencyEntrypoints?.(filePath) ?? /* @__PURE__ */ new Set();
|
|
51
|
+
const hasDependencyHit = dependencyHits.size > 0;
|
|
52
|
+
const impactedEntrypoints = hasDependencyHit ? Array.from(dependencyHits).filter((entrypoint) => watchedFiles.has(entrypoint)) : Array.from(watchedFiles.keys());
|
|
53
|
+
if (!hasDependencyHit) {
|
|
54
|
+
appLogger.debug("[JsHmrStrategy] Dependency graph miss, rebuilding all watched entrypoints");
|
|
55
|
+
}
|
|
56
|
+
for (const entrypoint of impactedEntrypoints) {
|
|
57
|
+
const outputUrl = watchedFiles.get(entrypoint);
|
|
58
|
+
if (!outputUrl) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const result = await this.bundleEntrypoint(entrypoint, outputUrl);
|
|
62
|
+
if (result.success) {
|
|
63
|
+
if (result.dependencies && this.context.setEntrypointDependencies) {
|
|
64
|
+
this.context.setEntrypointDependencies(entrypoint, result.dependencies);
|
|
65
|
+
}
|
|
66
|
+
updates.push(outputUrl);
|
|
67
|
+
if (result.requiresReload) {
|
|
68
|
+
reloadRequired = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (updates.length > 0) {
|
|
73
|
+
if (reloadRequired) {
|
|
74
|
+
appLogger.debug(`[JsHmrStrategy] Full reload required (no HMR accept found)`);
|
|
75
|
+
return {
|
|
76
|
+
type: "broadcast",
|
|
77
|
+
events: [
|
|
78
|
+
{
|
|
79
|
+
type: "reload"
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
type: "broadcast",
|
|
86
|
+
events: updates.map((path2) => ({
|
|
87
|
+
type: "update",
|
|
88
|
+
path: path2,
|
|
89
|
+
timestamp: Date.now()
|
|
90
|
+
}))
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return { type: "none" };
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Bundles a single entrypoint and processes the output.
|
|
97
|
+
*
|
|
98
|
+
* @param entrypointPath - Absolute path to the source file
|
|
99
|
+
* @param outputUrl - URL path for the bundled file
|
|
100
|
+
* @returns True if bundling was successful
|
|
101
|
+
*/
|
|
102
|
+
async bundleEntrypoint(entrypointPath, outputUrl) {
|
|
103
|
+
try {
|
|
104
|
+
const srcDir = this.context.getSrcDir();
|
|
105
|
+
const relativePath = path.relative(srcDir, entrypointPath);
|
|
106
|
+
const relativePathJs = relativePath.replace(/\.(tsx?|jsx?)$/, ".js");
|
|
107
|
+
const outputPath = path.join(this.context.getDistDir(), relativePathJs);
|
|
108
|
+
const result = await defaultBuildAdapter.build({
|
|
109
|
+
entrypoints: [entrypointPath],
|
|
110
|
+
outdir: this.context.getDistDir(),
|
|
111
|
+
naming: relativePathJs,
|
|
112
|
+
...defaultBuildAdapter.getTranspileOptions("hmr-entrypoint"),
|
|
113
|
+
plugins: this.context.getPlugins(),
|
|
114
|
+
minify: false,
|
|
115
|
+
external: ["react", "react-dom"]
|
|
116
|
+
});
|
|
117
|
+
if (!result.success) {
|
|
118
|
+
appLogger.error(`[JsHmrStrategy] Failed to build ${entrypointPath}:`, result.logs);
|
|
119
|
+
return { success: false, requiresReload: false, dependencies: void 0 };
|
|
120
|
+
}
|
|
121
|
+
const dependencyGraph = result.dependencyGraph?.entrypoints?.[path.resolve(entrypointPath)] ?? [];
|
|
122
|
+
const output = await this.processOutput(outputPath, outputUrl);
|
|
123
|
+
return {
|
|
124
|
+
...output,
|
|
125
|
+
dependencies: dependencyGraph
|
|
126
|
+
};
|
|
127
|
+
} catch (error) {
|
|
128
|
+
appLogger.error(`[JsHmrStrategy] Error bundling ${entrypointPath}:`, error);
|
|
129
|
+
return { success: false, requiresReload: false, dependencies: void 0 };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Processes bundled output by replacing specifiers and injecting HMR code.
|
|
134
|
+
*
|
|
135
|
+
* @param filepath - Path to the bundled output file
|
|
136
|
+
* @param url - URL path for the bundled file
|
|
137
|
+
* @returns True if processing was successful and update should be broadcast
|
|
138
|
+
*/
|
|
139
|
+
async processOutput(filepath, url) {
|
|
140
|
+
try {
|
|
141
|
+
let code = await fileSystem.readFile(filepath);
|
|
142
|
+
if (code.includes("/* [ecopages] hmr */")) {
|
|
143
|
+
return { success: true, requiresReload: !code.includes("import.meta.hot.accept") };
|
|
144
|
+
}
|
|
145
|
+
code = this.replaceBareSpecifiers(code);
|
|
146
|
+
await fileSystem.writeAsync(filepath, code);
|
|
147
|
+
appLogger.debug(`[JsHmrStrategy] Processed ${url}`);
|
|
148
|
+
const hasHmrAccept = code.includes("import.meta.hot.accept");
|
|
149
|
+
return { success: true, requiresReload: !hasHmrAccept };
|
|
150
|
+
} catch (error) {
|
|
151
|
+
appLogger.error(`[JsHmrStrategy] Error processing output for ${url}:`, error);
|
|
152
|
+
return { success: false, requiresReload: false };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Replaces bare specifiers with vendor URLs.
|
|
157
|
+
*
|
|
158
|
+
* Handles both static imports and dynamic imports.
|
|
159
|
+
*
|
|
160
|
+
* @param code - The bundled code to transform
|
|
161
|
+
* @returns The transformed code with vendor URLs
|
|
162
|
+
*/
|
|
163
|
+
replaceBareSpecifiers(code) {
|
|
164
|
+
const specifierMap = this.context.getSpecifierMap();
|
|
165
|
+
if (specifierMap.size === 0) {
|
|
166
|
+
return code;
|
|
167
|
+
}
|
|
168
|
+
let result = code;
|
|
169
|
+
for (const [bareSpec, vendorUrl] of specifierMap.entries()) {
|
|
170
|
+
const escaped = bareSpec.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
171
|
+
result = result.replace(new RegExp(`from\\s*["']${escaped}["']`, "g"), `from "${vendorUrl}"`);
|
|
172
|
+
result = result.replace(new RegExp(`import\\(["']${escaped}["']\\)`, "g"), `import("${vendorUrl}")`);
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
JsHmrStrategy
|
|
179
|
+
};
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JavaScript HMR Strategy
|
|
3
|
+
*
|
|
4
|
+
* Handles hot module replacement for JavaScript and TypeScript entrypoints.
|
|
5
|
+
* Bundles files, replaces bare specifiers, and injects HMR boilerplate.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import { fileSystem } from '@ecopages/file-system';
|
|
12
|
+
import { HmrStrategy, HmrStrategyType, type HmrAction } from '../hmr-strategy';
|
|
13
|
+
import { appLogger } from '../../global/app-logger';
|
|
14
|
+
import { defaultBuildAdapter } from '../../build/build-adapter.ts';
|
|
15
|
+
import type { EcoBuildPlugin } from '../../build/build-types.ts';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Context interface providing access to HmrManager state.
|
|
19
|
+
* Required for JsHmrStrategy to access registered entrypoints and configuration.
|
|
20
|
+
*/
|
|
21
|
+
export interface JsHmrContext {
|
|
22
|
+
/**
|
|
23
|
+
* Map of registered entrypoints to their output URLs.
|
|
24
|
+
*/
|
|
25
|
+
getWatchedFiles(): Map<string, string>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Map of bare specifiers to vendor URLs for import resolution.
|
|
29
|
+
*/
|
|
30
|
+
getSpecifierMap(): Map<string, string>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Returns entrypoints impacted by a changed dependency path.
|
|
34
|
+
*
|
|
35
|
+
* @remarks
|
|
36
|
+
* This hook is currently provided by the Node HMR manager where dependency
|
|
37
|
+
* graph metadata is extracted from the Node/esbuild build adapter.
|
|
38
|
+
*/
|
|
39
|
+
getDependencyEntrypoints?(filePath: string): Set<string>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Stores latest dependency set for an entrypoint.
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* This hook is currently used only by the Node HMR manager to maintain a
|
|
46
|
+
* reverse invalidation index. Runtimes that do not provide it keep rebuild-all
|
|
47
|
+
* fallback semantics.
|
|
48
|
+
*/
|
|
49
|
+
setEntrypointDependencies?(entrypointPath: string, dependencies: string[]): void;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Directory where HMR bundles are written.
|
|
53
|
+
*/
|
|
54
|
+
getDistDir(): string;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Build plugins to use during bundling.
|
|
58
|
+
*/
|
|
59
|
+
getPlugins(): EcoBuildPlugin[];
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Absolute path to the source directory.
|
|
63
|
+
*/
|
|
64
|
+
getSrcDir(): string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Strategy for handling JavaScript/TypeScript file changes with hot reloading.
|
|
69
|
+
*
|
|
70
|
+
* This strategy rebuilds all registered entrypoints when any file changes,
|
|
71
|
+
* as we don't currently track dependencies. This is safe but inefficient.
|
|
72
|
+
*
|
|
73
|
+
* The processing steps are:
|
|
74
|
+
* 1. Check if any entrypoints are registered
|
|
75
|
+
* 2. Rebuild all entrypoints (the changed file could be a dependency)
|
|
76
|
+
* 3. Replace bare specifiers with vendor URLs
|
|
77
|
+
* 4. Inject generic HMR boilerplate
|
|
78
|
+
* 5. Broadcast update events for each rebuilt entrypoint
|
|
79
|
+
*
|
|
80
|
+
* @remarks
|
|
81
|
+
* Future enhancement: Track dependencies using Bun's transpiler API to only
|
|
82
|
+
* rebuild affected entrypoints instead of all of them.
|
|
83
|
+
*
|
|
84
|
+
* @see https://bun.sh/docs/runtime/transpiler
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const context = {
|
|
89
|
+
* getWatchedFiles: () => watchedFilesMap,
|
|
90
|
+
* getSpecifierMap: () => specifierMap,
|
|
91
|
+
* getDistDir: () => '/path/to/dist/_hmr',
|
|
92
|
+
* getPlugins: () => [],
|
|
93
|
+
* getSrcDir: () => '/path/to/src'
|
|
94
|
+
* };
|
|
95
|
+
* const strategy = new JsHmrStrategy(context);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export class JsHmrStrategy extends HmrStrategy {
|
|
99
|
+
readonly type = HmrStrategyType.SCRIPT;
|
|
100
|
+
|
|
101
|
+
constructor(private context: JsHmrContext) {
|
|
102
|
+
super();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Determines if the file is a JS/TS file that could affect registered entrypoints.
|
|
107
|
+
*
|
|
108
|
+
* Matches if:
|
|
109
|
+
* 1. There are registered entrypoints to rebuild
|
|
110
|
+
* 2. The changed file is a JS/TS file in the src directory
|
|
111
|
+
*
|
|
112
|
+
* @param filePath - Absolute path to the changed file
|
|
113
|
+
* @returns True if this file should trigger entrypoint rebuilds
|
|
114
|
+
*/
|
|
115
|
+
matches(filePath: string): boolean {
|
|
116
|
+
const watchedFiles = this.context.getWatchedFiles();
|
|
117
|
+
const isJsTs = /\.(ts|tsx|js|jsx)$/.test(filePath);
|
|
118
|
+
const isInSrc = filePath.startsWith(this.context.getSrcDir());
|
|
119
|
+
|
|
120
|
+
if (watchedFiles.size === 0) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return isJsTs && isInSrc;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Processes a file change by rebuilding affected entrypoints.
|
|
129
|
+
*
|
|
130
|
+
* @param filePath - Absolute path to the changed file
|
|
131
|
+
*
|
|
132
|
+
* @remarks
|
|
133
|
+
* If runtime-specific dependency graph hooks are unavailable, this strategy
|
|
134
|
+
* falls back to rebuilding all watched entrypoints.
|
|
135
|
+
* @returns Action to broadcast update events
|
|
136
|
+
*/
|
|
137
|
+
async process(filePath: string): Promise<HmrAction> {
|
|
138
|
+
appLogger.debug(`[JsHmrStrategy] Processing ${filePath}`);
|
|
139
|
+
const watchedFiles = this.context.getWatchedFiles();
|
|
140
|
+
|
|
141
|
+
if (watchedFiles.size === 0) {
|
|
142
|
+
appLogger.debug(`[JsHmrStrategy] No watched files to rebuild`);
|
|
143
|
+
return { type: 'none' };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const updates: string[] = [];
|
|
147
|
+
let reloadRequired = false;
|
|
148
|
+
const dependencyHits = this.context.getDependencyEntrypoints?.(filePath) ?? new Set<string>();
|
|
149
|
+
const hasDependencyHit = dependencyHits.size > 0;
|
|
150
|
+
const impactedEntrypoints = hasDependencyHit
|
|
151
|
+
? Array.from(dependencyHits).filter((entrypoint) => watchedFiles.has(entrypoint))
|
|
152
|
+
: Array.from(watchedFiles.keys());
|
|
153
|
+
|
|
154
|
+
if (!hasDependencyHit) {
|
|
155
|
+
appLogger.debug('[JsHmrStrategy] Dependency graph miss, rebuilding all watched entrypoints');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (const entrypoint of impactedEntrypoints) {
|
|
159
|
+
const outputUrl = watchedFiles.get(entrypoint);
|
|
160
|
+
if (!outputUrl) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const result = await this.bundleEntrypoint(entrypoint, outputUrl);
|
|
165
|
+
if (result.success) {
|
|
166
|
+
if (result.dependencies && this.context.setEntrypointDependencies) {
|
|
167
|
+
this.context.setEntrypointDependencies(entrypoint, result.dependencies);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
updates.push(outputUrl);
|
|
171
|
+
if (result.requiresReload) {
|
|
172
|
+
reloadRequired = true;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (updates.length > 0) {
|
|
178
|
+
if (reloadRequired) {
|
|
179
|
+
appLogger.debug(`[JsHmrStrategy] Full reload required (no HMR accept found)`);
|
|
180
|
+
return {
|
|
181
|
+
type: 'broadcast',
|
|
182
|
+
events: [
|
|
183
|
+
{
|
|
184
|
+
type: 'reload',
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
type: 'broadcast',
|
|
192
|
+
events: updates.map((path) => ({
|
|
193
|
+
type: 'update',
|
|
194
|
+
path,
|
|
195
|
+
timestamp: Date.now(),
|
|
196
|
+
})),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return { type: 'none' };
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Bundles a single entrypoint and processes the output.
|
|
205
|
+
*
|
|
206
|
+
* @param entrypointPath - Absolute path to the source file
|
|
207
|
+
* @param outputUrl - URL path for the bundled file
|
|
208
|
+
* @returns True if bundling was successful
|
|
209
|
+
*/
|
|
210
|
+
private async bundleEntrypoint(
|
|
211
|
+
entrypointPath: string,
|
|
212
|
+
outputUrl: string,
|
|
213
|
+
): Promise<{ success: boolean; requiresReload: boolean; dependencies?: string[] }> {
|
|
214
|
+
try {
|
|
215
|
+
const srcDir = this.context.getSrcDir();
|
|
216
|
+
const relativePath = path.relative(srcDir, entrypointPath);
|
|
217
|
+
const relativePathJs = relativePath.replace(/\.(tsx?|jsx?)$/, '.js');
|
|
218
|
+
const outputPath = path.join(this.context.getDistDir(), relativePathJs);
|
|
219
|
+
|
|
220
|
+
const result = await defaultBuildAdapter.build({
|
|
221
|
+
entrypoints: [entrypointPath],
|
|
222
|
+
outdir: this.context.getDistDir(),
|
|
223
|
+
naming: relativePathJs,
|
|
224
|
+
...defaultBuildAdapter.getTranspileOptions('hmr-entrypoint'),
|
|
225
|
+
plugins: this.context.getPlugins(),
|
|
226
|
+
minify: false,
|
|
227
|
+
external: ['react', 'react-dom'],
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
if (!result.success) {
|
|
231
|
+
appLogger.error(`[JsHmrStrategy] Failed to build ${entrypointPath}:`, result.logs);
|
|
232
|
+
return { success: false, requiresReload: false, dependencies: undefined };
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const dependencyGraph = result.dependencyGraph?.entrypoints?.[path.resolve(entrypointPath)] ?? [];
|
|
236
|
+
const output = await this.processOutput(outputPath, outputUrl);
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
...output,
|
|
240
|
+
dependencies: dependencyGraph,
|
|
241
|
+
};
|
|
242
|
+
} catch (error) {
|
|
243
|
+
appLogger.error(`[JsHmrStrategy] Error bundling ${entrypointPath}:`, error as Error);
|
|
244
|
+
return { success: false, requiresReload: false, dependencies: undefined };
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Processes bundled output by replacing specifiers and injecting HMR code.
|
|
250
|
+
*
|
|
251
|
+
* @param filepath - Path to the bundled output file
|
|
252
|
+
* @param url - URL path for the bundled file
|
|
253
|
+
* @returns True if processing was successful and update should be broadcast
|
|
254
|
+
*/
|
|
255
|
+
private async processOutput(filepath: string, url: string): Promise<{ success: boolean; requiresReload: boolean }> {
|
|
256
|
+
try {
|
|
257
|
+
let code = await fileSystem.readFile(filepath);
|
|
258
|
+
|
|
259
|
+
if (code.includes('/* [ecopages] hmr */')) {
|
|
260
|
+
/**
|
|
261
|
+
* Already processed, assume it supports HMR if it has the header (legacy safety)
|
|
262
|
+
* or check specifically for accept
|
|
263
|
+
*/
|
|
264
|
+
return { success: true, requiresReload: !code.includes('import.meta.hot.accept') };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
code = this.replaceBareSpecifiers(code);
|
|
268
|
+
await fileSystem.writeAsync(filepath, code);
|
|
269
|
+
|
|
270
|
+
appLogger.debug(`[JsHmrStrategy] Processed ${url}`);
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Implicit HMR check: if the code explicitly accepts HMR, we broadcast update.
|
|
274
|
+
* Otherwise, we must reload the page to ensure fresh execution (e.g. for Custom Elements or side effects).
|
|
275
|
+
*/
|
|
276
|
+
const hasHmrAccept = code.includes('import.meta.hot.accept');
|
|
277
|
+
return { success: true, requiresReload: !hasHmrAccept };
|
|
278
|
+
} catch (error) {
|
|
279
|
+
appLogger.error(`[JsHmrStrategy] Error processing output for ${url}:`, error as Error);
|
|
280
|
+
return { success: false, requiresReload: false };
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Replaces bare specifiers with vendor URLs.
|
|
286
|
+
*
|
|
287
|
+
* Handles both static imports and dynamic imports.
|
|
288
|
+
*
|
|
289
|
+
* @param code - The bundled code to transform
|
|
290
|
+
* @returns The transformed code with vendor URLs
|
|
291
|
+
*/
|
|
292
|
+
private replaceBareSpecifiers(code: string): string {
|
|
293
|
+
const specifierMap = this.context.getSpecifierMap();
|
|
294
|
+
|
|
295
|
+
if (specifierMap.size === 0) {
|
|
296
|
+
return code;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
let result = code;
|
|
300
|
+
for (const [bareSpec, vendorUrl] of specifierMap.entries()) {
|
|
301
|
+
const escaped = bareSpec.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
302
|
+
result = result.replace(new RegExp(`from\\s*["']${escaped}["']`, 'g'), `from "${vendorUrl}"`);
|
|
303
|
+
result = result.replace(new RegExp(`import\\(["']${escaped}["']\\)`, 'g'), `import("${vendorUrl}")`);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return result;
|
|
307
|
+
}
|
|
308
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type * from './public-types.js';
|
|
2
|
+
export type * from './eco/eco.types.js';
|
|
3
|
+
export { eco } from './eco/eco.js';
|
|
4
|
+
export { EcopagesApp, createApp, type EcopagesAppOptions } from './create-app.js';
|
|
5
|
+
export { defineApiHandler, defineGroupHandler, type GroupHandler } from './define-api-handler.js';
|
package/src/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { eco } from "./eco/eco.js";
|
|
2
|
+
import { EcopagesApp, createApp } from "./create-app.js";
|
|
3
|
+
import { defineApiHandler, defineGroupHandler } from "./define-api-handler.js";
|
|
4
|
+
export {
|
|
5
|
+
EcopagesApp,
|
|
6
|
+
createApp,
|
|
7
|
+
defineApiHandler,
|
|
8
|
+
defineGroupHandler,
|
|
9
|
+
eco
|
|
10
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type * from './public-types.ts';
|
|
2
|
+
export type * from './eco/eco.types.ts';
|
|
3
|
+
export { eco } from './eco/eco.ts';
|
|
4
|
+
export { EcopagesApp, createApp, type EcopagesAppOptions } from './create-app.ts';
|
|
5
|
+
export { defineApiHandler, defineGroupHandler, type GroupHandler } from './define-api-handler.ts';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module contains the ghtml renderer
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
import type { EcoComponent, EcoPagesElement, IntegrationRendererRenderOptions, RouteRendererBody } from '../../public-types.js';
|
|
6
|
+
import { IntegrationRenderer, type RenderToResponseContext } from '../../route-renderer/integration-renderer.js';
|
|
7
|
+
/**
|
|
8
|
+
* A renderer for the ghtml integration.
|
|
9
|
+
* It renders a page using the HtmlTemplate and Page components.
|
|
10
|
+
*/
|
|
11
|
+
export declare class GhtmlRenderer extends IntegrationRenderer<EcoPagesElement> {
|
|
12
|
+
name: string;
|
|
13
|
+
render({ params, query, props, locals, pageLocals, metadata, Page, Layout, HtmlTemplate, }: IntegrationRendererRenderOptions): Promise<RouteRendererBody>;
|
|
14
|
+
renderToResponse<P = Record<string, unknown>>(view: EcoComponent<P>, props: P, ctx: RenderToResponseContext): Promise<Response>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { IntegrationRenderer } from "../../route-renderer/integration-renderer.js";
|
|
2
|
+
import { GHTML_PLUGIN_NAME } from "./ghtml.plugin.js";
|
|
3
|
+
class GhtmlRenderer extends IntegrationRenderer {
|
|
4
|
+
name = GHTML_PLUGIN_NAME;
|
|
5
|
+
async render({
|
|
6
|
+
params,
|
|
7
|
+
query,
|
|
8
|
+
props,
|
|
9
|
+
locals,
|
|
10
|
+
pageLocals,
|
|
11
|
+
metadata,
|
|
12
|
+
Page,
|
|
13
|
+
Layout,
|
|
14
|
+
HtmlTemplate
|
|
15
|
+
}) {
|
|
16
|
+
try {
|
|
17
|
+
const pageContent = await Page({ params, query, ...props, locals: pageLocals });
|
|
18
|
+
const children = Layout && typeof Layout === "function" ? await Layout({ children: pageContent, locals }) : pageContent;
|
|
19
|
+
const body = await HtmlTemplate({
|
|
20
|
+
metadata,
|
|
21
|
+
children,
|
|
22
|
+
pageProps: props || {}
|
|
23
|
+
});
|
|
24
|
+
return this.DOC_TYPE + body;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
throw this.createRenderError("Error rendering page", error);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async renderToResponse(view, props, ctx) {
|
|
30
|
+
try {
|
|
31
|
+
const Layout = view.config?.layout;
|
|
32
|
+
const viewFn = view;
|
|
33
|
+
const pageContent = await viewFn(props);
|
|
34
|
+
let body;
|
|
35
|
+
if (ctx.partial) {
|
|
36
|
+
body = pageContent;
|
|
37
|
+
} else {
|
|
38
|
+
const children = Layout ? await Layout({ children: pageContent }) : pageContent;
|
|
39
|
+
const HtmlTemplate = await this.getHtmlTemplate();
|
|
40
|
+
const metadata = view.metadata ? await view.metadata({
|
|
41
|
+
params: {},
|
|
42
|
+
query: {},
|
|
43
|
+
props,
|
|
44
|
+
appConfig: this.appConfig
|
|
45
|
+
}) : this.appConfig.defaultMetadata;
|
|
46
|
+
body = this.DOC_TYPE + await HtmlTemplate({
|
|
47
|
+
metadata,
|
|
48
|
+
children,
|
|
49
|
+
pageProps: props
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return this.createHtmlResponse(body, ctx);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
throw this.createRenderError("Error rendering view", error);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
GhtmlRenderer
|
|
60
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module contains the ghtml renderer
|
|
3
|
+
* @module
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
EcoComponent,
|
|
8
|
+
EcoPagesElement,
|
|
9
|
+
IntegrationRendererRenderOptions,
|
|
10
|
+
PageMetadataProps,
|
|
11
|
+
RouteRendererBody,
|
|
12
|
+
} from '../../public-types.ts';
|
|
13
|
+
import { IntegrationRenderer, type RenderToResponseContext } from '../../route-renderer/integration-renderer.ts';
|
|
14
|
+
import { GHTML_PLUGIN_NAME } from './ghtml.plugin.ts';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A renderer for the ghtml integration.
|
|
18
|
+
* It renders a page using the HtmlTemplate and Page components.
|
|
19
|
+
*/
|
|
20
|
+
export class GhtmlRenderer extends IntegrationRenderer<EcoPagesElement> {
|
|
21
|
+
name = GHTML_PLUGIN_NAME;
|
|
22
|
+
|
|
23
|
+
async render({
|
|
24
|
+
params,
|
|
25
|
+
query,
|
|
26
|
+
props,
|
|
27
|
+
locals,
|
|
28
|
+
pageLocals,
|
|
29
|
+
metadata,
|
|
30
|
+
Page,
|
|
31
|
+
Layout,
|
|
32
|
+
HtmlTemplate,
|
|
33
|
+
}: IntegrationRendererRenderOptions): Promise<RouteRendererBody> {
|
|
34
|
+
try {
|
|
35
|
+
const pageContent = await Page({ params, query, ...props, locals: pageLocals });
|
|
36
|
+
const children =
|
|
37
|
+
Layout && typeof Layout === 'function' ? await Layout({ children: pageContent, locals }) : pageContent;
|
|
38
|
+
const body = await HtmlTemplate({
|
|
39
|
+
metadata,
|
|
40
|
+
children,
|
|
41
|
+
pageProps: props || {},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return this.DOC_TYPE + body;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
throw this.createRenderError('Error rendering page', error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async renderToResponse<P = Record<string, unknown>>(
|
|
51
|
+
view: EcoComponent<P>,
|
|
52
|
+
props: P,
|
|
53
|
+
ctx: RenderToResponseContext,
|
|
54
|
+
): Promise<Response> {
|
|
55
|
+
try {
|
|
56
|
+
const Layout = view.config?.layout as
|
|
57
|
+
| ((props: { children: EcoPagesElement } & Record<string, unknown>) => Promise<EcoPagesElement>)
|
|
58
|
+
| undefined;
|
|
59
|
+
|
|
60
|
+
const viewFn = view as (props: P) => Promise<EcoPagesElement>;
|
|
61
|
+
const pageContent = await viewFn(props);
|
|
62
|
+
|
|
63
|
+
let body: string;
|
|
64
|
+
if (ctx.partial) {
|
|
65
|
+
body = pageContent as string;
|
|
66
|
+
} else {
|
|
67
|
+
const children = Layout ? await Layout({ children: pageContent }) : pageContent;
|
|
68
|
+
|
|
69
|
+
const HtmlTemplate = await this.getHtmlTemplate();
|
|
70
|
+
const metadata: PageMetadataProps = view.metadata
|
|
71
|
+
? await view.metadata({
|
|
72
|
+
params: {},
|
|
73
|
+
query: {},
|
|
74
|
+
props: props as Record<string, unknown>,
|
|
75
|
+
appConfig: this.appConfig,
|
|
76
|
+
})
|
|
77
|
+
: this.appConfig.defaultMetadata;
|
|
78
|
+
|
|
79
|
+
body =
|
|
80
|
+
this.DOC_TYPE +
|
|
81
|
+
(await HtmlTemplate({
|
|
82
|
+
metadata,
|
|
83
|
+
children: children as EcoPagesElement,
|
|
84
|
+
pageProps: props as Record<string, unknown>,
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return this.createHtmlResponse(body, ctx);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
throw this.createRenderError('Error rendering view', error);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|