@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
package/src/Ignitor.ts
ADDED
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ignitor — AdonisJS-compatible application bootstrap.
|
|
3
|
+
*
|
|
4
|
+
* Usage (like AdonisJS):
|
|
5
|
+
* new Ignitor(APP_ROOT, { importer: IMPORTER })
|
|
6
|
+
* .tap((app) => {
|
|
7
|
+
* app.booting(async () => { await import('#start/env') })
|
|
8
|
+
* app.listen('SIGTERM', () => app.terminate())
|
|
9
|
+
* })
|
|
10
|
+
* .httpServer()
|
|
11
|
+
* .start()
|
|
12
|
+
*
|
|
13
|
+
* @implements FR17, FR20, FR23
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { Application } from './Application.js'
|
|
17
|
+
import type { ErrorEvent } from './ErrorBoundary.js'
|
|
18
|
+
import { ErrorBoundary } from './ErrorBoundary.js'
|
|
19
|
+
import { ReamError } from './errors/ReamError.js'
|
|
20
|
+
import type { Emitter } from './events/Emitter.js'
|
|
21
|
+
import { startHotReload } from './HotReload.js'
|
|
22
|
+
import type { HttpKernelRequest, HttpKernelResponse } from './HttpKernel.js'
|
|
23
|
+
import { createHttpKernel } from './HttpKernel.js'
|
|
24
|
+
import { ExceptionHandler } from './http/Exception.js'
|
|
25
|
+
import type { MiddlewareFunction } from './middleware/Pipeline.js'
|
|
26
|
+
import { MiddlewareRegistry } from './middleware/Pipeline.js'
|
|
27
|
+
import type { AppContext, ProviderContract } from './Provider.js'
|
|
28
|
+
import { callProviderPhase } from './Provider.js'
|
|
29
|
+
import { Router } from './router/Router.js'
|
|
30
|
+
import { Server } from './server/Server.js'
|
|
31
|
+
import { setApp } from './services/app.js'
|
|
32
|
+
import { setRouter } from './services/router.js'
|
|
33
|
+
import { setServer } from './services/server.js'
|
|
34
|
+
|
|
35
|
+
/** Application environment. */
|
|
36
|
+
export type AppEnvironment = 'web' | 'console' | 'test' | 'unknown'
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Reamrc config — like AdonisJS adonisrc.ts with defineConfig().
|
|
40
|
+
*/
|
|
41
|
+
export interface ReamrcConfig {
|
|
42
|
+
providers?: Array<
|
|
43
|
+
| (() => Promise<{ default: new (app: AppContext) => ProviderContract }>)
|
|
44
|
+
| {
|
|
45
|
+
file: () => Promise<{ default: new (app: AppContext) => ProviderContract }>
|
|
46
|
+
environment?: string[]
|
|
47
|
+
}
|
|
48
|
+
>
|
|
49
|
+
preloads?: Array<
|
|
50
|
+
| (() => Promise<unknown>)
|
|
51
|
+
| {
|
|
52
|
+
file: () => Promise<unknown>
|
|
53
|
+
environment?: string[]
|
|
54
|
+
}
|
|
55
|
+
>
|
|
56
|
+
commands?: Array<() => Promise<unknown>>
|
|
57
|
+
modules?: {
|
|
58
|
+
/** Path to the modules directory (relative to app root). Default: './app/modules' */
|
|
59
|
+
path?: string
|
|
60
|
+
/** Auto-loaded files in each module directory. Default: ['routes'] */
|
|
61
|
+
autoload?: string[]
|
|
62
|
+
}
|
|
63
|
+
tests?: {
|
|
64
|
+
suites?: Array<{ name: string; files: string[]; timeout?: number }>
|
|
65
|
+
forceExit?: boolean
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** defineConfig helper — like AdonisJS defineConfig(). */
|
|
70
|
+
export function defineConfig(config: ReamrcConfig): ReamrcConfig {
|
|
71
|
+
return config
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Minimal interface for the HTTP server (NAPI or mock). */
|
|
75
|
+
export interface HyperServerLike {
|
|
76
|
+
onRequest(callback: (request: HttpKernelRequest) => Promise<HttpKernelResponse>): void
|
|
77
|
+
/**
|
|
78
|
+
* Optional — present on the real `HyperServer` (Rust-backed), absent on
|
|
79
|
+
* trivial test mocks. Ignitor only calls it when a shield config is set.
|
|
80
|
+
*/
|
|
81
|
+
configureShield?(config: { pathTraversal: boolean; paramPollution: boolean }): void
|
|
82
|
+
/** Optional — same lifecycle as `configureShield`. */
|
|
83
|
+
configureTrustedProxies?(cidrs: string[]): void
|
|
84
|
+
/** Optional — same lifecycle as `configureShield`. */
|
|
85
|
+
configureRateLimit?(config: { max: number; windowSecs: number } | null): void
|
|
86
|
+
listen(): Promise<void>
|
|
87
|
+
port(): Promise<number>
|
|
88
|
+
close(): Promise<void>
|
|
89
|
+
// Streaming primitives — optional so mock servers (no NAPI) opt out
|
|
90
|
+
// by simply not implementing them; the `response.sse()` helper throws
|
|
91
|
+
// a clean `STREAMING_UNSUPPORTED` error when called on such a host.
|
|
92
|
+
registerStream?(streamId: string): Promise<boolean>
|
|
93
|
+
writeStream?(streamId: string, chunk: string): Promise<boolean>
|
|
94
|
+
closeStream?(streamId: string): Promise<boolean>
|
|
95
|
+
onStreamDisconnect?(streamId: string, callback: () => void): void
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface IgnitorConfig {
|
|
99
|
+
port?: number
|
|
100
|
+
serverFactory?: (port: number) => HyperServerLike
|
|
101
|
+
importer?: (filePath: string) => Promise<unknown>
|
|
102
|
+
watchDirs?: string[]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Ignitor — boots and wires the Ream framework.
|
|
107
|
+
*
|
|
108
|
+
* Lifecycle: register → boot → start → ready → shutdown
|
|
109
|
+
*/
|
|
110
|
+
export class Ignitor {
|
|
111
|
+
private app: Application
|
|
112
|
+
private router: Router
|
|
113
|
+
private server: Server
|
|
114
|
+
private middleware: MiddlewareRegistry
|
|
115
|
+
private errorBoundary: ErrorBoundary
|
|
116
|
+
private _httpServer?: HyperServerLike
|
|
117
|
+
private config: IgnitorConfig
|
|
118
|
+
private appRoot?: URL
|
|
119
|
+
private environment: AppEnvironment = 'unknown'
|
|
120
|
+
private reamrc?: ReamrcConfig
|
|
121
|
+
private providers: ProviderContract[] = []
|
|
122
|
+
private errorListeners: Array<(event: ErrorEvent) => void> = []
|
|
123
|
+
private phase: 'created' | 'registered' | 'booted' | 'started' | 'ready' | 'shutdown' = 'created'
|
|
124
|
+
private hotReloadCleanup?: () => void
|
|
125
|
+
|
|
126
|
+
// Inline configuration (for simple use or testing)
|
|
127
|
+
private inlineRoutes?: (router: Router) => void
|
|
128
|
+
private inlineMiddleware: MiddlewareFunction[] = []
|
|
129
|
+
private inlineNamedMiddleware: Array<[string, MiddlewareFunction]> = []
|
|
130
|
+
private inlineProviderFactories: Array<(app: Application) => ProviderContract> = []
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Create the Ignitor.
|
|
134
|
+
*
|
|
135
|
+
* AdonisJS-style:
|
|
136
|
+
* new Ignitor(APP_ROOT, { importer: IMPORTER })
|
|
137
|
+
*
|
|
138
|
+
* Simple-style:
|
|
139
|
+
* new Ignitor({ port: 3000, serverFactory: ... })
|
|
140
|
+
*/
|
|
141
|
+
constructor(appRootOrConfig?: URL | IgnitorConfig, config?: IgnitorConfig) {
|
|
142
|
+
if (appRootOrConfig instanceof URL) {
|
|
143
|
+
this.appRoot = appRootOrConfig
|
|
144
|
+
this.config = config ?? {}
|
|
145
|
+
} else {
|
|
146
|
+
this.config = appRootOrConfig ?? {}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
this.app = new Application()
|
|
150
|
+
this.router = new Router()
|
|
151
|
+
this.server = new Server(this.router)
|
|
152
|
+
this.middleware = new MiddlewareRegistry()
|
|
153
|
+
this.errorBoundary = new ErrorBoundary((event) => this.handleError(event), this.isDevMode())
|
|
154
|
+
|
|
155
|
+
// Register framework services in container
|
|
156
|
+
this.app.container.singleton('router', () => this.router)
|
|
157
|
+
this.app.container.singleton('server', () => this.server)
|
|
158
|
+
this.app.container.singleton('middleware', () => this.middleware)
|
|
159
|
+
this.app.container.singleton('app', () => this.app)
|
|
160
|
+
// `appRoot` is the URL passed to `new Ignitor(new URL('../', import.meta.url))`.
|
|
161
|
+
// Providers resolve it through the container so they can interpret
|
|
162
|
+
// relative paths in config files (e.g. `pages.root: './resources/pages'`)
|
|
163
|
+
// against the project root — same convention `modules.path` uses.
|
|
164
|
+
if (this.appRoot) {
|
|
165
|
+
const root = this.appRoot
|
|
166
|
+
this.app.container.singleton('appRoot', () => root)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Set service singletons so route/kernel files can import them
|
|
170
|
+
setApp(this.app)
|
|
171
|
+
setRouter(this.router)
|
|
172
|
+
setServer(this.server)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ─── Configuration ────────────────────────────────────────
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Access the Application instance before start.
|
|
179
|
+
* Like AdonisJS: .tap((app) => { app.booting(...) })
|
|
180
|
+
*/
|
|
181
|
+
tap(callback: (app: Application) => void): this {
|
|
182
|
+
callback(this.app)
|
|
183
|
+
return this
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Set the application environment. */
|
|
187
|
+
setEnvironment(env: AppEnvironment): this {
|
|
188
|
+
this.environment = env
|
|
189
|
+
return this
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
getEnvironment(): AppEnvironment {
|
|
193
|
+
return this.environment
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Load the reamrc config (equivalent to adonisrc.ts).
|
|
198
|
+
*/
|
|
199
|
+
useRcFile(reamrc: ReamrcConfig): this {
|
|
200
|
+
this.reamrc = reamrc
|
|
201
|
+
return this
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// === Inline configuration (simple mode / testing) ===
|
|
205
|
+
|
|
206
|
+
/** Define routes inline (simple mode). */
|
|
207
|
+
routes(callback: (router: Router) => void): this {
|
|
208
|
+
this.inlineRoutes = callback
|
|
209
|
+
return this
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Add global middleware inline. */
|
|
213
|
+
use(mw: MiddlewareFunction): this {
|
|
214
|
+
this.inlineMiddleware.push(mw)
|
|
215
|
+
return this
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** Register a named middleware inline. */
|
|
219
|
+
named(name: string, mw: MiddlewareFunction): this {
|
|
220
|
+
this.inlineNamedMiddleware.push([name, mw])
|
|
221
|
+
return this
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Register a provider inline (for testing or simple apps). */
|
|
225
|
+
provider(factory: (app: Application) => ProviderContract): this {
|
|
226
|
+
this.inlineProviderFactories.push(factory)
|
|
227
|
+
return this
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** Listen for error events. */
|
|
231
|
+
onError(listener: (event: ErrorEvent) => void): this {
|
|
232
|
+
this.errorListeners.push(listener)
|
|
233
|
+
return this
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** Set a config value. */
|
|
237
|
+
configure(key: string, value: unknown): this {
|
|
238
|
+
this.app.config.set(key, value)
|
|
239
|
+
return this
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ─── Mode selection ───────────────────────────────────────
|
|
243
|
+
|
|
244
|
+
/** Configure for HTTP server mode. */
|
|
245
|
+
httpServer(): this {
|
|
246
|
+
this.environment = 'web'
|
|
247
|
+
return this
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** Configure for CLI/console mode. Returns a ConsoleKernel for dispatching commands. */
|
|
251
|
+
console(): ConsoleKernel {
|
|
252
|
+
this.environment = 'console'
|
|
253
|
+
return new ConsoleKernel(this)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/** Configure for test mode. */
|
|
257
|
+
testMode(): this {
|
|
258
|
+
this.environment = 'test'
|
|
259
|
+
return this
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// ─── Lifecycle ────────────────────────────────────────────
|
|
263
|
+
|
|
264
|
+
async start(): Promise<Ignitor> {
|
|
265
|
+
await this.phaseRegister()
|
|
266
|
+
await this.phaseBoot()
|
|
267
|
+
await this.phaseStart()
|
|
268
|
+
await this.phaseReady()
|
|
269
|
+
return this
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
private async phaseRegister(): Promise<void> {
|
|
273
|
+
// Auto-load config/*.ts files into app.config
|
|
274
|
+
await this.autoloadConfig()
|
|
275
|
+
|
|
276
|
+
// Load providers from reamrc
|
|
277
|
+
if (this.reamrc?.providers) {
|
|
278
|
+
for (const providerEntry of this.reamrc.providers) {
|
|
279
|
+
const providerImport =
|
|
280
|
+
typeof providerEntry === 'function' ? providerEntry : providerEntry.file
|
|
281
|
+
const env = typeof providerEntry === 'function' ? undefined : providerEntry.environment
|
|
282
|
+
|
|
283
|
+
// Skip providers not matching current environment
|
|
284
|
+
if (env && !env.includes(this.environment)) continue
|
|
285
|
+
|
|
286
|
+
const mod = await providerImport()
|
|
287
|
+
const ProviderClass = mod.default
|
|
288
|
+
const instance = new ProviderClass(this.app)
|
|
289
|
+
this.providers.push(instance)
|
|
290
|
+
this.app.register(instance)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Register inline providers
|
|
295
|
+
for (const factory of this.inlineProviderFactories) {
|
|
296
|
+
const instance = factory(this.app)
|
|
297
|
+
this.providers.push(instance)
|
|
298
|
+
this.app.register(instance)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
this.phase = 'registered'
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
private async phaseBoot(): Promise<void> {
|
|
305
|
+
await this.app.boot()
|
|
306
|
+
this.phase = 'booted'
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private async phaseStart(): Promise<void> {
|
|
310
|
+
// Import preload files (routes.ts, kernel.ts, etc.)
|
|
311
|
+
if (this.reamrc?.preloads) {
|
|
312
|
+
for (const preloadEntry of this.reamrc.preloads) {
|
|
313
|
+
const preloadImport = typeof preloadEntry === 'function' ? preloadEntry : preloadEntry.file
|
|
314
|
+
const env =
|
|
315
|
+
typeof preloadEntry === 'function'
|
|
316
|
+
? undefined
|
|
317
|
+
: (preloadEntry as { environment?: string[] }).environment
|
|
318
|
+
|
|
319
|
+
if (env && !env.includes(this.environment)) continue
|
|
320
|
+
await preloadImport()
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Auto-load module files (routes.ts, etc.) from modules directory
|
|
325
|
+
await this.autoloadModules()
|
|
326
|
+
|
|
327
|
+
// Apply inline configuration
|
|
328
|
+
for (const mw of this.inlineMiddleware) {
|
|
329
|
+
this.middleware.use(mw)
|
|
330
|
+
}
|
|
331
|
+
for (const [name, mw] of this.inlineNamedMiddleware) {
|
|
332
|
+
this.middleware.register(name, mw)
|
|
333
|
+
}
|
|
334
|
+
if (this.inlineRoutes) {
|
|
335
|
+
this.inlineRoutes(this.router)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Call start() on providers
|
|
339
|
+
for (const provider of this.providers) {
|
|
340
|
+
await callProviderPhase(provider, 'start')
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
this.phase = 'started'
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
private async phaseReady(): Promise<void> {
|
|
347
|
+
// Boot the Server (resolves lazy error handler etc.)
|
|
348
|
+
await this.server.boot()
|
|
349
|
+
|
|
350
|
+
// Start HTTP server if in web mode
|
|
351
|
+
if (this.environment === 'web' && this.config.serverFactory) {
|
|
352
|
+
// Build the HttpKernel with server middleware + router middleware.
|
|
353
|
+
// The streaming backend is resolved lazily — the HyperServer is
|
|
354
|
+
// created a few lines down, after the kernel — so the kernel
|
|
355
|
+
// closes over the `this._httpServer` slot and reads it on every
|
|
356
|
+
// request through the factory.
|
|
357
|
+
const kernel = createHttpKernel({
|
|
358
|
+
router: this.router,
|
|
359
|
+
middleware: this.middleware,
|
|
360
|
+
container: this.app.container,
|
|
361
|
+
exceptionHandler:
|
|
362
|
+
this.server.getErrorHandler() ?? new ExceptionHandler(!this.app.inProduction),
|
|
363
|
+
serverMiddleware: this.server.getServerMiddleware(),
|
|
364
|
+
routerMiddleware: this.router.getRouterMiddleware(),
|
|
365
|
+
onError: (error, ctx) => {
|
|
366
|
+
this.errorBoundary.serviceError('HttpKernel', error, ctx.id)
|
|
367
|
+
},
|
|
368
|
+
streamBackend: () => {
|
|
369
|
+
const server = this._httpServer
|
|
370
|
+
if (
|
|
371
|
+
server &&
|
|
372
|
+
typeof server.registerStream === 'function' &&
|
|
373
|
+
typeof server.writeStream === 'function' &&
|
|
374
|
+
typeof server.closeStream === 'function' &&
|
|
375
|
+
typeof server.onStreamDisconnect === 'function'
|
|
376
|
+
) {
|
|
377
|
+
// Narrow to a backend-shaped record. All four methods are
|
|
378
|
+
// present at this point — the check above guards mocked
|
|
379
|
+
// servers without forcing a structural cast.
|
|
380
|
+
return {
|
|
381
|
+
registerStream: server.registerStream.bind(server),
|
|
382
|
+
writeStream: server.writeStream.bind(server),
|
|
383
|
+
closeStream: server.closeStream.bind(server),
|
|
384
|
+
onStreamDisconnect: server.onStreamDisconnect.bind(server),
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return undefined
|
|
388
|
+
},
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
const desiredPort = this.config.port ?? 3000
|
|
392
|
+
const availablePort = await findAvailablePort(desiredPort)
|
|
393
|
+
this._httpServer = this.config.serverFactory(availablePort)
|
|
394
|
+
this._httpServer.onRequest(kernel)
|
|
395
|
+
// Pre-resolve client IPs in Rust from the trusted-proxy CIDRs before
|
|
396
|
+
// listen. Security filtering itself lives in @c9up/blackhole.
|
|
397
|
+
const trustedProxies = this.server.getTrustedProxies()
|
|
398
|
+
if (
|
|
399
|
+
trustedProxies.length > 0 &&
|
|
400
|
+
typeof this._httpServer.configureTrustedProxies === 'function'
|
|
401
|
+
) {
|
|
402
|
+
this._httpServer.configureTrustedProxies([...trustedProxies])
|
|
403
|
+
}
|
|
404
|
+
await this._httpServer.listen()
|
|
405
|
+
} else if (this.environment === 'web' && !this.config.serverFactory) {
|
|
406
|
+
throw new ReamError(
|
|
407
|
+
'IGNITOR_NO_SERVER_FACTORY',
|
|
408
|
+
'httpServer() requires a serverFactory in config',
|
|
409
|
+
{
|
|
410
|
+
hint: 'Example: new Ignitor({ serverFactory: (port) => new HyperServer(port) })',
|
|
411
|
+
},
|
|
412
|
+
)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Install error boundary
|
|
416
|
+
this.errorBoundary.install()
|
|
417
|
+
|
|
418
|
+
// Call ready() on providers
|
|
419
|
+
for (const provider of this.providers) {
|
|
420
|
+
await callProviderPhase(provider, 'ready')
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// Core domain event: the app finished booting (all providers ready).
|
|
424
|
+
// Emitted once through the bus when events are wired — zero hot-path cost.
|
|
425
|
+
if (this.app.container.has('events')) {
|
|
426
|
+
this.app.container
|
|
427
|
+
.resolve<Emitter>('events')
|
|
428
|
+
.emit('app:ready', { environment: this.environment })
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Hot-reload in dev mode
|
|
432
|
+
if (this.isDevMode()) {
|
|
433
|
+
const watchDirs = this.config.watchDirs ?? ['app', 'start']
|
|
434
|
+
this.hotReloadCleanup = startHotReload({
|
|
435
|
+
watchDirs,
|
|
436
|
+
onReload: async () => {
|
|
437
|
+
const { clearServiceRegistry } = await import('./decorators/Service.js')
|
|
438
|
+
clearServiceRegistry()
|
|
439
|
+
this.router.clear()
|
|
440
|
+
if (this.inlineRoutes) this.inlineRoutes(this.router)
|
|
441
|
+
if (this.reamrc?.preloads) {
|
|
442
|
+
for (const preloadEntry of this.reamrc.preloads) {
|
|
443
|
+
const preloadImport =
|
|
444
|
+
typeof preloadEntry === 'function' ? preloadEntry : preloadEntry.file
|
|
445
|
+
await preloadImport()
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
},
|
|
449
|
+
logger: {
|
|
450
|
+
info: (msg) =>
|
|
451
|
+
this.handleError({
|
|
452
|
+
type: 'system.info',
|
|
453
|
+
source: 'HotReload',
|
|
454
|
+
message: msg,
|
|
455
|
+
severity: 'info',
|
|
456
|
+
timestamp: new Date().toISOString(),
|
|
457
|
+
} as ErrorEvent),
|
|
458
|
+
},
|
|
459
|
+
})
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
this.phase = 'ready'
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Auto-load config/*.ts files into app.config store.
|
|
467
|
+
* Each file's default export is stored under its filename (without extension).
|
|
468
|
+
* e.g. config/database.ts → app.config.get('database')
|
|
469
|
+
*/
|
|
470
|
+
private async autoloadConfig(): Promise<void> {
|
|
471
|
+
const { readdirSync, existsSync } = await import('node:fs')
|
|
472
|
+
const { join, basename } = await import('node:path')
|
|
473
|
+
const { fileURLToPath, pathToFileURL } = await import('node:url')
|
|
474
|
+
|
|
475
|
+
const configDir = this.appRoot
|
|
476
|
+
? join(fileURLToPath(this.appRoot), 'config')
|
|
477
|
+
: join(process.cwd(), 'config')
|
|
478
|
+
|
|
479
|
+
if (!existsSync(configDir)) return
|
|
480
|
+
|
|
481
|
+
const files = readdirSync(configDir)
|
|
482
|
+
.filter((f: string) => (f.endsWith('.ts') || f.endsWith('.js')) && !f.startsWith('.'))
|
|
483
|
+
.sort()
|
|
484
|
+
|
|
485
|
+
for (const file of files) {
|
|
486
|
+
const key = basename(file).replace(/\.(ts|js)$/, '')
|
|
487
|
+
const mod = await import(pathToFileURL(join(configDir, file)).href)
|
|
488
|
+
this.app.config.set(key, mod.default ?? mod)
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Auto-load module files (routes.ts, etc.) from the modules directory.
|
|
494
|
+
* Scans modules.path for subdirectories and imports matching files.
|
|
495
|
+
*/
|
|
496
|
+
private async autoloadModules(): Promise<void> {
|
|
497
|
+
const modulesConfig = this.reamrc?.modules
|
|
498
|
+
if (!modulesConfig?.path) return
|
|
499
|
+
|
|
500
|
+
const { readdirSync, existsSync } = await import('node:fs')
|
|
501
|
+
const { join, resolve } = await import('node:path')
|
|
502
|
+
const { fileURLToPath } = await import('node:url')
|
|
503
|
+
const { pathToFileURL } = await import('node:url')
|
|
504
|
+
|
|
505
|
+
// Resolve modules path relative to app root or cwd
|
|
506
|
+
const basePath = this.appRoot
|
|
507
|
+
? join(fileURLToPath(this.appRoot), modulesConfig.path)
|
|
508
|
+
: resolve(modulesConfig.path)
|
|
509
|
+
|
|
510
|
+
if (!existsSync(basePath)) return
|
|
511
|
+
|
|
512
|
+
const autoloadFiles = modulesConfig.autoload ?? ['routes', 'events']
|
|
513
|
+
const moduleDirs = readdirSync(basePath, { withFileTypes: true })
|
|
514
|
+
.filter((d) => d.isDirectory())
|
|
515
|
+
.map((d) => d.name)
|
|
516
|
+
.sort()
|
|
517
|
+
|
|
518
|
+
for (const moduleDir of moduleDirs) {
|
|
519
|
+
for (const fileName of autoloadFiles) {
|
|
520
|
+
const tsPath = join(basePath, moduleDir, `${fileName}.ts`)
|
|
521
|
+
const jsPath = join(basePath, moduleDir, `${fileName}.js`)
|
|
522
|
+
const filePath = existsSync(tsPath) ? tsPath : existsSync(jsPath) ? jsPath : null
|
|
523
|
+
if (filePath) {
|
|
524
|
+
await import(pathToFileURL(filePath).href)
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/** Graceful shutdown. */
|
|
531
|
+
async stop(): Promise<void> {
|
|
532
|
+
if (this.hotReloadCleanup) this.hotReloadCleanup()
|
|
533
|
+
if (this._httpServer) await this._httpServer.close()
|
|
534
|
+
this.errorBoundary.uninstall()
|
|
535
|
+
await this.app.shutdown()
|
|
536
|
+
this.phase = 'shutdown'
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// ─── Accessors ────────────────────────────────────────────
|
|
540
|
+
|
|
541
|
+
async port(): Promise<number> {
|
|
542
|
+
return this._httpServer ? this._httpServer.port() : 0
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
getApp(): Application {
|
|
546
|
+
return this.app
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
getRouter(): Router {
|
|
550
|
+
return this.router
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
getServer(): Server {
|
|
554
|
+
return this.server
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/** Get the kernel callback (for serverless / testing). */
|
|
558
|
+
getKernel(): (request: HttpKernelRequest) => Promise<HttpKernelResponse> {
|
|
559
|
+
return createHttpKernel({
|
|
560
|
+
router: this.router,
|
|
561
|
+
middleware: this.middleware,
|
|
562
|
+
container: this.app.container,
|
|
563
|
+
exceptionHandler:
|
|
564
|
+
this.server.getErrorHandler() ?? new ExceptionHandler(!this.app.inProduction),
|
|
565
|
+
serverMiddleware: this.server.getServerMiddleware(),
|
|
566
|
+
routerMiddleware: this.router.getRouterMiddleware(),
|
|
567
|
+
})
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
isDevMode(): boolean {
|
|
571
|
+
return this.app.inDev
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
getPhase(): string {
|
|
575
|
+
return this.phase
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
private handleError(event: ErrorEvent): void {
|
|
579
|
+
for (const listener of this.errorListeners) {
|
|
580
|
+
try {
|
|
581
|
+
listener(event)
|
|
582
|
+
} catch {
|
|
583
|
+
/* Don't let listeners crash */
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* Pretty-print an error (like AdonisJS prettyPrintError).
|
|
591
|
+
*/
|
|
592
|
+
export function prettyPrintError(error: unknown): void {
|
|
593
|
+
if (error instanceof ReamError) {
|
|
594
|
+
console.error(error.toDevString())
|
|
595
|
+
} else if (error instanceof Error) {
|
|
596
|
+
console.error(`\n ${error.message}\n`)
|
|
597
|
+
if (error.stack) console.error(error.stack)
|
|
598
|
+
} else {
|
|
599
|
+
console.error(error)
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* ConsoleKernel — handles CLI command dispatching.
|
|
605
|
+
* Like AdonisJS: new Ignitor(...).console().handle(process.argv.splice(2))
|
|
606
|
+
*/
|
|
607
|
+
export class ConsoleKernel {
|
|
608
|
+
private ignitor: Ignitor
|
|
609
|
+
|
|
610
|
+
constructor(ignitor: Ignitor) {
|
|
611
|
+
this.ignitor = ignitor
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
async handle(argv: string[]): Promise<void> {
|
|
615
|
+
await this.ignitor.start()
|
|
616
|
+
const { CommandRunner } = await import('./console/CommandRunner.js')
|
|
617
|
+
const runner = new CommandRunner()
|
|
618
|
+
|
|
619
|
+
// Auto-register commands from reamrc
|
|
620
|
+
const reamrc = (this.ignitor as unknown as { reamrc?: ReamrcConfig }).reamrc
|
|
621
|
+
if (reamrc?.commands) {
|
|
622
|
+
for (const commandImport of reamrc.commands) {
|
|
623
|
+
const mod = await commandImport()
|
|
624
|
+
const cmd = (
|
|
625
|
+
mod as {
|
|
626
|
+
default: {
|
|
627
|
+
name: string
|
|
628
|
+
description: string
|
|
629
|
+
run: (args: string[], flags: Record<string, string | boolean>) => Promise<void>
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
).default
|
|
633
|
+
if (cmd?.name && typeof cmd?.run === 'function') {
|
|
634
|
+
runner.register(cmd)
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
this.ignitor.getApp().container.singleton('console', () => runner)
|
|
640
|
+
await runner.handle(argv)
|
|
641
|
+
await this.ignitor.stop()
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
async function findAvailablePort(desired: number): Promise<number> {
|
|
646
|
+
const net = await import('node:net')
|
|
647
|
+
for (let port = desired; port < desired + 20; port++) {
|
|
648
|
+
const available = await new Promise<boolean>((resolve) => {
|
|
649
|
+
const server = net.createServer()
|
|
650
|
+
server.listen(port, () => server.close(() => resolve(true)))
|
|
651
|
+
server.on('error', () => resolve(false))
|
|
652
|
+
})
|
|
653
|
+
if (available) return port
|
|
654
|
+
}
|
|
655
|
+
return desired
|
|
656
|
+
}
|