@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,50 @@
|
|
|
1
|
+
class HttpError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
details;
|
|
4
|
+
constructor(status, message, details) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "HttpError";
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.details = details;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Serialize error to JSON for API responses.
|
|
12
|
+
*/
|
|
13
|
+
toJSON() {
|
|
14
|
+
const json = {
|
|
15
|
+
error: this.message,
|
|
16
|
+
status: this.status
|
|
17
|
+
};
|
|
18
|
+
if (this.details) {
|
|
19
|
+
json.details = this.details;
|
|
20
|
+
}
|
|
21
|
+
return json;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create a Response object from this error.
|
|
25
|
+
*/
|
|
26
|
+
toResponse() {
|
|
27
|
+
return Response.json(this.toJSON(), { status: this.status });
|
|
28
|
+
}
|
|
29
|
+
static BadRequest(message = "Bad Request", details) {
|
|
30
|
+
return new HttpError(400, message, details);
|
|
31
|
+
}
|
|
32
|
+
static Unauthorized(message = "Unauthorized") {
|
|
33
|
+
return new HttpError(401, message);
|
|
34
|
+
}
|
|
35
|
+
static Forbidden(message = "Forbidden") {
|
|
36
|
+
return new HttpError(403, message);
|
|
37
|
+
}
|
|
38
|
+
static NotFound(message = "Not Found") {
|
|
39
|
+
return new HttpError(404, message);
|
|
40
|
+
}
|
|
41
|
+
static Conflict(message = "Conflict", details) {
|
|
42
|
+
return new HttpError(409, message, details);
|
|
43
|
+
}
|
|
44
|
+
static InternalServerError(message = "Internal Server Error") {
|
|
45
|
+
return new HttpError(500, message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
HttpError
|
|
50
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export interface HttpErrorDetails {
|
|
2
|
+
[key: string]: unknown;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface HttpErrorJson {
|
|
6
|
+
error: string;
|
|
7
|
+
status: number;
|
|
8
|
+
details?: HttpErrorDetails;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* HTTP error class for structured error handling in route handlers.
|
|
13
|
+
* Provides static factory methods for common HTTP error responses.
|
|
14
|
+
*/
|
|
15
|
+
export class HttpError extends Error {
|
|
16
|
+
readonly status: number;
|
|
17
|
+
readonly details?: HttpErrorDetails;
|
|
18
|
+
|
|
19
|
+
constructor(status: number, message: string, details?: HttpErrorDetails) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = 'HttpError';
|
|
22
|
+
this.status = status;
|
|
23
|
+
this.details = details;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Serialize error to JSON for API responses.
|
|
28
|
+
*/
|
|
29
|
+
toJSON(): HttpErrorJson {
|
|
30
|
+
const json: HttpErrorJson = {
|
|
31
|
+
error: this.message,
|
|
32
|
+
status: this.status,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (this.details) {
|
|
36
|
+
json.details = this.details;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return json;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create a Response object from this error.
|
|
44
|
+
*/
|
|
45
|
+
toResponse(): Response {
|
|
46
|
+
return Response.json(this.toJSON(), { status: this.status });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
static BadRequest(message = 'Bad Request', details?: HttpErrorDetails): HttpError {
|
|
50
|
+
return new HttpError(400, message, details);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static Unauthorized(message = 'Unauthorized'): HttpError {
|
|
54
|
+
return new HttpError(401, message);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static Forbidden(message = 'Forbidden'): HttpError {
|
|
58
|
+
return new HttpError(403, message);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static NotFound(message = 'Not Found'): HttpError {
|
|
62
|
+
return new HttpError(404, message);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static Conflict(message = 'Conflict', details?: HttpErrorDetails): HttpError {
|
|
66
|
+
return new HttpError(409, message, details);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static InternalServerError(message = 'Internal Server Error'): HttpError {
|
|
70
|
+
return new HttpError(500, message);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ecopages HMR Runtime
|
|
3
|
+
* Injected into the browser to handle Hot Module Replacement updates.
|
|
4
|
+
*/
|
|
5
|
+
interface HMRPayload {
|
|
6
|
+
type: 'reload' | 'error' | 'update' | 'css-update' | 'layout-update';
|
|
7
|
+
path?: string;
|
|
8
|
+
message?: string;
|
|
9
|
+
timestamp?: number;
|
|
10
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
(function() {
|
|
2
|
+
const WS_URL = "ws://" + location.host + "/_hmr";
|
|
3
|
+
let socket;
|
|
4
|
+
let reconnectAttempts = 0;
|
|
5
|
+
function connect() {
|
|
6
|
+
socket = new WebSocket(WS_URL);
|
|
7
|
+
socket.addEventListener("open", () => {
|
|
8
|
+
console.log("[ecopages] HMR Connected");
|
|
9
|
+
reconnectAttempts = 0;
|
|
10
|
+
});
|
|
11
|
+
socket.addEventListener("message", async (event) => {
|
|
12
|
+
try {
|
|
13
|
+
const payload = JSON.parse(event.data);
|
|
14
|
+
handleMessage(payload);
|
|
15
|
+
} catch (e) {
|
|
16
|
+
console.error("[ecopages] Invalid HMR message:", e);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
socket.addEventListener("close", () => {
|
|
20
|
+
if (reconnectAttempts < 10) {
|
|
21
|
+
setTimeout(connect, 1e3 * 2 ** reconnectAttempts);
|
|
22
|
+
reconnectAttempts++;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async function handleMessage(payload) {
|
|
27
|
+
switch (payload.type) {
|
|
28
|
+
case "reload":
|
|
29
|
+
location.reload();
|
|
30
|
+
break;
|
|
31
|
+
case "layout-update": {
|
|
32
|
+
const reloadFn = window.__ecopages_reload_current_page__;
|
|
33
|
+
if (typeof reloadFn === "function") {
|
|
34
|
+
await reloadFn({ clearCache: true });
|
|
35
|
+
} else {
|
|
36
|
+
location.reload();
|
|
37
|
+
}
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
case "error":
|
|
41
|
+
console.error("[ecopages] HMR Error:", payload.message);
|
|
42
|
+
break;
|
|
43
|
+
case "update":
|
|
44
|
+
if (payload.path) {
|
|
45
|
+
await applyUpdate(payload.path, payload.timestamp);
|
|
46
|
+
}
|
|
47
|
+
break;
|
|
48
|
+
case "css-update":
|
|
49
|
+
if (payload.path) {
|
|
50
|
+
refreshStylesheet(payload.path);
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function applyUpdate(path, timestamp) {
|
|
56
|
+
try {
|
|
57
|
+
const url = path + "?t=" + (timestamp || Date.now());
|
|
58
|
+
const handlers = window.__ecopages_hmr_handlers__;
|
|
59
|
+
if (handlers?.[path]) {
|
|
60
|
+
await handlers[path](url);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
await import(url);
|
|
64
|
+
const reloadFn = window.__ecopages_reload_current_page__;
|
|
65
|
+
if (typeof reloadFn === "function") {
|
|
66
|
+
await reloadFn({ clearCache: false });
|
|
67
|
+
}
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.error("[ecopages] Failed to apply HMR update:", e);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function refreshStylesheet(path) {
|
|
73
|
+
const filename = path.split("/").pop() || "";
|
|
74
|
+
const links = document.querySelectorAll('link[rel="stylesheet"]');
|
|
75
|
+
links.forEach((link) => {
|
|
76
|
+
const href = link.href;
|
|
77
|
+
if (href.includes(filename) || href.includes(path.replace(/^.*\/src\//, "/assets/"))) {
|
|
78
|
+
const url = new URL(href, location.origin);
|
|
79
|
+
url.searchParams.set("t", Date.now().toString());
|
|
80
|
+
link.href = url.toString();
|
|
81
|
+
console.log("[ecopages] CSS updated:", filename);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
connect();
|
|
86
|
+
})();
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ecopages HMR Runtime
|
|
3
|
+
* Injected into the browser to handle Hot Module Replacement updates.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
interface HMRPayload {
|
|
7
|
+
type: 'reload' | 'error' | 'update' | 'css-update' | 'layout-update';
|
|
8
|
+
path?: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
timestamp?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
(function () {
|
|
14
|
+
const WS_URL = 'ws://' + location.host + '/_hmr';
|
|
15
|
+
let socket: WebSocket;
|
|
16
|
+
let reconnectAttempts = 0;
|
|
17
|
+
|
|
18
|
+
function connect() {
|
|
19
|
+
socket = new WebSocket(WS_URL);
|
|
20
|
+
|
|
21
|
+
socket.addEventListener('open', () => {
|
|
22
|
+
console.log('[ecopages] HMR Connected');
|
|
23
|
+
reconnectAttempts = 0;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
socket.addEventListener('message', async (event) => {
|
|
27
|
+
try {
|
|
28
|
+
const payload: HMRPayload = JSON.parse(event.data);
|
|
29
|
+
handleMessage(payload);
|
|
30
|
+
} catch (e) {
|
|
31
|
+
console.error('[ecopages] Invalid HMR message:', e);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
socket.addEventListener('close', () => {
|
|
36
|
+
if (reconnectAttempts < 10) {
|
|
37
|
+
setTimeout(connect, 1000 * 2 ** reconnectAttempts);
|
|
38
|
+
reconnectAttempts++;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function handleMessage(payload: HMRPayload) {
|
|
44
|
+
switch (payload.type) {
|
|
45
|
+
case 'reload':
|
|
46
|
+
location.reload();
|
|
47
|
+
break;
|
|
48
|
+
case 'layout-update': {
|
|
49
|
+
const reloadFn = window.__ecopages_reload_current_page__;
|
|
50
|
+
if (typeof reloadFn === 'function') {
|
|
51
|
+
await reloadFn({ clearCache: true });
|
|
52
|
+
} else {
|
|
53
|
+
location.reload();
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case 'error':
|
|
58
|
+
console.error('[ecopages] HMR Error:', payload.message);
|
|
59
|
+
break;
|
|
60
|
+
case 'update':
|
|
61
|
+
if (payload.path) {
|
|
62
|
+
await applyUpdate(payload.path, payload.timestamp);
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
case 'css-update':
|
|
66
|
+
if (payload.path) {
|
|
67
|
+
refreshStylesheet(payload.path);
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Applies a module update by calling registered HMR handlers or re-importing the module.
|
|
75
|
+
* @param path - The module path to update
|
|
76
|
+
* @param timestamp - Optional timestamp for cache busting
|
|
77
|
+
*/
|
|
78
|
+
async function applyUpdate(path: string, timestamp?: number) {
|
|
79
|
+
try {
|
|
80
|
+
const url = path + '?t=' + (timestamp || Date.now());
|
|
81
|
+
const handlers = window.__ecopages_hmr_handlers__;
|
|
82
|
+
|
|
83
|
+
if (handlers?.[path]) {
|
|
84
|
+
await handlers[path](url);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await import(url);
|
|
89
|
+
|
|
90
|
+
// If we're inside the EcoRouter, we need to trigger a router navigation to render the new component.
|
|
91
|
+
// Passing clearCache: false preserves the persisted layout cache.
|
|
92
|
+
const reloadFn = window.__ecopages_reload_current_page__;
|
|
93
|
+
if (typeof reloadFn === 'function') {
|
|
94
|
+
await reloadFn({ clearCache: false });
|
|
95
|
+
}
|
|
96
|
+
} catch (e) {
|
|
97
|
+
console.error('[ecopages] Failed to apply HMR update:', e);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Hot-reload CSS by updating stylesheet link href with cache-busting query param.
|
|
103
|
+
* This causes the browser to re-fetch the stylesheet without a full page reload.
|
|
104
|
+
*/
|
|
105
|
+
function refreshStylesheet(path: string) {
|
|
106
|
+
const filename = path.split('/').pop() || '';
|
|
107
|
+
const links = document.querySelectorAll('link[rel="stylesheet"]');
|
|
108
|
+
|
|
109
|
+
links.forEach((link) => {
|
|
110
|
+
const href = (link as HTMLLinkElement).href;
|
|
111
|
+
if (href.includes(filename) || href.includes(path.replace(/^.*\/src\//, '/assets/'))) {
|
|
112
|
+
const url = new URL(href, location.origin);
|
|
113
|
+
url.searchParams.set('t', Date.now().toString());
|
|
114
|
+
(link as HTMLLinkElement).href = url.toString();
|
|
115
|
+
console.log('[ecopages] CSS updated:', filename);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
connect();
|
|
121
|
+
})();
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { ClientBridgeEvent } from '../public-types';
|
|
2
|
+
/**
|
|
3
|
+
* HMR Strategy Pattern
|
|
4
|
+
*
|
|
5
|
+
* This module defines the base classes and types for Hot Module Replacement strategies.
|
|
6
|
+
* Each strategy handles a specific type of file change and determines how to process it.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* class CustomHmrStrategy extends HmrStrategy {
|
|
12
|
+
* readonly type = HmrStrategyType.INTEGRATION;
|
|
13
|
+
*
|
|
14
|
+
* matches(filePath: string): boolean {
|
|
15
|
+
* return filePath.endsWith('.custom');
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* async process(filePath: string): Promise<HmrAction> {
|
|
19
|
+
* return {
|
|
20
|
+
* type: 'broadcast',
|
|
21
|
+
* events: [{ type: 'update', path: filePath, timestamp: Date.now() }]
|
|
22
|
+
* };
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
|
|
26
|
+
* Defines the category of an HMR strategy, which determines its execution priority.
|
|
27
|
+
* Strategies are evaluated in descending order: INTEGRATION → ASSET → SCRIPT → FALLBACK.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* The numeric values represent base priorities. Strategies can fine-tune their priority
|
|
31
|
+
* using the `priorityOffset` property.
|
|
32
|
+
*/
|
|
33
|
+
export declare enum HmrStrategyType {
|
|
34
|
+
/**
|
|
35
|
+
* Integration-specific strategies (React, Lit, etc.)
|
|
36
|
+
* Highest priority to allow framework-specific HMR handling.
|
|
37
|
+
*/
|
|
38
|
+
INTEGRATION = 100,
|
|
39
|
+
/**
|
|
40
|
+
* Asset processing strategies (CSS, images, etc.)
|
|
41
|
+
* High priority for specialized asset handling.
|
|
42
|
+
*/
|
|
43
|
+
ASSET = 50,
|
|
44
|
+
/**
|
|
45
|
+
* Generic script bundling strategies (JS/TS)
|
|
46
|
+
* Medium priority for standard script processing.
|
|
47
|
+
*/
|
|
48
|
+
SCRIPT = 25,
|
|
49
|
+
/**
|
|
50
|
+
* Fallback strategy for unhandled file types.
|
|
51
|
+
* Lowest priority, triggers full page reload.
|
|
52
|
+
*/
|
|
53
|
+
FALLBACK = 0
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Represents an action to be taken after processing a file change.
|
|
57
|
+
*/
|
|
58
|
+
export interface HmrAction {
|
|
59
|
+
/**
|
|
60
|
+
* Whether to broadcast an HMR event to connected clients.
|
|
61
|
+
*/
|
|
62
|
+
type: 'broadcast' | 'none';
|
|
63
|
+
/**
|
|
64
|
+
* The HMR events to broadcast, if type is 'broadcast'.
|
|
65
|
+
* capable of broadcasting multiple events at once.
|
|
66
|
+
*/
|
|
67
|
+
events?: ClientBridgeEvent[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Base class for HMR strategies.
|
|
71
|
+
*
|
|
72
|
+
* Each strategy handles a specific type of file change and determines how to process it.
|
|
73
|
+
* Strategies are selected based on their priority (higher values are evaluated first) and
|
|
74
|
+
* whether they match the changed file path.
|
|
75
|
+
*
|
|
76
|
+
* @remarks
|
|
77
|
+
* Strategies should be stateless and idempotent. The same file change should always
|
|
78
|
+
* produce the same result when processed by the same strategy.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* class MyAssetStrategy extends HmrStrategy {
|
|
83
|
+
* readonly type = HmrStrategyType.ASSET;
|
|
84
|
+
* readonly priorityOffset = 5;
|
|
85
|
+
*
|
|
86
|
+
* matches(filePath: string): boolean {
|
|
87
|
+
* return /\.(png|jpg|svg)$/.test(filePath);
|
|
88
|
+
* }
|
|
89
|
+
*
|
|
90
|
+
* async process(filePath: string): Promise<HmrAction> {
|
|
91
|
+
* await this.optimizeImage(filePath);
|
|
92
|
+
* return {
|
|
93
|
+
* type: 'broadcast',
|
|
94
|
+
* events: [{ type: 'update', path: filePath, timestamp: Date.now() }]
|
|
95
|
+
* };
|
|
96
|
+
* }
|
|
97
|
+
* }
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare abstract class HmrStrategy {
|
|
101
|
+
/**
|
|
102
|
+
* The category of this strategy, determining its base priority.
|
|
103
|
+
*/
|
|
104
|
+
abstract readonly type: HmrStrategyType;
|
|
105
|
+
/**
|
|
106
|
+
* Optional offset to fine-tune priority within the same category.
|
|
107
|
+
* Useful when multiple strategies share the same type.
|
|
108
|
+
*
|
|
109
|
+
* @defaultValue 0
|
|
110
|
+
*/
|
|
111
|
+
readonly priorityOffset: number;
|
|
112
|
+
/**
|
|
113
|
+
* Computed priority for strategy selection.
|
|
114
|
+
* Higher values are evaluated first.
|
|
115
|
+
*
|
|
116
|
+
* @returns The sum of the strategy type and priority offset
|
|
117
|
+
*/
|
|
118
|
+
get priority(): number;
|
|
119
|
+
/**
|
|
120
|
+
* Determines if this strategy can handle the given file path.
|
|
121
|
+
*
|
|
122
|
+
* @param filePath - Absolute path to the changed file
|
|
123
|
+
* @returns True if this strategy should process the file
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* matches(filePath: string): boolean {
|
|
128
|
+
* return filePath.endsWith('.css');
|
|
129
|
+
* }
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
abstract matches(filePath: string): boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Processes a file change and returns the action to take.
|
|
135
|
+
*
|
|
136
|
+
* This method may perform side effects such as:
|
|
137
|
+
* - Rebuilding files
|
|
138
|
+
* - Writing to disk
|
|
139
|
+
* - Transforming code
|
|
140
|
+
* - Updating caches
|
|
141
|
+
*
|
|
142
|
+
* @param filePath - Absolute path to the changed file
|
|
143
|
+
* @returns Action to take (broadcast event or none)
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* async process(filePath: string): Promise<HmrAction> {
|
|
148
|
+
* const processed = await this.transform(filePath);
|
|
149
|
+
* await Bun.write(outputPath, processed);
|
|
150
|
+
*
|
|
151
|
+
* return {
|
|
152
|
+
* type: 'broadcast',
|
|
153
|
+
* events: [{ type: 'update', path: outputPath, timestamp: Date.now() }]
|
|
154
|
+
* };
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
abstract process(filePath: string): Promise<HmrAction>;
|
|
159
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
var HmrStrategyType = /* @__PURE__ */ ((HmrStrategyType2) => {
|
|
2
|
+
HmrStrategyType2[HmrStrategyType2["INTEGRATION"] = 100] = "INTEGRATION";
|
|
3
|
+
HmrStrategyType2[HmrStrategyType2["ASSET"] = 50] = "ASSET";
|
|
4
|
+
HmrStrategyType2[HmrStrategyType2["SCRIPT"] = 25] = "SCRIPT";
|
|
5
|
+
HmrStrategyType2[HmrStrategyType2["FALLBACK"] = 0] = "FALLBACK";
|
|
6
|
+
return HmrStrategyType2;
|
|
7
|
+
})(HmrStrategyType || {});
|
|
8
|
+
class HmrStrategy {
|
|
9
|
+
/**
|
|
10
|
+
* Optional offset to fine-tune priority within the same category.
|
|
11
|
+
* Useful when multiple strategies share the same type.
|
|
12
|
+
*
|
|
13
|
+
* @defaultValue 0
|
|
14
|
+
*/
|
|
15
|
+
priorityOffset = 0;
|
|
16
|
+
/**
|
|
17
|
+
* Computed priority for strategy selection.
|
|
18
|
+
* Higher values are evaluated first.
|
|
19
|
+
*
|
|
20
|
+
* @returns The sum of the strategy type and priority offset
|
|
21
|
+
*/
|
|
22
|
+
get priority() {
|
|
23
|
+
return this.type + this.priorityOffset;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
HmrStrategy,
|
|
28
|
+
HmrStrategyType
|
|
29
|
+
};
|