@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/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 C9up
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @c9up/ream
|
|
2
|
+
|
|
3
|
+
Rust-powered Node.js application framework. Convention over configuration with native performance.
|
|
4
|
+
|
|
5
|
+
`@c9up/ream` ships as a single package containing both the TypeScript framework and prebuilt Rust (NAPI) binaries — consumers never compile anything.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **IoC Container** — `@Service()`, `@Inject()`, auto-resolution, scopes
|
|
10
|
+
- **Lifecycle** — register → boot → start → ready → shutdown
|
|
11
|
+
- **Router** — fluent chaining, groups, params, guards, versioning
|
|
12
|
+
- **Middleware pipeline** — onion pattern, global + named, guard enforcement
|
|
13
|
+
- **HTTP server** — Rust Hyper via NAPI
|
|
14
|
+
- **Event bus** — in-process emitter with optional Redis store (`@c9up/ream/events`)
|
|
15
|
+
- **Scheduler** — cron/interval tasks via the `@Schedule()` decorator (Rust-backed)
|
|
16
|
+
- **GraphQL & RPC** — built-in GraphQL engine and typed RPC router
|
|
17
|
+
- **Security primitives** — signed cookies, HMAC, signed URLs, trusted-proxy config (request-filter security — XSS / CSRF / rate-limiting — lives in [@c9up/blackhole](https://github.com/C9up/blackhole))
|
|
18
|
+
- **Error DX** — structured errors, fuzzy matching, pipeline stage context
|
|
19
|
+
- **Health check** — Kubernetes-compatible `/health` endpoint
|
|
20
|
+
- **Graceful shutdown** — SIGTERM/SIGINT with drain timeout
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { Ignitor } from '@c9up/ream'
|
|
26
|
+
|
|
27
|
+
const app = new Ignitor({ port: 3000 })
|
|
28
|
+
.httpServer()
|
|
29
|
+
.routes((router) => {
|
|
30
|
+
router.get('/hello/:name', async ({ params, response }) => {
|
|
31
|
+
response.status(200).send(`Hello, ${params.name}!`)
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
await app.start()
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Ecosystem
|
|
39
|
+
|
|
40
|
+
Every package is standalone and publishable on its own; they consume the Ream
|
|
41
|
+
universe through the container, never via a static import.
|
|
42
|
+
|
|
43
|
+
| Package | Description |
|
|
44
|
+
|---------|-------------|
|
|
45
|
+
| [@c9up/atlas](https://github.com/C9up/atlas) | Data Mapper ORM |
|
|
46
|
+
| [@c9up/rune](https://github.com/C9up/rune) | Validation engine |
|
|
47
|
+
| [@c9up/warden](https://github.com/C9up/warden) | Authentication |
|
|
48
|
+
| [@c9up/sigil](https://github.com/C9up/sigil) | Password hashing (argon2, bcrypt, scrypt) |
|
|
49
|
+
| [@c9up/blackhole](https://github.com/C9up/blackhole) | Security filter — XSS, CSRF, rate-limiting (Rust-native) |
|
|
50
|
+
| [@c9up/spectrum](https://github.com/C9up/spectrum) | Structured logging |
|
|
51
|
+
| [@c9up/rosetta](https://github.com/C9up/rosetta) | Internationalization (i18n) |
|
|
52
|
+
| [@c9up/chronos](https://github.com/C9up/chronos) | Date/time & recurrence engine |
|
|
53
|
+
| [@c9up/atom](https://github.com/C9up/atom) | Exact decimal arithmetic |
|
|
54
|
+
| [@c9up/bay](https://github.com/C9up/bay) | Job queue (memory + Redis drivers) |
|
|
55
|
+
| [@c9up/echo](https://github.com/C9up/echo) | Cache (memory + Redis drivers) |
|
|
56
|
+
| [@c9up/archive](https://github.com/C9up/archive) | File storage (Local + S3-compatible) |
|
|
57
|
+
| [@c9up/rover](https://github.com/C9up/rover) | Mail transport (SMTP, log, pluggable) |
|
|
58
|
+
| [@c9up/nova](https://github.com/C9up/nova) | Web Push notifications (VAPID) |
|
|
59
|
+
| [@c9up/relay](https://github.com/C9up/relay) | Realtime transport (SSE + WebSocket) |
|
|
60
|
+
| [@c9up/aurora](https://github.com/C9up/aurora) | Reactive UI runtime (SSR + hydration) |
|
|
61
|
+
| [@c9up/photon](https://github.com/C9up/photon) | Frontend rendering engine |
|
|
62
|
+
| [@c9up/inker](https://github.com/C9up/inker) | Server-side templating |
|
|
63
|
+
| [@c9up/station](https://github.com/C9up/station) | Admin scaffolding |
|
|
64
|
+
| [@c9up/helix](https://github.com/C9up/helix) | Framework-agnostic test runtime |
|
|
65
|
+
| [@c9up/ream-cli](https://github.com/C9up/ream-cli) | CLI & code generators (Rust binary, `ream` command) |
|
|
66
|
+
| [@c9up/ream-mcp](https://github.com/C9up/ream-mcp) | MCP server — agent-ready framework assistant |
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
MIT
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application — manages providers, config, lifecycle, and signal handling.
|
|
3
|
+
*
|
|
4
|
+
* Like AdonisJS Application:
|
|
5
|
+
* - app.booting(callback) — register hooks that run during boot
|
|
6
|
+
* - app.booted(callback) — register hooks that run after boot completes
|
|
7
|
+
* - app.listen(signal, callback) — listen for process signals
|
|
8
|
+
* - app.listenIf(condition, signal, callback) — conditional signal listener
|
|
9
|
+
* - app.terminate() — graceful shutdown
|
|
10
|
+
* - app.managedByPm2 — PM2 detection
|
|
11
|
+
* - app.inProduction / app.inDev / app.inTest
|
|
12
|
+
*
|
|
13
|
+
* @implements FR17, FR20
|
|
14
|
+
*/
|
|
15
|
+
import { ConfigStore } from './ConfigLoader.js';
|
|
16
|
+
import { Container } from './container/Container.js';
|
|
17
|
+
import type { AppContext, ProviderContract } from './Provider.js';
|
|
18
|
+
export declare class Application implements AppContext {
|
|
19
|
+
readonly container: Container;
|
|
20
|
+
readonly config: ConfigStore;
|
|
21
|
+
private providers;
|
|
22
|
+
private _booted;
|
|
23
|
+
private _bootingHooks;
|
|
24
|
+
private _bootedHooks;
|
|
25
|
+
private _shutdownHooks;
|
|
26
|
+
constructor();
|
|
27
|
+
/** Check if running in production. */
|
|
28
|
+
get inProduction(): boolean;
|
|
29
|
+
/** Check if running in development. */
|
|
30
|
+
get inDev(): boolean;
|
|
31
|
+
/** Check if running in test mode. */
|
|
32
|
+
get inTest(): boolean;
|
|
33
|
+
/** Check if managed by PM2. */
|
|
34
|
+
get managedByPm2(): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Register a callback that runs during the boot phase (before providers boot).
|
|
37
|
+
* Like AdonisJS app.booting().
|
|
38
|
+
*/
|
|
39
|
+
booting(callback: () => Promise<void> | void): void;
|
|
40
|
+
/**
|
|
41
|
+
* Register a callback that runs after boot completes.
|
|
42
|
+
* Like AdonisJS app.booted().
|
|
43
|
+
*/
|
|
44
|
+
booted(callback: () => Promise<void> | void): void;
|
|
45
|
+
/**
|
|
46
|
+
* Listen for a process signal.
|
|
47
|
+
* Like AdonisJS app.listen('SIGTERM', () => app.terminate()).
|
|
48
|
+
*/
|
|
49
|
+
listen(signal: NodeJS.Signals, callback: () => void): void;
|
|
50
|
+
/**
|
|
51
|
+
* Conditionally listen for a process signal.
|
|
52
|
+
* Like AdonisJS app.listenIf(app.managedByPm2, 'SIGINT', ...).
|
|
53
|
+
*/
|
|
54
|
+
listenIf(condition: boolean, signal: NodeJS.Signals, callback: () => void): void;
|
|
55
|
+
/**
|
|
56
|
+
* Graceful shutdown — stop all providers and exit.
|
|
57
|
+
* Like AdonisJS app.terminate().
|
|
58
|
+
*/
|
|
59
|
+
terminate(): Promise<void>;
|
|
60
|
+
/** Register a provider instance. */
|
|
61
|
+
register(provider: ProviderContract): void;
|
|
62
|
+
/** Boot all registered providers. Runs booting/booted hooks. */
|
|
63
|
+
boot(): Promise<void>;
|
|
64
|
+
/** Shutdown all providers in reverse order. */
|
|
65
|
+
shutdown(): Promise<void>;
|
|
66
|
+
/** Register a shutdown hook. */
|
|
67
|
+
onShutdown(callback: () => Promise<void> | void): void;
|
|
68
|
+
get isBooted(): boolean;
|
|
69
|
+
get providerCount(): number;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=Application.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Application.d.ts","sourceRoot":"","sources":["../src/Application.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAGjE,qBAAa,WAAY,YAAW,UAAU;IAC5C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,aAAa,CAAwC;IAC7D,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,cAAc,CAAwC;;IAS9D,sCAAsC;IACtC,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,uCAAuC;IACvC,IAAI,KAAK,IAAI,OAAO,CAGnB;IAED,qCAAqC;IACrC,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,+BAA+B;IAC/B,IAAI,YAAY,IAAI,OAAO,CAE1B;IAID;;;OAGG;IACH,OAAO,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAInD;;;OAGG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAmBlD;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAI1D;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IAMhF;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAOhC,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAO1C,gEAAgE;IAC1D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB3B,+CAA+C;IACzC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAY/B,gCAAgC;IAChC,UAAU,CAAC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI;IAItD,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,IAAI,aAAa,IAAI,MAAM,CAE1B;CACF"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application — manages providers, config, lifecycle, and signal handling.
|
|
3
|
+
*
|
|
4
|
+
* Like AdonisJS Application:
|
|
5
|
+
* - app.booting(callback) — register hooks that run during boot
|
|
6
|
+
* - app.booted(callback) — register hooks that run after boot completes
|
|
7
|
+
* - app.listen(signal, callback) — listen for process signals
|
|
8
|
+
* - app.listenIf(condition, signal, callback) — conditional signal listener
|
|
9
|
+
* - app.terminate() — graceful shutdown
|
|
10
|
+
* - app.managedByPm2 — PM2 detection
|
|
11
|
+
* - app.inProduction / app.inDev / app.inTest
|
|
12
|
+
*
|
|
13
|
+
* @implements FR17, FR20
|
|
14
|
+
*/
|
|
15
|
+
import { ConfigStore } from './ConfigLoader.js';
|
|
16
|
+
import { Container } from './container/Container.js';
|
|
17
|
+
import { callProviderPhase } from './Provider.js';
|
|
18
|
+
export class Application {
|
|
19
|
+
container;
|
|
20
|
+
config;
|
|
21
|
+
providers = [];
|
|
22
|
+
_booted = false;
|
|
23
|
+
_bootingHooks = [];
|
|
24
|
+
_bootedHooks = [];
|
|
25
|
+
_shutdownHooks = [];
|
|
26
|
+
constructor() {
|
|
27
|
+
this.container = new Container();
|
|
28
|
+
this.config = new ConfigStore();
|
|
29
|
+
}
|
|
30
|
+
// ─── Environment ──────────────────────────────────────────
|
|
31
|
+
/** Check if running in production. */
|
|
32
|
+
get inProduction() {
|
|
33
|
+
return process.env.NODE_ENV === 'production';
|
|
34
|
+
}
|
|
35
|
+
/** Check if running in development. */
|
|
36
|
+
get inDev() {
|
|
37
|
+
const env = process.env.NODE_ENV;
|
|
38
|
+
return env !== 'production' && env !== 'test';
|
|
39
|
+
}
|
|
40
|
+
/** Check if running in test mode. */
|
|
41
|
+
get inTest() {
|
|
42
|
+
return process.env.NODE_ENV === 'test';
|
|
43
|
+
}
|
|
44
|
+
/** Check if managed by PM2. */
|
|
45
|
+
get managedByPm2() {
|
|
46
|
+
return 'PM2_HOME' in process.env || 'pm_id' in process.env;
|
|
47
|
+
}
|
|
48
|
+
// ─── Lifecycle hooks ──────────────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* Register a callback that runs during the boot phase (before providers boot).
|
|
51
|
+
* Like AdonisJS app.booting().
|
|
52
|
+
*/
|
|
53
|
+
booting(callback) {
|
|
54
|
+
this._bootingHooks.push(callback);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Register a callback that runs after boot completes.
|
|
58
|
+
* Like AdonisJS app.booted().
|
|
59
|
+
*/
|
|
60
|
+
booted(callback) {
|
|
61
|
+
if (this._booted) {
|
|
62
|
+
// Already booted — run immediately. Invoke callback() INSIDE the
|
|
63
|
+
// promise chain (not as `Promise.resolve(callback())`, which
|
|
64
|
+
// evaluates callback() eagerly and lets a synchronous throw
|
|
65
|
+
// escape to the caller) so both sync throws and async rejections
|
|
66
|
+
// are funnelled to the logger.
|
|
67
|
+
Promise.resolve()
|
|
68
|
+
.then(() => callback())
|
|
69
|
+
.catch((err) => {
|
|
70
|
+
process.stderr.write(`[Ream] booted() callback error: ${err}\n`);
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
this._bootedHooks.push(callback);
|
|
75
|
+
}
|
|
76
|
+
// ─── Signal handling ──────────────────────────────────────
|
|
77
|
+
/**
|
|
78
|
+
* Listen for a process signal.
|
|
79
|
+
* Like AdonisJS app.listen('SIGTERM', () => app.terminate()).
|
|
80
|
+
*/
|
|
81
|
+
listen(signal, callback) {
|
|
82
|
+
process.on(signal, callback);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Conditionally listen for a process signal.
|
|
86
|
+
* Like AdonisJS app.listenIf(app.managedByPm2, 'SIGINT', ...).
|
|
87
|
+
*/
|
|
88
|
+
listenIf(condition, signal, callback) {
|
|
89
|
+
if (condition) {
|
|
90
|
+
process.on(signal, callback);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Graceful shutdown — stop all providers and exit.
|
|
95
|
+
* Like AdonisJS app.terminate().
|
|
96
|
+
*/
|
|
97
|
+
async terminate() {
|
|
98
|
+
await this.shutdown();
|
|
99
|
+
process.exit(0);
|
|
100
|
+
}
|
|
101
|
+
// ─── Provider lifecycle ───────────────────────────────────
|
|
102
|
+
/** Register a provider instance. */
|
|
103
|
+
register(provider) {
|
|
104
|
+
this.providers.push(provider);
|
|
105
|
+
if (typeof provider.register === 'function') {
|
|
106
|
+
provider.register();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** Boot all registered providers. Runs booting/booted hooks. */
|
|
110
|
+
async boot() {
|
|
111
|
+
if (this._booted)
|
|
112
|
+
return;
|
|
113
|
+
// Run booting hooks
|
|
114
|
+
for (const hook of this._bootingHooks) {
|
|
115
|
+
await hook();
|
|
116
|
+
}
|
|
117
|
+
// Boot providers. `callProviderPhase` skips providers that don't
|
|
118
|
+
// declare the phase — duck-typed packages (spectrum, warden, etc.)
|
|
119
|
+
// implement only what they need.
|
|
120
|
+
for (const provider of this.providers) {
|
|
121
|
+
await callProviderPhase(provider, 'boot');
|
|
122
|
+
}
|
|
123
|
+
this._booted = true;
|
|
124
|
+
// Run booted hooks
|
|
125
|
+
for (const hook of this._bootedHooks) {
|
|
126
|
+
await hook();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Shutdown all providers in reverse order. */
|
|
130
|
+
async shutdown() {
|
|
131
|
+
// Run shutdown hooks
|
|
132
|
+
for (const hook of this._shutdownHooks) {
|
|
133
|
+
await hook();
|
|
134
|
+
}
|
|
135
|
+
for (const provider of [...this.providers].reverse()) {
|
|
136
|
+
await callProviderPhase(provider, 'shutdown');
|
|
137
|
+
}
|
|
138
|
+
this._booted = false;
|
|
139
|
+
}
|
|
140
|
+
/** Register a shutdown hook. */
|
|
141
|
+
onShutdown(callback) {
|
|
142
|
+
this._shutdownHooks.push(callback);
|
|
143
|
+
}
|
|
144
|
+
get isBooted() {
|
|
145
|
+
return this._booted;
|
|
146
|
+
}
|
|
147
|
+
get providerCount() {
|
|
148
|
+
return this.providers.length;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=Application.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Application.js","sourceRoot":"","sources":["../src/Application.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface Codemods {
|
|
2
|
+
addProvider(importPath: string): Promise<void>;
|
|
3
|
+
addEnvVars(vars: Record<string, string>): Promise<void>;
|
|
4
|
+
writeFile(filePath: string, content: string, options?: {
|
|
5
|
+
force?: boolean;
|
|
6
|
+
}): Promise<void>;
|
|
7
|
+
registerCommand(importPath: string): Promise<void>;
|
|
8
|
+
registerMiddleware(importPath: string, options?: {
|
|
9
|
+
tier?: 'server' | 'router';
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
export declare function createCodemods(options?: {
|
|
13
|
+
force?: boolean;
|
|
14
|
+
cwd?: string;
|
|
15
|
+
}): Codemods;
|
|
16
|
+
//# sourceMappingURL=Codemods.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Codemods.d.ts","sourceRoot":"","sources":["../src/Codemods.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9C,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACvD,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1F,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAClD,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAChG;AA0DD,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,QAAQ,CAmRpF"}
|
package/dist/Codemods.js
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
function isMiddlewareTier(value) {
|
|
4
|
+
return value === 'server' || value === 'router';
|
|
5
|
+
}
|
|
6
|
+
function findTierBlock(content, tier) {
|
|
7
|
+
// Word-boundary prefix `(?:^|[^A-Za-z0-9_$.])` rejects `customServer.use` / `myRouter.use`
|
|
8
|
+
// when scanning for the canonical `server` / `router` tier. The `.` exclusion also rejects
|
|
9
|
+
// `obj.server.use` shapes. Match[1] captures the literal `<tier>.use([` so we can compute
|
|
10
|
+
// the post-`[` cursor without including the boundary char.
|
|
11
|
+
const marker = new RegExp(`(?:^|[^A-Za-z0-9_$.])(${tier}\\.use\\s*\\(\\s*(?:\\/\\*[\\s\\S]*?\\*\\/\\s*)?\\[)`);
|
|
12
|
+
const match = marker.exec(content);
|
|
13
|
+
if (match === null || match[1] === undefined)
|
|
14
|
+
return null;
|
|
15
|
+
const start = match.index + match[0].length;
|
|
16
|
+
// The array close pattern `\]\s*,?\s*\)` matches `])`, `],)`, `],\n)`, `]\n)` — every
|
|
17
|
+
// canonical kernel shape produced by `ream new` or hand-formatted by Prettier. Using
|
|
18
|
+
// this pattern (vs a bare `]`) avoids early-truncating the slice on nested `]` inside
|
|
19
|
+
// an array entry — important for the dedup window since we read the slice content for
|
|
20
|
+
// cross-tier collision detection AND per-tier idempotency.
|
|
21
|
+
const closeMatch = /\]\s*,?\s*\)/.exec(content.slice(start));
|
|
22
|
+
if (closeMatch === null)
|
|
23
|
+
return null;
|
|
24
|
+
return { start, end: start + closeMatch.index };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Detect line ending (CRLF on Windows checkouts, LF elsewhere) so codemods preserve the file's existing convention.
|
|
28
|
+
* Majority-based: a stray CRLF in an otherwise-LF file must not flip the whole insertion to CRLF.
|
|
29
|
+
*/
|
|
30
|
+
function detectLineEnding(content) {
|
|
31
|
+
const crlfCount = (content.match(/\r\n/g) ?? []).length;
|
|
32
|
+
const bareLfCount = (content.match(/(?<!\r)\n/g) ?? []).length;
|
|
33
|
+
return crlfCount > bareLfCount ? '\r\n' : '\n';
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Refuse to follow a symlink that escapes the project root. Mirrors the guard `writeFile` enforces
|
|
37
|
+
* (lines 137-155) so `registerCommand` and `registerMiddleware` cannot be tricked into writing
|
|
38
|
+
* outside `root` via a symlinked `reamrc.ts` or `start/kernel.ts`.
|
|
39
|
+
*/
|
|
40
|
+
function assertCanonicallyInside(root, filePath, displayName) {
|
|
41
|
+
if (!fs.existsSync(filePath))
|
|
42
|
+
return;
|
|
43
|
+
const canonRoot = fs.realpathSync(root);
|
|
44
|
+
const canonFile = fs.realpathSync(filePath);
|
|
45
|
+
if (!canonFile.startsWith(canonRoot + path.sep) && canonFile !== canonRoot) {
|
|
46
|
+
throw new Error(`[configure] Symlink escape detected: ${displayName} resolves outside project root`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function createCodemods(options) {
|
|
50
|
+
const force = options?.force ?? false;
|
|
51
|
+
const root = path.resolve(options?.cwd ?? process.cwd());
|
|
52
|
+
return {
|
|
53
|
+
/**
|
|
54
|
+
* Insert a provider import into `reamrc.ts` by string manipulation.
|
|
55
|
+
*
|
|
56
|
+
* KNOWN LIMITATION: this is a regex-based codemod, not a TS AST
|
|
57
|
+
* transform. It works for the canonical `providers: [ ... ]` shape
|
|
58
|
+
* emitted by `ream new` and tolerates comments/whitespace around
|
|
59
|
+
* the array literal. It does NOT handle unusual shapes such as
|
|
60
|
+
* providers declared via a spread, a ternary, a `const providers =
|
|
61
|
+
* [...]` extracted above the config object, or a `providers:`
|
|
62
|
+
* identifier that appears inside a string literal or block comment
|
|
63
|
+
* elsewhere in the file. For those cases, edit `reamrc.ts` by hand.
|
|
64
|
+
* A full AST-based rewrite is tracked separately.
|
|
65
|
+
*/
|
|
66
|
+
async addProvider(importPath) {
|
|
67
|
+
const rcPath = path.join(root, 'reamrc.ts');
|
|
68
|
+
if (!fs.existsSync(rcPath)) {
|
|
69
|
+
throw new Error(`[configure] reamrc.ts not found — cannot register provider ${importPath}. Run 'ream new' first.`);
|
|
70
|
+
}
|
|
71
|
+
// Same symlink-containment guard registerCommand/registerMiddleware/
|
|
72
|
+
// writeFile apply — a symlinked reamrc.ts must not redirect the
|
|
73
|
+
// write outside the project root.
|
|
74
|
+
assertCanonicallyInside(root, rcPath, 'reamrc.ts');
|
|
75
|
+
let content = fs.readFileSync(rcPath, 'utf8');
|
|
76
|
+
// Dedup check — any mention of the exact import path is treated
|
|
77
|
+
// as an existing registration. This is a coarse heuristic but
|
|
78
|
+
// safe because `importPath` is typically a package path like
|
|
79
|
+
// `@c9up/atlas/providers`, which should not appear in comments
|
|
80
|
+
// or unrelated strings in a typical `reamrc.ts`.
|
|
81
|
+
if (content.includes(`'${importPath}'`) || content.includes(`"${importPath}"`))
|
|
82
|
+
return;
|
|
83
|
+
const entry = ` () => import('${importPath}'),`;
|
|
84
|
+
// Marker tolerates extra whitespace and optional trailing comments
|
|
85
|
+
// between `providers:` and `[`. Still brittle to string-literal
|
|
86
|
+
// false-positives (see doc above).
|
|
87
|
+
const marker = /providers\s*:\s*(?:\/\*[\s\S]*?\*\/\s*)?\[/;
|
|
88
|
+
const match = marker.exec(content);
|
|
89
|
+
if (!match) {
|
|
90
|
+
throw new Error(`[configure] Could not find 'providers: [' in reamrc.ts — provider ${importPath} not added. Check your reamrc.ts format.`);
|
|
91
|
+
}
|
|
92
|
+
const insertAt = match.index + match[0].length;
|
|
93
|
+
const eol = detectLineEnding(content);
|
|
94
|
+
content = `${content.slice(0, insertAt)}${eol}${entry}${content.slice(insertAt)}`;
|
|
95
|
+
fs.writeFileSync(rcPath, content);
|
|
96
|
+
},
|
|
97
|
+
async addEnvVars(vars) {
|
|
98
|
+
const envPath = path.join(root, '.env');
|
|
99
|
+
// A symlinked .env must not redirect the write outside the root.
|
|
100
|
+
assertCanonicallyInside(root, envPath, '.env');
|
|
101
|
+
let content = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf8') : '';
|
|
102
|
+
let added = 0;
|
|
103
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
104
|
+
const pattern = new RegExp(`^${key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}=`, 'm');
|
|
105
|
+
if (!pattern.test(content)) {
|
|
106
|
+
content += `${key}=${value}\n`;
|
|
107
|
+
added++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (added > 0)
|
|
111
|
+
fs.writeFileSync(envPath, content);
|
|
112
|
+
},
|
|
113
|
+
async writeFile(filePath, content, opts) {
|
|
114
|
+
if (path.isAbsolute(filePath)) {
|
|
115
|
+
throw new Error(`[configure] Absolute paths not allowed: ${filePath}`);
|
|
116
|
+
}
|
|
117
|
+
const resolved = path.resolve(root, filePath);
|
|
118
|
+
if (!resolved.startsWith(root + path.sep) && resolved !== root) {
|
|
119
|
+
throw new Error(`[configure] Refusing to write outside project root: ${filePath}`);
|
|
120
|
+
}
|
|
121
|
+
const shouldForce = opts?.force ?? force;
|
|
122
|
+
if (fs.existsSync(resolved) && !shouldForce)
|
|
123
|
+
return;
|
|
124
|
+
const dir = path.dirname(resolved);
|
|
125
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
126
|
+
const canonRoot = fs.realpathSync(root);
|
|
127
|
+
if (fs.existsSync(dir)) {
|
|
128
|
+
const canonDir = fs.realpathSync(dir);
|
|
129
|
+
if (!canonDir.startsWith(canonRoot + path.sep) && canonDir !== canonRoot) {
|
|
130
|
+
throw new Error(`[configure] Symlink escape detected: ${filePath} — directory resolves outside project root`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (fs.existsSync(resolved)) {
|
|
134
|
+
const canonFile = fs.realpathSync(resolved);
|
|
135
|
+
if (!canonFile.startsWith(canonRoot + path.sep)) {
|
|
136
|
+
throw new Error(`[configure] Symlink escape detected: ${filePath} — file resolves outside project root`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
fs.writeFileSync(resolved, content);
|
|
140
|
+
},
|
|
141
|
+
/**
|
|
142
|
+
* Insert a command import into `reamrc.ts` `commands: [ ... ]` array.
|
|
143
|
+
*
|
|
144
|
+
* Mirrors `addProvider`'s shape: regex-based codemod (NOT a TS AST
|
|
145
|
+
* transform), idempotent string-match dedup against the exact import
|
|
146
|
+
* path quoted, `[configure]` error prefix on failure.
|
|
147
|
+
*
|
|
148
|
+
* Bootstraps the `commands:` field when absent — inserts immediately
|
|
149
|
+
* after the existing `providers: [...]` block when present, otherwise
|
|
150
|
+
* before the closing `})` of `defineConfig({...})`. The field is
|
|
151
|
+
* optional in `ReamrcConfig` (Ignitor.ts:55), so adding it is
|
|
152
|
+
* non-breaking.
|
|
153
|
+
*
|
|
154
|
+
* Indent convention: inserted entries use 4-space indent, matching the
|
|
155
|
+
* canonical depth-2 nesting inside `defineConfig({ providers: [ ... ] })`.
|
|
156
|
+
* (registerMiddleware uses 2-space indent because its target is the
|
|
157
|
+
* depth-1 `<tier>.use([ ... ])` call in `start/kernel.ts`.)
|
|
158
|
+
*
|
|
159
|
+
* Marker anchoring: top-level fields of `defineConfig({...})` are
|
|
160
|
+
* anchored to start-of-line + ≤4 leading spaces to reject false matches
|
|
161
|
+
* inside nested objects (e.g. a `tests: { commands: [...] }` field
|
|
162
|
+
* higher in `reamrc.ts`).
|
|
163
|
+
*/
|
|
164
|
+
async registerCommand(importPath) {
|
|
165
|
+
const rcPath = path.join(root, 'reamrc.ts');
|
|
166
|
+
if (!fs.existsSync(rcPath)) {
|
|
167
|
+
throw new Error(`[configure] reamrc.ts not found — cannot register command ${importPath}. Run 'ream new' first.`);
|
|
168
|
+
}
|
|
169
|
+
assertCanonicallyInside(root, rcPath, 'reamrc.ts');
|
|
170
|
+
let content = fs.readFileSync(rcPath, 'utf8');
|
|
171
|
+
if (content.includes(`'${importPath}'`) || content.includes(`"${importPath}"`))
|
|
172
|
+
return;
|
|
173
|
+
const eol = detectLineEnding(content);
|
|
174
|
+
const entry = ` () => import('${importPath}'),`;
|
|
175
|
+
// Anchor `commands:` to start-of-line + ≤4 leading spaces (top-level field of
|
|
176
|
+
// `defineConfig({...})`). Rejects nested matches like `tests: { commands: [...] }`.
|
|
177
|
+
const arrayMarker = /^[ \t]{0,4}commands\s*:\s*(?:\/\*[\s\S]*?\*\/\s*)?\[/m;
|
|
178
|
+
const arrayMatch = arrayMarker.exec(content);
|
|
179
|
+
if (arrayMatch !== null) {
|
|
180
|
+
const insertAt = arrayMatch.index + arrayMatch[0].length;
|
|
181
|
+
content = `${content.slice(0, insertAt)}${eol}${entry}${content.slice(insertAt)}`;
|
|
182
|
+
fs.writeFileSync(rcPath, content);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const block = ` commands: [${eol}${entry}${eol} ],${eol}`;
|
|
186
|
+
// Same start-of-line anchor as the commands marker — rejects nested `providers:`.
|
|
187
|
+
// Note: the non-greedy `\[[\s\S]*?\]` still finds the FIRST `]` after `providers:`,
|
|
188
|
+
// so a top-level `providers: [...]` containing nested `]` (e.g. tuple-typed entries)
|
|
189
|
+
// can still mis-match. Rare in practice; if hit, the user's reamrc.ts is in a shape
|
|
190
|
+
// the regex codemod cannot safely manipulate — they should add `commands: []`
|
|
191
|
+
// manually and re-run, or fall through to the defineConfig-close fallback below.
|
|
192
|
+
const providersEndMarker = /^[ \t]{0,4}providers\s*:\s*\[[\s\S]*?\],?[ \t]*\r?\n/m;
|
|
193
|
+
const providersEnd = providersEndMarker.exec(content);
|
|
194
|
+
if (providersEnd !== null) {
|
|
195
|
+
const insertAt = providersEnd.index + providersEnd[0].length;
|
|
196
|
+
content = `${content.slice(0, insertAt)}${block}${content.slice(insertAt)}`;
|
|
197
|
+
fs.writeFileSync(rcPath, content);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
// Use the LAST `})` in the file (conventionally the `defineConfig({...})` close in a
|
|
201
|
+
// canonical `export default defineConfig({...})` reamrc). `lastIndexOf` avoids the
|
|
202
|
+
// /m-anchored `exec` returning the FIRST line ending in `})` — which would mis-target
|
|
203
|
+
// a helper above defineConfig like `const helper = makeProviders({ eager: true })`.
|
|
204
|
+
const defineCloseIdx = content.lastIndexOf('})');
|
|
205
|
+
if (defineCloseIdx !== -1) {
|
|
206
|
+
content = `${content.slice(0, defineCloseIdx)}${block}${content.slice(defineCloseIdx)}`;
|
|
207
|
+
fs.writeFileSync(rcPath, content);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
throw new Error(`[configure] Could not find 'defineConfig({ ... })' in reamrc.ts — command ${importPath} not added. Check your reamrc.ts format.`);
|
|
211
|
+
},
|
|
212
|
+
/**
|
|
213
|
+
* Insert a middleware import into `start/kernel.ts` `<tier>.use([ ... ])`
|
|
214
|
+
* array. `tier` defaults to `'router'` (matched routes only) — the
|
|
215
|
+
* conservative choice that does not run on 404s. Set `tier: 'server'`
|
|
216
|
+
* for middleware that must run on every request including 404s
|
|
217
|
+
* (security headers, request-id, structured logging).
|
|
218
|
+
*
|
|
219
|
+
* Mirrors `addProvider`'s shape: regex-based codemod, idempotent
|
|
220
|
+
* per-tier string-match dedup, `[configure]` error prefix.
|
|
221
|
+
*
|
|
222
|
+
* KNOWN LIMITATION: does NOT bootstrap a missing `<tier>.use([])`
|
|
223
|
+
* block. Unlike `commands`, the `server.use` / `router.use` calls
|
|
224
|
+
* are user-authored idiom in `start/kernel.ts`, not a config-shape
|
|
225
|
+
* contract — synthesising them would require also synthesising the
|
|
226
|
+
* `import server from '@c9up/ream/services/server'` boilerplate, and
|
|
227
|
+
* is footgun-prone if the user has renamed identifiers. When the
|
|
228
|
+
* targeted block is absent, this method errors and asks the user
|
|
229
|
+
* to add the block manually.
|
|
230
|
+
*
|
|
231
|
+
* Cross-tier collision is rejected: registering the same import path
|
|
232
|
+
* in BOTH `server` and `router` tiers is almost certainly a mistake;
|
|
233
|
+
* the second call throws `[configure] middleware <importPath> is
|
|
234
|
+
* already registered in <other-tier> tier`.
|
|
235
|
+
*
|
|
236
|
+
* Indent convention: inserted entries use 2-space indent, matching
|
|
237
|
+
* the canonical depth-1 nesting inside `<tier>.use([ ... ])` at the
|
|
238
|
+
* top of `start/kernel.ts`. (registerCommand uses 4-space indent
|
|
239
|
+
* because its target is the depth-2 `defineConfig({ commands: [ ... ] })`
|
|
240
|
+
* block in `reamrc.ts`.)
|
|
241
|
+
*/
|
|
242
|
+
async registerMiddleware(importPath, options) {
|
|
243
|
+
const requestedTier = options?.tier ?? 'router';
|
|
244
|
+
if (!isMiddlewareTier(requestedTier)) {
|
|
245
|
+
throw new Error(`[configure] Invalid middleware tier: '${String(requestedTier)}'. Expected 'server' or 'router'.`);
|
|
246
|
+
}
|
|
247
|
+
const tier = requestedTier;
|
|
248
|
+
const otherTier = tier === 'server' ? 'router' : 'server';
|
|
249
|
+
const kernelPath = path.join(root, 'start', 'kernel.ts');
|
|
250
|
+
if (!fs.existsSync(kernelPath)) {
|
|
251
|
+
throw new Error(`[configure] start/kernel.ts not found — cannot register middleware ${importPath}. Run 'ream new' first or create the file from the installation guide.`);
|
|
252
|
+
}
|
|
253
|
+
assertCanonicallyInside(root, kernelPath, 'start/kernel.ts');
|
|
254
|
+
let content = fs.readFileSync(kernelPath, 'utf8');
|
|
255
|
+
const otherBlock = findTierBlock(content, otherTier);
|
|
256
|
+
if (otherBlock !== null) {
|
|
257
|
+
const otherSlice = content.slice(otherBlock.start, otherBlock.end);
|
|
258
|
+
if (otherSlice.includes(`'${importPath}'`) || otherSlice.includes(`"${importPath}"`)) {
|
|
259
|
+
throw new Error(`[configure] middleware ${importPath} is already registered in ${otherTier} tier — cannot also register in ${tier} tier. Choose one tier or remove the existing registration.`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const targetBlock = findTierBlock(content, tier);
|
|
263
|
+
if (targetBlock === null) {
|
|
264
|
+
throw new Error(`[configure] Could not find '${tier}.use([' in start/kernel.ts — middleware ${importPath} not added. Add the block manually or check your start/kernel.ts format.`);
|
|
265
|
+
}
|
|
266
|
+
const targetSlice = content.slice(targetBlock.start, targetBlock.end);
|
|
267
|
+
if (targetSlice.includes(`'${importPath}'`) || targetSlice.includes(`"${importPath}"`)) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const eol = detectLineEnding(content);
|
|
271
|
+
const entry = ` () => import('${importPath}'),`;
|
|
272
|
+
content = `${content.slice(0, targetBlock.start)}${eol}${entry}${content.slice(targetBlock.start)}`;
|
|
273
|
+
fs.writeFileSync(kernelPath, content);
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=Codemods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Codemods.js","sourceRoot":"","sources":["../src/Codemods.ts"],"names":[],"mappings":"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"}
|