@c9up/ream 0.1.3
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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/Application.d.ts +71 -0
- package/dist/Application.d.ts.map +1 -0
- package/dist/Application.js +151 -0
- package/dist/Application.js.map +1 -0
- package/dist/Codemods.d.ts +16 -0
- package/dist/Codemods.d.ts.map +1 -0
- package/dist/Codemods.js +277 -0
- package/dist/Codemods.js.map +1 -0
- package/dist/ConfigLoader.d.ts +29 -0
- package/dist/ConfigLoader.d.ts.map +1 -0
- package/dist/ConfigLoader.js +43 -0
- package/dist/ConfigLoader.js.map +1 -0
- package/dist/ErrorBoundary.d.ts +51 -0
- package/dist/ErrorBoundary.d.ts.map +1 -0
- package/dist/ErrorBoundary.js +122 -0
- package/dist/ErrorBoundary.js.map +1 -0
- package/dist/GracefulShutdown.d.ts +28 -0
- package/dist/GracefulShutdown.d.ts.map +1 -0
- package/dist/GracefulShutdown.js +55 -0
- package/dist/GracefulShutdown.js.map +1 -0
- package/dist/HealthCheck.d.ts +42 -0
- package/dist/HealthCheck.d.ts.map +1 -0
- package/dist/HealthCheck.js +65 -0
- package/dist/HealthCheck.js.map +1 -0
- package/dist/HotReload.d.ts +28 -0
- package/dist/HotReload.d.ts.map +1 -0
- package/dist/HotReload.js +60 -0
- package/dist/HotReload.js.map +1 -0
- package/dist/HttpKernel.d.ts +62 -0
- package/dist/HttpKernel.d.ts.map +1 -0
- package/dist/HttpKernel.js +210 -0
- package/dist/HttpKernel.js.map +1 -0
- package/dist/Ignitor.d.ts +195 -0
- package/dist/Ignitor.d.ts.map +1 -0
- package/dist/Ignitor.js +505 -0
- package/dist/Ignitor.js.map +1 -0
- package/dist/Provider.d.ts +54 -0
- package/dist/Provider.d.ts.map +1 -0
- package/dist/Provider.js +37 -0
- package/dist/Provider.js.map +1 -0
- package/dist/bodyparser/BodyParserMiddleware.d.ts +38 -0
- package/dist/bodyparser/BodyParserMiddleware.d.ts.map +1 -0
- package/dist/bodyparser/BodyParserMiddleware.js +143 -0
- package/dist/bodyparser/BodyParserMiddleware.js.map +1 -0
- package/dist/bodyparser/MultipartFile.d.ts +77 -0
- package/dist/bodyparser/MultipartFile.d.ts.map +1 -0
- package/dist/bodyparser/MultipartFile.js +138 -0
- package/dist/bodyparser/MultipartFile.js.map +1 -0
- package/dist/bodyparser/parseSize.d.ts +6 -0
- package/dist/bodyparser/parseSize.d.ts.map +1 -0
- package/dist/bodyparser/parseSize.js +21 -0
- package/dist/bodyparser/parseSize.js.map +1 -0
- package/dist/bootstrap/hyper-server.d.ts +27 -0
- package/dist/bootstrap/hyper-server.d.ts.map +1 -0
- package/dist/bootstrap/hyper-server.js +63 -0
- package/dist/bootstrap/hyper-server.js.map +1 -0
- package/dist/console/CommandRunner.d.ts +18 -0
- package/dist/console/CommandRunner.d.ts.map +1 -0
- package/dist/console/CommandRunner.js +65 -0
- package/dist/console/CommandRunner.js.map +1 -0
- package/dist/container/Container.d.ts +60 -0
- package/dist/container/Container.d.ts.map +1 -0
- package/dist/container/Container.js +329 -0
- package/dist/container/Container.js.map +1 -0
- package/dist/container/types.d.ts +25 -0
- package/dist/container/types.d.ts.map +1 -0
- package/dist/container/types.js +6 -0
- package/dist/container/types.js.map +1 -0
- package/dist/decorators/Lazy.d.ts +19 -0
- package/dist/decorators/Lazy.d.ts.map +1 -0
- package/dist/decorators/Lazy.js +53 -0
- package/dist/decorators/Lazy.js.map +1 -0
- package/dist/decorators/Service.d.ts +48 -0
- package/dist/decorators/Service.d.ts.map +1 -0
- package/dist/decorators/Service.js +70 -0
- package/dist/decorators/Service.js.map +1 -0
- package/dist/errors/FuzzyMatcher.d.ts +41 -0
- package/dist/errors/FuzzyMatcher.d.ts.map +1 -0
- package/dist/errors/FuzzyMatcher.js +81 -0
- package/dist/errors/FuzzyMatcher.js.map +1 -0
- package/dist/errors/ModuleErrors.d.ts +41 -0
- package/dist/errors/ModuleErrors.d.ts.map +1 -0
- package/dist/errors/ModuleErrors.js +65 -0
- package/dist/errors/ModuleErrors.js.map +1 -0
- package/dist/errors/PipelineStageError.d.ts +31 -0
- package/dist/errors/PipelineStageError.d.ts.map +1 -0
- package/dist/errors/PipelineStageError.js +77 -0
- package/dist/errors/PipelineStageError.js.map +1 -0
- package/dist/errors/ReamError.d.ts +50 -0
- package/dist/errors/ReamError.d.ts.map +1 -0
- package/dist/errors/ReamError.js +108 -0
- package/dist/errors/ReamError.js.map +1 -0
- package/dist/events/Emitter.d.ts +124 -0
- package/dist/events/Emitter.d.ts.map +1 -0
- package/dist/events/Emitter.js +271 -0
- package/dist/events/Emitter.js.map +1 -0
- package/dist/events/EventsProvider.d.ts +28 -0
- package/dist/events/EventsProvider.d.ts.map +1 -0
- package/dist/events/EventsProvider.js +36 -0
- package/dist/events/EventsProvider.js.map +1 -0
- package/dist/events/config.d.ts +8 -0
- package/dist/events/config.d.ts.map +1 -0
- package/dist/events/config.js +4 -0
- package/dist/events/config.js.map +1 -0
- package/dist/events/configure.d.ts +10 -0
- package/dist/events/configure.d.ts.map +1 -0
- package/dist/events/configure.js +11 -0
- package/dist/events/configure.js.map +1 -0
- package/dist/events/helix/helpers.d.ts +62 -0
- package/dist/events/helix/helpers.d.ts.map +1 -0
- package/dist/events/helix/helpers.js +187 -0
- package/dist/events/helix/helpers.js.map +1 -0
- package/dist/events/index.d.ts +17 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +15 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/native.d.ts +21 -0
- package/dist/events/native.d.ts.map +1 -0
- package/dist/events/native.js +17 -0
- package/dist/events/native.js.map +1 -0
- package/dist/events/services/main.d.ts +18 -0
- package/dist/events/services/main.d.ts.map +1 -0
- package/dist/events/services/main.js +31 -0
- package/dist/events/services/main.js.map +1 -0
- package/dist/events/testing/FakeBus.d.ts +66 -0
- package/dist/events/testing/FakeBus.d.ts.map +1 -0
- package/dist/events/testing/FakeBus.js +356 -0
- package/dist/events/testing/FakeBus.js.map +1 -0
- package/dist/graphql/GraphQLEngine.d.ts +69 -0
- package/dist/graphql/GraphQLEngine.d.ts.map +1 -0
- package/dist/graphql/GraphQLEngine.js +309 -0
- package/dist/graphql/GraphQLEngine.js.map +1 -0
- package/dist/graphql/GraphQLProvider.d.ts +32 -0
- package/dist/graphql/GraphQLProvider.d.ts.map +1 -0
- package/dist/graphql/GraphQLProvider.js +49 -0
- package/dist/graphql/GraphQLProvider.js.map +1 -0
- package/dist/helpers/base64.d.ts +40 -0
- package/dist/helpers/base64.d.ts.map +1 -0
- package/dist/helpers/base64.js +70 -0
- package/dist/helpers/base64.js.map +1 -0
- package/dist/helpers/index.d.ts +7 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +5 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/is.d.ts +101 -0
- package/dist/helpers/is.d.ts.map +1 -0
- package/dist/helpers/is.js +151 -0
- package/dist/helpers/is.js.map +1 -0
- package/dist/helpers/napi-loader.d.ts +46 -0
- package/dist/helpers/napi-loader.d.ts.map +1 -0
- package/dist/helpers/napi-loader.js +69 -0
- package/dist/helpers/napi-loader.js.map +1 -0
- package/dist/helpers/safeEqual.d.ts +9 -0
- package/dist/helpers/safeEqual.d.ts.map +1 -0
- package/dist/helpers/safeEqual.js +16 -0
- package/dist/helpers/safeEqual.js.map +1 -0
- package/dist/helpers/string.d.ts +161 -0
- package/dist/helpers/string.d.ts.map +1 -0
- package/dist/helpers/string.js +429 -0
- package/dist/helpers/string.js.map +1 -0
- package/dist/helpers/types.d.ts +83 -0
- package/dist/helpers/types.d.ts.map +1 -0
- package/dist/helpers/types.js +6 -0
- package/dist/helpers/types.js.map +1 -0
- package/dist/http/Exception.d.ts +103 -0
- package/dist/http/Exception.d.ts.map +1 -0
- package/dist/http/Exception.js +228 -0
- package/dist/http/Exception.js.map +1 -0
- package/dist/http/HttpContext.d.ts +69 -0
- package/dist/http/HttpContext.d.ts.map +1 -0
- package/dist/http/HttpContext.js +55 -0
- package/dist/http/HttpContext.js.map +1 -0
- package/dist/http/RedirectBuilder.d.ts +31 -0
- package/dist/http/RedirectBuilder.d.ts.map +1 -0
- package/dist/http/RedirectBuilder.js +75 -0
- package/dist/http/RedirectBuilder.js.map +1 -0
- package/dist/http/Request.d.ts +160 -0
- package/dist/http/Request.d.ts.map +1 -0
- package/dist/http/Request.js +484 -0
- package/dist/http/Request.js.map +1 -0
- package/dist/http/Response.d.ts +114 -0
- package/dist/http/Response.d.ts.map +1 -0
- package/dist/http/Response.js +303 -0
- package/dist/http/Response.js.map +1 -0
- package/dist/http/SseStream.d.ts +89 -0
- package/dist/http/SseStream.d.ts.map +1 -0
- package/dist/http/SseStream.js +228 -0
- package/dist/http/SseStream.js.map +1 -0
- package/dist/http/urlDecode.d.ts +8 -0
- package/dist/http/urlDecode.d.ts.map +1 -0
- package/dist/http/urlDecode.js +18 -0
- package/dist/http/urlDecode.js.map +1 -0
- package/dist/index.d.ts +92 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/Pipeline.d.ts +36 -0
- package/dist/middleware/Pipeline.d.ts.map +1 -0
- package/dist/middleware/Pipeline.js +104 -0
- package/dist/middleware/Pipeline.js.map +1 -0
- package/dist/openapi/OpenApiGenerator.d.ts +58 -0
- package/dist/openapi/OpenApiGenerator.d.ts.map +1 -0
- package/dist/openapi/OpenApiGenerator.js +192 -0
- package/dist/openapi/OpenApiGenerator.js.map +1 -0
- package/dist/openapi/OpenApiMiddleware.d.ts +24 -0
- package/dist/openapi/OpenApiMiddleware.d.ts.map +1 -0
- package/dist/openapi/OpenApiMiddleware.js +78 -0
- package/dist/openapi/OpenApiMiddleware.js.map +1 -0
- package/dist/openapi/OpenApiProvider.d.ts +36 -0
- package/dist/openapi/OpenApiProvider.d.ts.map +1 -0
- package/dist/openapi/OpenApiProvider.js +42 -0
- package/dist/openapi/OpenApiProvider.js.map +1 -0
- package/dist/resources/ApiResource.d.ts +45 -0
- package/dist/resources/ApiResource.d.ts.map +1 -0
- package/dist/resources/ApiResource.js +58 -0
- package/dist/resources/ApiResource.js.map +1 -0
- package/dist/router/Router.d.ts +205 -0
- package/dist/router/Router.d.ts.map +1 -0
- package/dist/router/Router.js +552 -0
- package/dist/router/Router.js.map +1 -0
- package/dist/rpc/RpcProvider.d.ts +34 -0
- package/dist/rpc/RpcProvider.d.ts.map +1 -0
- package/dist/rpc/RpcProvider.js +37 -0
- package/dist/rpc/RpcProvider.js.map +1 -0
- package/dist/rpc/RpcRouter.d.ts +61 -0
- package/dist/rpc/RpcRouter.d.ts.map +1 -0
- package/dist/rpc/RpcRouter.js +187 -0
- package/dist/rpc/RpcRouter.js.map +1 -0
- package/dist/scheduler/Schedule.d.ts +53 -0
- package/dist/scheduler/Schedule.d.ts.map +1 -0
- package/dist/scheduler/Schedule.js +76 -0
- package/dist/scheduler/Schedule.js.map +1 -0
- package/dist/scheduler/ScheduleProvider.d.ts +56 -0
- package/dist/scheduler/ScheduleProvider.d.ts.map +1 -0
- package/dist/scheduler/ScheduleProvider.js +145 -0
- package/dist/scheduler/ScheduleProvider.js.map +1 -0
- package/dist/scheduler/Scheduler.d.ts +209 -0
- package/dist/scheduler/Scheduler.d.ts.map +1 -0
- package/dist/scheduler/Scheduler.js +432 -0
- package/dist/scheduler/Scheduler.js.map +1 -0
- package/dist/scheduler/index.d.ts +14 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/index.js +6 -0
- package/dist/scheduler/index.js.map +1 -0
- package/dist/scheduler/locks/LockBackend.d.ts +37 -0
- package/dist/scheduler/locks/LockBackend.d.ts.map +1 -0
- package/dist/scheduler/locks/LockBackend.js +13 -0
- package/dist/scheduler/locks/LockBackend.js.map +1 -0
- package/dist/scheduler/locks/MemoryLockBackend.d.ts +39 -0
- package/dist/scheduler/locks/MemoryLockBackend.d.ts.map +1 -0
- package/dist/scheduler/locks/MemoryLockBackend.js +71 -0
- package/dist/scheduler/locks/MemoryLockBackend.js.map +1 -0
- package/dist/scheduler/observability/ErrorReporter.d.ts +15 -0
- package/dist/scheduler/observability/ErrorReporter.d.ts.map +1 -0
- package/dist/scheduler/observability/ErrorReporter.js +13 -0
- package/dist/scheduler/observability/ErrorReporter.js.map +1 -0
- package/dist/scheduler/observability/ScheduleEvent.d.ts +57 -0
- package/dist/scheduler/observability/ScheduleEvent.d.ts.map +1 -0
- package/dist/scheduler/observability/ScheduleEvent.js +12 -0
- package/dist/scheduler/observability/ScheduleEvent.js.map +1 -0
- package/dist/scheduler/observability/ScheduleEventSink.d.ts +20 -0
- package/dist/scheduler/observability/ScheduleEventSink.d.ts.map +1 -0
- package/dist/scheduler/observability/ScheduleEventSink.js +17 -0
- package/dist/scheduler/observability/ScheduleEventSink.js.map +1 -0
- package/dist/scheduler/observability/StatsTracker.d.ts +50 -0
- package/dist/scheduler/observability/StatsTracker.d.ts.map +1 -0
- package/dist/scheduler/observability/StatsTracker.js +96 -0
- package/dist/scheduler/observability/StatsTracker.js.map +1 -0
- package/dist/security/CookieSigner.d.ts +13 -0
- package/dist/security/CookieSigner.d.ts.map +1 -0
- package/dist/security/CookieSigner.js +51 -0
- package/dist/security/CookieSigner.js.map +1 -0
- package/dist/security/SignedUrl.d.ts +17 -0
- package/dist/security/SignedUrl.d.ts.map +1 -0
- package/dist/security/SignedUrl.js +63 -0
- package/dist/security/SignedUrl.js.map +1 -0
- package/dist/security/crypto.d.ts +25 -0
- package/dist/security/crypto.d.ts.map +1 -0
- package/dist/security/crypto.js +82 -0
- package/dist/security/crypto.js.map +1 -0
- package/dist/server/HyperServer.d.ts +64 -0
- package/dist/server/HyperServer.d.ts.map +1 -0
- package/dist/server/HyperServer.js +54 -0
- package/dist/server/HyperServer.js.map +1 -0
- package/dist/server/Server.d.ts +68 -0
- package/dist/server/Server.d.ts.map +1 -0
- package/dist/server/Server.js +113 -0
- package/dist/server/Server.js.map +1 -0
- package/dist/services/app.d.ts +14 -0
- package/dist/services/app.d.ts.map +1 -0
- package/dist/services/app.js +27 -0
- package/dist/services/app.js.map +1 -0
- package/dist/services/router.d.ts +21 -0
- package/dist/services/router.d.ts.map +1 -0
- package/dist/services/router.js +36 -0
- package/dist/services/router.js.map +1 -0
- package/dist/services/server.d.ts +16 -0
- package/dist/services/server.d.ts.map +1 -0
- package/dist/services/server.js +32 -0
- package/dist/services/server.js.map +1 -0
- package/dist/session/Session.d.ts +88 -0
- package/dist/session/Session.d.ts.map +1 -0
- package/dist/session/Session.js +186 -0
- package/dist/session/Session.js.map +1 -0
- package/dist/session/SessionMiddleware.d.ts +16 -0
- package/dist/session/SessionMiddleware.d.ts.map +1 -0
- package/dist/session/SessionMiddleware.js +132 -0
- package/dist/session/SessionMiddleware.js.map +1 -0
- package/dist/session/drivers/CookieDriver.d.ts +17 -0
- package/dist/session/drivers/CookieDriver.d.ts.map +1 -0
- package/dist/session/drivers/CookieDriver.js +42 -0
- package/dist/session/drivers/CookieDriver.js.map +1 -0
- package/dist/session/drivers/MemoryDriver.d.ts +9 -0
- package/dist/session/drivers/MemoryDriver.d.ts.map +1 -0
- package/dist/session/drivers/MemoryDriver.js +24 -0
- package/dist/session/drivers/MemoryDriver.js.map +1 -0
- package/dist/storage/S3Driver.d.ts +27 -0
- package/dist/storage/S3Driver.d.ts.map +1 -0
- package/dist/storage/S3Driver.js +135 -0
- package/dist/storage/S3Driver.js.map +1 -0
- package/dist/storage/StaticMiddleware.d.ts +27 -0
- package/dist/storage/StaticMiddleware.d.ts.map +1 -0
- package/dist/storage/StaticMiddleware.js +153 -0
- package/dist/storage/StaticMiddleware.js.map +1 -0
- package/dist/storage/StaticProvider.d.ts +26 -0
- package/dist/storage/StaticProvider.d.ts.map +1 -0
- package/dist/storage/StaticProvider.js +31 -0
- package/dist/storage/StaticProvider.js.map +1 -0
- package/dist/storage/StorageManager.d.ts +31 -0
- package/dist/storage/StorageManager.d.ts.map +1 -0
- package/dist/storage/StorageManager.js +120 -0
- package/dist/storage/StorageManager.js.map +1 -0
- package/dist/testing/RequestBuilder.d.ts +67 -0
- package/dist/testing/RequestBuilder.d.ts.map +1 -0
- package/dist/testing/RequestBuilder.js +202 -0
- package/dist/testing/RequestBuilder.js.map +1 -0
- package/dist/testing/TestClient.d.ts +96 -0
- package/dist/testing/TestClient.d.ts.map +1 -0
- package/dist/testing/TestClient.js +263 -0
- package/dist/testing/TestClient.js.map +1 -0
- package/dist/types/helpers.d.ts +47 -0
- package/dist/types/helpers.d.ts.map +1 -0
- package/dist/types/helpers.js +5 -0
- package/dist/types/helpers.js.map +1 -0
- package/events.darwin-arm64.node +0 -0
- package/events.darwin-x64.node +0 -0
- package/events.linux-arm64-gnu.node +0 -0
- package/events.linux-x64-gnu.node +0 -0
- package/events.win32-x64-msvc.node +0 -0
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +106 -0
- package/scheduler.darwin-arm64.node +0 -0
- package/scheduler.darwin-x64.node +0 -0
- package/scheduler.linux-arm64-gnu.node +0 -0
- package/scheduler.linux-x64-gnu.node +0 -0
- package/scheduler.win32-x64-msvc.node +0 -0
- package/scripts/copy-napi.mjs +113 -0
- package/src/Application.ts +177 -0
- package/src/Codemods.ts +343 -0
- package/src/ConfigLoader.ts +49 -0
- package/src/ErrorBoundary.ts +157 -0
- package/src/GracefulShutdown.ts +80 -0
- package/src/HealthCheck.ts +96 -0
- package/src/HotReload.ts +78 -0
- package/src/HttpKernel.ts +305 -0
- package/src/Ignitor.ts +656 -0
- package/src/Provider.ts +74 -0
- package/src/bodyparser/BodyParserMiddleware.ts +183 -0
- package/src/bodyparser/MultipartFile.ts +181 -0
- package/src/bodyparser/parseSize.ts +19 -0
- package/src/bootstrap/hyper-server.ts +78 -0
- package/src/console/CommandRunner.ts +82 -0
- package/src/container/Container.ts +383 -0
- package/src/container/types.ts +30 -0
- package/src/decorators/Lazy.ts +57 -0
- package/src/decorators/Service.ts +85 -0
- package/src/errors/FuzzyMatcher.ts +93 -0
- package/src/errors/ModuleErrors.ts +73 -0
- package/src/errors/PipelineStageError.ts +97 -0
- package/src/errors/ReamError.ts +138 -0
- package/src/events/Emitter.ts +333 -0
- package/src/events/EventsProvider.ts +58 -0
- package/src/events/config.ts +10 -0
- package/src/events/configure.ts +19 -0
- package/src/events/helix/helpers.ts +260 -0
- package/src/events/index.ts +22 -0
- package/src/events/native.ts +37 -0
- package/src/events/services/main.ts +39 -0
- package/src/events/testing/FakeBus.ts +420 -0
- package/src/graphql/GraphQLEngine.ts +421 -0
- package/src/graphql/GraphQLProvider.ts +59 -0
- package/src/helpers/base64.ts +72 -0
- package/src/helpers/index.ts +6 -0
- package/src/helpers/is.ts +162 -0
- package/src/helpers/napi-loader.ts +106 -0
- package/src/helpers/safeEqual.ts +15 -0
- package/src/helpers/string.ts +469 -0
- package/src/helpers/types.ts +100 -0
- package/src/http/Exception.ts +272 -0
- package/src/http/HttpContext.ts +108 -0
- package/src/http/RedirectBuilder.ts +89 -0
- package/src/http/Request.ts +540 -0
- package/src/http/Response.ts +351 -0
- package/src/http/SseStream.ts +250 -0
- package/src/http/urlDecode.ts +18 -0
- package/src/index.ts +263 -0
- package/src/middleware/Pipeline.ts +136 -0
- package/src/openapi/OpenApiGenerator.ts +254 -0
- package/src/openapi/OpenApiMiddleware.ts +101 -0
- package/src/openapi/OpenApiProvider.ts +67 -0
- package/src/resources/ApiResource.ts +79 -0
- package/src/router/Router.ts +733 -0
- package/src/rpc/RpcProvider.ts +54 -0
- package/src/rpc/RpcRouter.ts +243 -0
- package/src/scheduler/Schedule.ts +96 -0
- package/src/scheduler/ScheduleProvider.ts +177 -0
- package/src/scheduler/Scheduler.ts +601 -0
- package/src/scheduler/index.ts +24 -0
- package/src/scheduler/locks/LockBackend.ts +38 -0
- package/src/scheduler/locks/MemoryLockBackend.ts +85 -0
- package/src/scheduler/observability/ErrorReporter.ts +13 -0
- package/src/scheduler/observability/ScheduleEvent.ts +61 -0
- package/src/scheduler/observability/ScheduleEventSink.ts +21 -0
- package/src/scheduler/observability/StatsTracker.ts +134 -0
- package/src/security/CookieSigner.ts +54 -0
- package/src/security/SignedUrl.ts +71 -0
- package/src/security/crypto.ts +98 -0
- package/src/server/HyperServer.ts +121 -0
- package/src/server/Server.ts +147 -0
- package/src/services/app.ts +34 -0
- package/src/services/router.ts +44 -0
- package/src/services/server.ts +40 -0
- package/src/session/Session.ts +231 -0
- package/src/session/SessionMiddleware.ts +153 -0
- package/src/session/drivers/CookieDriver.ts +48 -0
- package/src/session/drivers/MemoryDriver.ts +29 -0
- package/src/storage/S3Driver.ts +171 -0
- package/src/storage/StaticMiddleware.ts +182 -0
- package/src/storage/StaticProvider.ts +40 -0
- package/src/storage/StorageManager.ts +142 -0
- package/src/testing/RequestBuilder.ts +275 -0
- package/src/testing/TestClient.ts +344 -0
- package/src/types/helpers.ts +52 -0
- package/swcrc.app.json +17 -0
- package/tsconfig.app.json +21 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health Check — built-in /health endpoint compatible with Kubernetes liveness/readiness probes.
|
|
3
|
+
*
|
|
4
|
+
* @implements FR81
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface HealthStatus {
|
|
8
|
+
status: 'ok' | 'degraded' | 'error'
|
|
9
|
+
uptime: number
|
|
10
|
+
timestamp: string
|
|
11
|
+
checks: HealthCheckResult[]
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface HealthCheckResult {
|
|
15
|
+
name: string
|
|
16
|
+
status: 'ok' | 'warn' | 'error'
|
|
17
|
+
message?: string
|
|
18
|
+
latency?: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type HealthChecker = () => Promise<HealthCheckResult> | HealthCheckResult
|
|
22
|
+
|
|
23
|
+
/** Default per-checker timeout in ms. */
|
|
24
|
+
const DEFAULT_CHECK_TIMEOUT = 5000
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Manages health check registrations and produces aggregated status.
|
|
28
|
+
*/
|
|
29
|
+
export class HealthCheck {
|
|
30
|
+
private checkers: Map<string, HealthChecker> = new Map()
|
|
31
|
+
private startTime = Date.now()
|
|
32
|
+
private checkTimeout: number
|
|
33
|
+
|
|
34
|
+
constructor(options?: { checkTimeout?: number }) {
|
|
35
|
+
this.checkTimeout = options?.checkTimeout ?? DEFAULT_CHECK_TIMEOUT
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Register a health checker. */
|
|
39
|
+
register(name: string, checker: HealthChecker): void {
|
|
40
|
+
this.checkers.set(name, checker)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Run all health checks and return aggregated status. */
|
|
44
|
+
async check(): Promise<HealthStatus> {
|
|
45
|
+
const checks: HealthCheckResult[] = []
|
|
46
|
+
|
|
47
|
+
for (const [name, checker] of this.checkers) {
|
|
48
|
+
const start = Date.now()
|
|
49
|
+
try {
|
|
50
|
+
const result = await Promise.race([
|
|
51
|
+
Promise.resolve(checker()),
|
|
52
|
+
new Promise<never>((_, reject) =>
|
|
53
|
+
setTimeout(
|
|
54
|
+
() =>
|
|
55
|
+
reject(new Error(`Health check '${name}' timed out after ${this.checkTimeout}ms`)),
|
|
56
|
+
this.checkTimeout,
|
|
57
|
+
),
|
|
58
|
+
),
|
|
59
|
+
])
|
|
60
|
+
// Enforce authoritative name from registration key
|
|
61
|
+
result.name = name
|
|
62
|
+
result.latency = Date.now() - start
|
|
63
|
+
checks.push(result)
|
|
64
|
+
} catch (err) {
|
|
65
|
+
checks.push({
|
|
66
|
+
name,
|
|
67
|
+
status: 'error',
|
|
68
|
+
message: err instanceof Error ? err.message : String(err),
|
|
69
|
+
latency: Date.now() - start,
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const hasError = checks.some((c) => c.status === 'error')
|
|
75
|
+
const hasWarn = checks.some((c) => c.status === 'warn')
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
status: hasError ? 'error' : hasWarn ? 'degraded' : 'ok',
|
|
79
|
+
uptime: Math.floor((Date.now() - this.startTime) / 1000),
|
|
80
|
+
timestamp: new Date().toISOString(),
|
|
81
|
+
checks,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Create the /health route handler. Returns 200 for ok, 503 for degraded/error. */
|
|
86
|
+
handler(): (ctx: {
|
|
87
|
+
response: { status: number; headers: Record<string, string>; body: string }
|
|
88
|
+
}) => Promise<void> {
|
|
89
|
+
return async (ctx) => {
|
|
90
|
+
const health = await this.check()
|
|
91
|
+
ctx.response.status = health.status === 'ok' ? 200 : 503
|
|
92
|
+
ctx.response.headers['content-type'] = 'application/json'
|
|
93
|
+
ctx.response.body = JSON.stringify(health)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
package/src/HotReload.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HotReload — re-registers routes and middleware when TS files change.
|
|
3
|
+
*
|
|
4
|
+
* The Hyper server (Rust) stays alive. Only the TypeScript handlers are swapped.
|
|
5
|
+
* This gives sub-100ms reload times since no Rust recompilation is needed.
|
|
6
|
+
*
|
|
7
|
+
* @implements FR75, FR76
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as fs from 'node:fs'
|
|
11
|
+
import * as path from 'node:path'
|
|
12
|
+
|
|
13
|
+
export interface HotReloadOptions {
|
|
14
|
+
/** Directories to watch for changes. */
|
|
15
|
+
watchDirs: string[]
|
|
16
|
+
/** File extensions to watch (default: ['.ts', '.js']). */
|
|
17
|
+
extensions?: string[]
|
|
18
|
+
/** Callback to execute on reload. */
|
|
19
|
+
onReload: () => Promise<void> | void
|
|
20
|
+
/** Debounce delay in ms (default: 50). */
|
|
21
|
+
debounce?: number
|
|
22
|
+
/** Logger (optional). */
|
|
23
|
+
logger?: { info: (msg: string) => void }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Watch TypeScript files and trigger handler re-registration on changes.
|
|
28
|
+
* Returns a cleanup function to stop watching.
|
|
29
|
+
*/
|
|
30
|
+
export function startHotReload(options: HotReloadOptions): () => void {
|
|
31
|
+
const extensions = options.extensions ?? ['.ts', '.js']
|
|
32
|
+
const debounceMs = options.debounce ?? 50
|
|
33
|
+
const logger = options.logger ?? { info: () => {} }
|
|
34
|
+
|
|
35
|
+
let debounceTimer: ReturnType<typeof setTimeout> | undefined
|
|
36
|
+
const watchers: fs.FSWatcher[] = []
|
|
37
|
+
|
|
38
|
+
const handleChange = (filename: string | null) => {
|
|
39
|
+
if (!filename || !extensions.some((ext) => filename.endsWith(ext))) return
|
|
40
|
+
|
|
41
|
+
if (debounceTimer) clearTimeout(debounceTimer)
|
|
42
|
+
debounceTimer = setTimeout(async () => {
|
|
43
|
+
const start = Date.now()
|
|
44
|
+
try {
|
|
45
|
+
await options.onReload()
|
|
46
|
+
const duration = Date.now() - start
|
|
47
|
+
logger.info(`Hot reload: ${duration}ms`)
|
|
48
|
+
} catch (err) {
|
|
49
|
+
logger.info(`Hot reload failed: ${err instanceof Error ? err.message : String(err)}`)
|
|
50
|
+
}
|
|
51
|
+
}, debounceMs)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
for (const dir of options.watchDirs) {
|
|
55
|
+
const resolved = path.resolve(dir)
|
|
56
|
+
if (!fs.existsSync(resolved)) continue
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const watcher = fs.watch(
|
|
60
|
+
resolved,
|
|
61
|
+
{ recursive: true },
|
|
62
|
+
(_event: string, filename: string | null) => {
|
|
63
|
+
handleChange(filename)
|
|
64
|
+
},
|
|
65
|
+
)
|
|
66
|
+
watchers.push(watcher)
|
|
67
|
+
} catch {
|
|
68
|
+
// fs.watch with recursive may not be supported on all platforms
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
logger.info(`Hot reload watching: ${options.watchDirs.join(', ')}`)
|
|
73
|
+
|
|
74
|
+
return () => {
|
|
75
|
+
if (debounceTimer) clearTimeout(debounceTimer)
|
|
76
|
+
for (const w of watchers) w.close()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HttpKernel — bridges HyperServer NAPI with Router + Middleware Pipeline + ExceptionHandler.
|
|
3
|
+
*
|
|
4
|
+
* Request flow (like AdonisJS):
|
|
5
|
+
* 1. Parse JSON from Rust NAPI
|
|
6
|
+
* 2. Create HttpContext
|
|
7
|
+
* 3. Onion pipeline: Server MW → Router MW → Route MW → Guards → Handler
|
|
8
|
+
* 4. ExceptionHandler for any errors
|
|
9
|
+
*
|
|
10
|
+
* @implements FR21, FR22, FR23, FR24
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { Container } from './container/Container.js'
|
|
14
|
+
import type { Emitter } from './events/Emitter.js'
|
|
15
|
+
import { E_ROUTE_NOT_FOUND, ExceptionHandler } from './http/Exception.js'
|
|
16
|
+
import { HttpContext } from './http/HttpContext.js'
|
|
17
|
+
import type { MiddlewareFunction, MiddlewareRegistry } from './middleware/Pipeline.js'
|
|
18
|
+
import { compose } from './middleware/Pipeline.js'
|
|
19
|
+
import type { Router } from './router/Router.js'
|
|
20
|
+
import type { Dict } from './types/helpers.js'
|
|
21
|
+
|
|
22
|
+
export interface HttpKernelConfig {
|
|
23
|
+
router: Router
|
|
24
|
+
middleware: MiddlewareRegistry
|
|
25
|
+
container?: Container
|
|
26
|
+
exceptionHandler?: ExceptionHandler
|
|
27
|
+
serverMiddleware?: MiddlewareFunction[]
|
|
28
|
+
routerMiddleware?: MiddlewareFunction[]
|
|
29
|
+
onError?: (error: unknown, ctx: HttpContext) => void
|
|
30
|
+
debug?: boolean
|
|
31
|
+
/**
|
|
32
|
+
* Lazily-resolved streaming backend. The Ignitor wires this so that
|
|
33
|
+
* `ctx.response.sse()` can register / push / close streams against the
|
|
34
|
+
* Rust HyperServer registry. Returning `undefined` short-circuits the
|
|
35
|
+
* SSE path with a clean error — used by mock servers in unit tests.
|
|
36
|
+
*/
|
|
37
|
+
streamBackend?: () => import('./http/SseStream.js').StreamBackend | undefined
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface HttpKernelResponse {
|
|
41
|
+
status: number
|
|
42
|
+
headers: Dict
|
|
43
|
+
body: string
|
|
44
|
+
/**
|
|
45
|
+
* Streaming-response handle. Present when the route handler opened
|
|
46
|
+
* an `SseStream` (`response.sse()`). The HyperServer NAPI matches
|
|
47
|
+
* this id against its stream registry to keep the connection open
|
|
48
|
+
* and feed the body from JS-pushed chunks.
|
|
49
|
+
*/
|
|
50
|
+
streamId?: string
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Shape the kernel expects when called with an already-parsed object — the
|
|
55
|
+
* NAPI bridge passes this directly to skip a JSON round-trip. The string
|
|
56
|
+
* form is the legacy entrypoint kept for serverless / fixture use.
|
|
57
|
+
*/
|
|
58
|
+
export interface HttpKernelRequest {
|
|
59
|
+
method: string
|
|
60
|
+
path: string
|
|
61
|
+
query: string
|
|
62
|
+
headers: Dict
|
|
63
|
+
body: string
|
|
64
|
+
bodyEncoding?: 'utf8' | 'base64'
|
|
65
|
+
remoteAddr?: string
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function createHttpKernel(
|
|
69
|
+
config: HttpKernelConfig,
|
|
70
|
+
): (request: HttpKernelRequest) => Promise<HttpKernelResponse> {
|
|
71
|
+
// Debug mode requires explicit opt-in — never leak stack traces by default
|
|
72
|
+
const handler = config.exceptionHandler ?? new ExceptionHandler(config.debug === true)
|
|
73
|
+
const serverMw = config.serverMiddleware ?? []
|
|
74
|
+
const routerMw = config.routerMiddleware ?? []
|
|
75
|
+
|
|
76
|
+
// Pipeline cache: compiled middleware chain per route key (PERF-7)
|
|
77
|
+
// Cleared when router.clear() is called (hot-reload).
|
|
78
|
+
const pipelineCache = new Map<string, { chain: MiddlewareFunction }>()
|
|
79
|
+
|
|
80
|
+
// Hook into router clear for cache invalidation
|
|
81
|
+
const origClear = config.router.clear.bind(config.router)
|
|
82
|
+
config.router.clear = () => {
|
|
83
|
+
origClear()
|
|
84
|
+
pipelineCache.clear()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Resolve the events emitter once, only when the app registered
|
|
88
|
+
// `EventsProvider`. Lazy + cached: the binding may not exist yet at kernel
|
|
89
|
+
// creation, and `has()` avoids loading the native bus for apps without events.
|
|
90
|
+
let eventsEmitter: Emitter | undefined
|
|
91
|
+
let eventsResolved = false
|
|
92
|
+
const resolveEvents = (): Emitter | undefined => {
|
|
93
|
+
if (!eventsResolved) {
|
|
94
|
+
eventsResolved = true
|
|
95
|
+
if (config.container?.has('events')) {
|
|
96
|
+
eventsEmitter = config.container.resolve<Emitter>('events')
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return eventsEmitter
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return async (reqData: HttpKernelRequest): Promise<HttpKernelResponse> => {
|
|
103
|
+
// The Rust HyperServer hands the request as a typed JS object via napi
|
|
104
|
+
// `to_js_value` (no JSON intermediate). Serverless adapters that pass a
|
|
105
|
+
// JSON string must `JSON.parse` themselves before invoking the kernel.
|
|
106
|
+
|
|
107
|
+
// 2. Correlation ID
|
|
108
|
+
const CORR_ID_RE = /^[A-Za-z0-9\-_]{8,128}$/
|
|
109
|
+
const rawCorrId = reqData.headers['x-request-id'] ?? reqData.headers['x-correlation-id'] ?? ''
|
|
110
|
+
const correlationId = CORR_ID_RE.test(rawCorrId) ? rawCorrId : crypto.randomUUID()
|
|
111
|
+
|
|
112
|
+
// 3. Match route (pass host for domain-based routing).
|
|
113
|
+
// The Rust HyperServer lowercases every header name before handing
|
|
114
|
+
// the request over (see crates/ream-http/src/request.rs — `headers`
|
|
115
|
+
// is documented "lowercased"). Looking up `host` is therefore the
|
|
116
|
+
// only correct key; the previous PascalCase fallback was dead code.
|
|
117
|
+
const host = reqData.headers.host
|
|
118
|
+
const match = config.router.match(reqData.method, reqData.path, host)
|
|
119
|
+
const routeInfo = match
|
|
120
|
+
? {
|
|
121
|
+
pattern: match.route.path,
|
|
122
|
+
name: match.route.name,
|
|
123
|
+
middleware: match.route.middleware,
|
|
124
|
+
// Forward the controller class + method name onto the public
|
|
125
|
+
// RouteInfo so middleware (Warden's @Guard, Photon's @Meta) can
|
|
126
|
+
// read decorator metadata via Reflect. Absent for inline-arrow
|
|
127
|
+
// route handlers — that's intentional, decorators only apply
|
|
128
|
+
// to controller methods.
|
|
129
|
+
controller: match.route.controller?.target.prototype as object | undefined,
|
|
130
|
+
action: match.route.controller?.method,
|
|
131
|
+
}
|
|
132
|
+
: { pattern: '', middleware: [] }
|
|
133
|
+
|
|
134
|
+
// 4. Create HttpContext
|
|
135
|
+
const ctx = new HttpContext(correlationId, reqData, match?.params ?? {}, routeInfo)
|
|
136
|
+
ctx.setRouteUrlResolver((name, params) => config.router.makeUrl(name, params))
|
|
137
|
+
ctx.events = resolveEvents()
|
|
138
|
+
// Wire the streaming backend so `ctx.response.sse()` can talk to
|
|
139
|
+
// the HyperServer NAPI. Falls back silently when no backend is
|
|
140
|
+
// available (mock server, websocket-only host) — the SSE helper
|
|
141
|
+
// throws a clean error in that case.
|
|
142
|
+
const backend = config.streamBackend?.()
|
|
143
|
+
if (backend) {
|
|
144
|
+
ctx.response.setStreamBackend(backend)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
// 5. Build the FULL onion pipeline:
|
|
149
|
+
// Server MW → [route match check] → Router MW → Route named MW → Route inline MW → Guards → Handler
|
|
150
|
+
const coreHandler: MiddlewareFunction = async (innerCtx) => {
|
|
151
|
+
if (!match) {
|
|
152
|
+
throw new E_ROUTE_NOT_FOUND(reqData.method, reqData.path)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Cache key: method + path pattern (static per route definition)
|
|
156
|
+
const cacheKey = `${match.route.method}:${match.route.path}`
|
|
157
|
+
let cached = pipelineCache.get(cacheKey)
|
|
158
|
+
|
|
159
|
+
if (!cached) {
|
|
160
|
+
// Resolve handler (once per route)
|
|
161
|
+
let routeHandler: (typeof match.route)['handler']
|
|
162
|
+
if (match.route.controller) {
|
|
163
|
+
routeHandler = createControllerHandler(match.route.controller, config.container)
|
|
164
|
+
} else if (match.route.handler) {
|
|
165
|
+
routeHandler = match.route.handler
|
|
166
|
+
} else {
|
|
167
|
+
throw new Error(
|
|
168
|
+
`Route ${match.route.method} ${match.route.path} has neither controller nor handler`,
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Merge route-level guards with controller method decorator metadata (once)
|
|
173
|
+
let guards = [...match.route.guards]
|
|
174
|
+
let roles = [...match.route.roles]
|
|
175
|
+
let permissions = [...match.route.permissions]
|
|
176
|
+
|
|
177
|
+
if (match.route.controller) {
|
|
178
|
+
const meta = readControllerGuardMetadata(
|
|
179
|
+
match.route.controller.target,
|
|
180
|
+
match.route.controller.method,
|
|
181
|
+
)
|
|
182
|
+
guards = [...guards, ...meta.guards]
|
|
183
|
+
roles = [...roles, ...meta.roles]
|
|
184
|
+
permissions = [...permissions, ...meta.permissions]
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Compile pipeline once
|
|
188
|
+
const chain = config.middleware.buildChain(
|
|
189
|
+
match.route.middleware,
|
|
190
|
+
[...routerMw, ...match.route.inlineMiddleware],
|
|
191
|
+
async (c) => {
|
|
192
|
+
await routeHandler(c)
|
|
193
|
+
},
|
|
194
|
+
{ guards, roles, permissions },
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
cached = { chain }
|
|
198
|
+
pipelineCache.set(cacheKey, cached)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// API versioning headers (per-request, cheap)
|
|
202
|
+
if (match.route.version) {
|
|
203
|
+
innerCtx.response.header('x-api-version', match.route.version)
|
|
204
|
+
}
|
|
205
|
+
if (match.route.deprecates) {
|
|
206
|
+
innerCtx.response.header('deprecation', 'true')
|
|
207
|
+
innerCtx.response.header('x-deprecated-version', match.route.deprecates.version)
|
|
208
|
+
if (match.route.deprecates.sunset) {
|
|
209
|
+
innerCtx.response.header('sunset', match.route.deprecates.sunset)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
await cached.chain(innerCtx, async () => {})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Compose: server middleware wraps everything (onion)
|
|
217
|
+
const fullPipeline = compose([...serverMw, coreHandler])
|
|
218
|
+
await fullPipeline(ctx, async () => {})
|
|
219
|
+
|
|
220
|
+
return serializeResponse(ctx)
|
|
221
|
+
} catch (error) {
|
|
222
|
+
// If the handler opened an SSE stream via `response.sse()` and
|
|
223
|
+
// THEN threw, the reserved stream id is still on the response.
|
|
224
|
+
// Tear it down before building the error response — otherwise
|
|
225
|
+
// serializeResponse emits `streamId` next to an error body and
|
|
226
|
+
// the HyperServer keeps feeding a dead stream slot forever.
|
|
227
|
+
await ctx.response.abortStream()
|
|
228
|
+
try {
|
|
229
|
+
await handler.handle(error, ctx)
|
|
230
|
+
await handler.report(error, ctx)
|
|
231
|
+
} catch (handlerError) {
|
|
232
|
+
console.error('ExceptionHandler failed:', handlerError)
|
|
233
|
+
ctx.response
|
|
234
|
+
.status(500)
|
|
235
|
+
.json({ error: { code: 'E_HANDLER_FAILURE', message: 'An internal error occurred' } })
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (config.onError) {
|
|
239
|
+
config.onError(error, ctx)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Core domain event: a request raised an exception. Fire-and-forget
|
|
243
|
+
// through the bus when events are wired (error path only — zero cost on
|
|
244
|
+
// the happy path). Emitter isolates listener failures from the response.
|
|
245
|
+
ctx.events?.emit('exception', {
|
|
246
|
+
id: ctx.id,
|
|
247
|
+
method: reqData.method,
|
|
248
|
+
path: reqData.path,
|
|
249
|
+
error: error instanceof Error ? error.message : String(error),
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
return serializeResponse(ctx)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function createControllerHandler(
|
|
258
|
+
// biome-ignore lint/suspicious/noExplicitAny: see ControllerAction type — IoC resolves constructor params
|
|
259
|
+
controller: { target: new (...args: any[]) => any; method: string },
|
|
260
|
+
container?: Container,
|
|
261
|
+
): (ctx: HttpContext) => Promise<void> {
|
|
262
|
+
return async (ctx: HttpContext) => {
|
|
263
|
+
const instance = container ? container.make(controller.target) : new controller.target()
|
|
264
|
+
const method = (instance as Record<string, (ctx: HttpContext) => Promise<void> | void>)[
|
|
265
|
+
controller.method
|
|
266
|
+
]
|
|
267
|
+
if (typeof method !== 'function') {
|
|
268
|
+
throw new Error(
|
|
269
|
+
`Controller method '${controller.method}' not found on ${controller.target.name}`,
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
await method.call(instance, ctx)
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Read @Guard, @Role, @Permission metadata from a controller method.
|
|
278
|
+
* Returns empty arrays if no decorators are present.
|
|
279
|
+
*/
|
|
280
|
+
function readControllerGuardMetadata(
|
|
281
|
+
target: new (...args: unknown[]) => unknown,
|
|
282
|
+
method: string,
|
|
283
|
+
): { guards: string[]; roles: string[]; permissions: string[] } {
|
|
284
|
+
try {
|
|
285
|
+
const guards: string[] =
|
|
286
|
+
Reflect.getMetadata(Symbol.for('warden:guard'), target.prototype, method) ?? []
|
|
287
|
+
const roles: string[] =
|
|
288
|
+
Reflect.getMetadata(Symbol.for('warden:role'), target.prototype, method) ?? []
|
|
289
|
+
const permissions: string[] =
|
|
290
|
+
Reflect.getMetadata(Symbol.for('warden:permission'), target.prototype, method) ?? []
|
|
291
|
+
return { guards, roles, permissions }
|
|
292
|
+
} catch {
|
|
293
|
+
return { guards: [], roles: [], permissions: [] }
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function serializeResponse(ctx: HttpContext): HttpKernelResponse {
|
|
298
|
+
const streamId = ctx.response.getStreamId()
|
|
299
|
+
return {
|
|
300
|
+
status: ctx.response.getStatus(),
|
|
301
|
+
headers: ctx.response.getHeaders(),
|
|
302
|
+
body: ctx.response.getBody(),
|
|
303
|
+
...(streamId !== undefined ? { streamId } : {}),
|
|
304
|
+
}
|
|
305
|
+
}
|