imposters 0.1.0
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/Program/package.json +6 -0
- package/README.md +365 -0
- package/api/AdminApi/package.json +6 -0
- package/api/ApiErrors/package.json +6 -0
- package/api/ApiSchemas/package.json +6 -0
- package/api/Conversions/package.json +6 -0
- package/api/ImpostersGroup/package.json +6 -0
- package/api/ImpostersHandlers/package.json +6 -0
- package/api/SystemGroup/package.json +6 -0
- package/api/SystemHandlers/package.json +6 -0
- package/bin/imposters +47 -0
- package/cli/Commands/package.json +6 -0
- package/cli/ConfigLoader/package.json +6 -0
- package/client/HandlerHttpClient/package.json +6 -0
- package/client/ImpostersClient/package.json +6 -0
- package/client/testing/package.json +6 -0
- package/dist/cjs/Program.js +4 -0
- package/dist/cjs/Program.js.map +1 -0
- package/dist/cjs/api/AdminApi.js +11 -0
- package/dist/cjs/api/AdminApi.js.map +1 -0
- package/dist/cjs/api/ApiErrors.js +30 -0
- package/dist/cjs/api/ApiErrors.js.map +1 -0
- package/dist/cjs/api/ApiSchemas.js +36 -0
- package/dist/cjs/api/ApiSchemas.js.map +1 -0
- package/dist/cjs/api/Conversions.js +41 -0
- package/dist/cjs/api/Conversions.js.map +1 -0
- package/dist/cjs/api/ImpostersGroup.js +37 -0
- package/dist/cjs/api/ImpostersGroup.js.map +1 -0
- package/dist/cjs/api/ImpostersHandlers.js +361 -0
- package/dist/cjs/api/ImpostersHandlers.js.map +1 -0
- package/dist/cjs/api/SystemGroup.js +12 -0
- package/dist/cjs/api/SystemGroup.js.map +1 -0
- package/dist/cjs/api/SystemHandlers.js +74 -0
- package/dist/cjs/api/SystemHandlers.js.map +1 -0
- package/dist/cjs/cli/Commands.js +104 -0
- package/dist/cjs/cli/Commands.js.map +1 -0
- package/dist/cjs/cli/ConfigLoader.js +34 -0
- package/dist/cjs/cli/ConfigLoader.js.map +1 -0
- package/dist/cjs/client/HandlerHttpClient.js +50 -0
- package/dist/cjs/client/HandlerHttpClient.js.map +1 -0
- package/dist/cjs/client/ImpostersClient.js +20 -0
- package/dist/cjs/client/ImpostersClient.js.map +1 -0
- package/dist/cjs/client/index.js +57 -0
- package/dist/cjs/client/index.js.map +1 -0
- package/dist/cjs/client/testing.js +94 -0
- package/dist/cjs/client/testing.js.map +1 -0
- package/dist/cjs/domain/imposter.js +125 -0
- package/dist/cjs/domain/imposter.js.map +1 -0
- package/dist/cjs/domain/route.js +185 -0
- package/dist/cjs/domain/route.js.map +1 -0
- package/dist/cjs/index.js +106 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/layers/ApiLayer.js +18 -0
- package/dist/cjs/layers/ApiLayer.js.map +1 -0
- package/dist/cjs/layers/MainLayer.js +27 -0
- package/dist/cjs/layers/MainLayer.js.map +1 -0
- package/dist/cjs/matching/ExpressionEvaluator.js +103 -0
- package/dist/cjs/matching/ExpressionEvaluator.js.map +1 -0
- package/dist/cjs/matching/RequestMatcher.js +145 -0
- package/dist/cjs/matching/RequestMatcher.js.map +1 -0
- package/dist/cjs/matching/ResponseGenerator.js +80 -0
- package/dist/cjs/matching/ResponseGenerator.js.map +1 -0
- package/dist/cjs/matching/TemplateEngine.js +55 -0
- package/dist/cjs/matching/TemplateEngine.js.map +1 -0
- package/dist/cjs/repositories/ImposterRepository.js +118 -0
- package/dist/cjs/repositories/ImposterRepository.js.map +1 -0
- package/dist/cjs/schemas/ConfigFileSchema.js +44 -0
- package/dist/cjs/schemas/ConfigFileSchema.js.map +1 -0
- package/dist/cjs/schemas/ImposterSchema.js +202 -0
- package/dist/cjs/schemas/ImposterSchema.js.map +1 -0
- package/dist/cjs/schemas/RequestLogSchema.js +51 -0
- package/dist/cjs/schemas/RequestLogSchema.js.map +1 -0
- package/dist/cjs/schemas/StubSchema.js +84 -0
- package/dist/cjs/schemas/StubSchema.js.map +1 -0
- package/dist/cjs/schemas/common.js +67 -0
- package/dist/cjs/schemas/common.js.map +1 -0
- package/dist/cjs/server/AdminServer.js +36 -0
- package/dist/cjs/server/AdminServer.js.map +1 -0
- package/dist/cjs/server/BunServer.js +13 -0
- package/dist/cjs/server/BunServer.js.map +1 -0
- package/dist/cjs/server/FiberManager.js +21 -0
- package/dist/cjs/server/FiberManager.js.map +1 -0
- package/dist/cjs/server/ImposterServer.js +234 -0
- package/dist/cjs/server/ImposterServer.js.map +1 -0
- package/dist/cjs/services/AppConfig.js +18 -0
- package/dist/cjs/services/AppConfig.js.map +1 -0
- package/dist/cjs/services/MetricsService.js +113 -0
- package/dist/cjs/services/MetricsService.js.map +1 -0
- package/dist/cjs/services/PortAllocator.js +50 -0
- package/dist/cjs/services/PortAllocator.js.map +1 -0
- package/dist/cjs/services/ProxyService.js +109 -0
- package/dist/cjs/services/ProxyService.js.map +1 -0
- package/dist/cjs/services/RequestLogger.js +60 -0
- package/dist/cjs/services/RequestLogger.js.map +1 -0
- package/dist/cjs/services/Uuid.js +10 -0
- package/dist/cjs/services/Uuid.js.map +1 -0
- package/dist/cjs/services/UuidLive.js +16 -0
- package/dist/cjs/services/UuidLive.js.map +1 -0
- package/dist/cjs/ui/UiRouter.js +242 -0
- package/dist/cjs/ui/UiRouter.js.map +1 -0
- package/dist/cjs/ui/admin/AdminLayout.js +36 -0
- package/dist/cjs/ui/admin/AdminLayout.js.map +1 -0
- package/dist/cjs/ui/admin/AdminUiRouter.js +155 -0
- package/dist/cjs/ui/admin/AdminUiRouter.js.map +1 -0
- package/dist/cjs/ui/admin/pages/AdminDashboard.js +55 -0
- package/dist/cjs/ui/admin/pages/AdminDashboard.js.map +1 -0
- package/dist/cjs/ui/admin/partials.js +64 -0
- package/dist/cjs/ui/admin/partials.js.map +1 -0
- package/dist/cjs/ui/html.js +42 -0
- package/dist/cjs/ui/html.js.map +1 -0
- package/dist/cjs/ui/layout.js +39 -0
- package/dist/cjs/ui/layout.js.map +1 -0
- package/dist/cjs/ui/pages/dashboard.js +51 -0
- package/dist/cjs/ui/pages/dashboard.js.map +1 -0
- package/dist/cjs/ui/pages/request-detail.js +119 -0
- package/dist/cjs/ui/pages/request-detail.js.map +1 -0
- package/dist/cjs/ui/pages/requests.js +120 -0
- package/dist/cjs/ui/pages/requests.js.map +1 -0
- package/dist/cjs/ui/pages/stubs.js +46 -0
- package/dist/cjs/ui/pages/stubs.js.map +1 -0
- package/dist/cjs/ui/partials.js +104 -0
- package/dist/cjs/ui/partials.js.map +1 -0
- package/dist/dts/Program.d.ts +2 -0
- package/dist/dts/Program.d.ts.map +1 -0
- package/dist/dts/api/AdminApi.d.ts +490 -0
- package/dist/dts/api/AdminApi.d.ts.map +1 -0
- package/dist/dts/api/ApiErrors.d.ts +26 -0
- package/dist/dts/api/ApiErrors.d.ts.map +1 -0
- package/dist/dts/api/ApiSchemas.d.ts +36 -0
- package/dist/dts/api/ApiSchemas.d.ts.map +1 -0
- package/dist/dts/api/Conversions.d.ts +7 -0
- package/dist/dts/api/Conversions.d.ts.map +1 -0
- package/dist/dts/api/ImpostersGroup.d.ts +448 -0
- package/dist/dts/api/ImpostersGroup.d.ts.map +1 -0
- package/dist/dts/api/ImpostersHandlers.d.ts +9 -0
- package/dist/dts/api/ImpostersHandlers.d.ts.map +1 -0
- package/dist/dts/api/SystemGroup.d.ts +46 -0
- package/dist/dts/api/SystemGroup.d.ts.map +1 -0
- package/dist/dts/api/SystemHandlers.d.ts +4 -0
- package/dist/dts/api/SystemHandlers.d.ts.map +1 -0
- package/dist/dts/cli/Commands.d.ts +4 -0
- package/dist/dts/cli/Commands.d.ts.map +1 -0
- package/dist/dts/cli/ConfigLoader.d.ts +13 -0
- package/dist/dts/cli/ConfigLoader.d.ts.map +1 -0
- package/dist/dts/client/HandlerHttpClient.d.ts +5 -0
- package/dist/dts/client/HandlerHttpClient.d.ts.map +1 -0
- package/dist/dts/client/ImpostersClient.d.ts +1868 -0
- package/dist/dts/client/ImpostersClient.d.ts.map +1 -0
- package/dist/dts/client/index.d.ts +6 -0
- package/dist/dts/client/index.d.ts.map +1 -0
- package/dist/dts/client/testing.d.ts +35 -0
- package/dist/dts/client/testing.d.ts.map +1 -0
- package/dist/dts/domain/imposter.d.ts +123 -0
- package/dist/dts/domain/imposter.d.ts.map +1 -0
- package/dist/dts/domain/route.d.ts +128 -0
- package/dist/dts/domain/route.d.ts.map +1 -0
- package/dist/dts/index.d.ts +60 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/dts/layers/ApiLayer.d.ts +3 -0
- package/dist/dts/layers/ApiLayer.d.ts.map +1 -0
- package/dist/dts/layers/MainLayer.d.ts +3 -0
- package/dist/dts/layers/MainLayer.d.ts.map +1 -0
- package/dist/dts/matching/ExpressionEvaluator.d.ts +11 -0
- package/dist/dts/matching/ExpressionEvaluator.d.ts.map +1 -0
- package/dist/dts/matching/RequestMatcher.d.ts +13 -0
- package/dist/dts/matching/RequestMatcher.d.ts.map +1 -0
- package/dist/dts/matching/ResponseGenerator.d.ts +9 -0
- package/dist/dts/matching/ResponseGenerator.d.ts.map +1 -0
- package/dist/dts/matching/TemplateEngine.d.ts +4 -0
- package/dist/dts/matching/TemplateEngine.d.ts.map +1 -0
- package/dist/dts/repositories/ImposterRepository.d.ts +33 -0
- package/dist/dts/repositories/ImposterRepository.d.ts.map +1 -0
- package/dist/dts/schemas/ConfigFileSchema.d.ts +142 -0
- package/dist/dts/schemas/ConfigFileSchema.d.ts.map +1 -0
- package/dist/dts/schemas/ImposterSchema.d.ts +368 -0
- package/dist/dts/schemas/ImposterSchema.d.ts.map +1 -0
- package/dist/dts/schemas/RequestLogSchema.d.ts +36 -0
- package/dist/dts/schemas/RequestLogSchema.d.ts.map +1 -0
- package/dist/dts/schemas/StubSchema.d.ts +112 -0
- package/dist/dts/schemas/StubSchema.d.ts.map +1 -0
- package/dist/dts/schemas/common.d.ts +56 -0
- package/dist/dts/schemas/common.d.ts.map +1 -0
- package/dist/dts/server/AdminServer.d.ts +11 -0
- package/dist/dts/server/AdminServer.d.ts.map +1 -0
- package/dist/dts/server/BunServer.d.ts +17 -0
- package/dist/dts/server/BunServer.d.ts.map +1 -0
- package/dist/dts/server/FiberManager.d.ts +12 -0
- package/dist/dts/server/FiberManager.d.ts.map +1 -0
- package/dist/dts/server/ImposterServer.d.ts +29 -0
- package/dist/dts/server/ImposterServer.d.ts.map +1 -0
- package/dist/dts/services/AppConfig.d.ts +14 -0
- package/dist/dts/services/AppConfig.d.ts.map +1 -0
- package/dist/dts/services/MetricsService.d.ts +26 -0
- package/dist/dts/services/MetricsService.d.ts.map +1 -0
- package/dist/dts/services/PortAllocator.d.ts +29 -0
- package/dist/dts/services/PortAllocator.d.ts.map +1 -0
- package/dist/dts/services/ProxyService.d.ts +24 -0
- package/dist/dts/services/ProxyService.d.ts.map +1 -0
- package/dist/dts/services/RequestLogger.d.ts +23 -0
- package/dist/dts/services/RequestLogger.d.ts.map +1 -0
- package/dist/dts/services/Uuid.d.ts +9 -0
- package/dist/dts/services/Uuid.d.ts.map +1 -0
- package/dist/dts/services/UuidLive.d.ts +4 -0
- package/dist/dts/services/UuidLive.d.ts.map +1 -0
- package/dist/dts/ui/UiRouter.d.ts +15 -0
- package/dist/dts/ui/UiRouter.d.ts.map +1 -0
- package/dist/dts/ui/admin/AdminLayout.d.ts +7 -0
- package/dist/dts/ui/admin/AdminLayout.d.ts.map +1 -0
- package/dist/dts/ui/admin/AdminUiRouter.d.ts +6 -0
- package/dist/dts/ui/admin/AdminUiRouter.d.ts.map +1 -0
- package/dist/dts/ui/admin/pages/AdminDashboard.d.ts +7 -0
- package/dist/dts/ui/admin/pages/AdminDashboard.d.ts.map +1 -0
- package/dist/dts/ui/admin/partials.d.ts +14 -0
- package/dist/dts/ui/admin/partials.d.ts.map +1 -0
- package/dist/dts/ui/html.d.ts +12 -0
- package/dist/dts/ui/html.d.ts.map +1 -0
- package/dist/dts/ui/layout.d.ts +9 -0
- package/dist/dts/ui/layout.d.ts.map +1 -0
- package/dist/dts/ui/pages/dashboard.d.ts +10 -0
- package/dist/dts/ui/pages/dashboard.d.ts.map +1 -0
- package/dist/dts/ui/pages/request-detail.d.ts +11 -0
- package/dist/dts/ui/pages/request-detail.d.ts.map +1 -0
- package/dist/dts/ui/pages/requests.d.ts +15 -0
- package/dist/dts/ui/pages/requests.d.ts.map +1 -0
- package/dist/dts/ui/pages/stubs.d.ts +8 -0
- package/dist/dts/ui/pages/stubs.d.ts.map +1 -0
- package/dist/dts/ui/partials.d.ts +13 -0
- package/dist/dts/ui/partials.d.ts.map +1 -0
- package/dist/esm/Program.js +2 -0
- package/dist/esm/Program.js.map +1 -0
- package/dist/esm/api/AdminApi.js +5 -0
- package/dist/esm/api/AdminApi.js.map +1 -0
- package/dist/esm/api/ApiErrors.js +20 -0
- package/dist/esm/api/ApiErrors.js.map +1 -0
- package/dist/esm/api/ApiSchemas.js +29 -0
- package/dist/esm/api/ApiSchemas.js.map +1 -0
- package/dist/esm/api/Conversions.js +32 -0
- package/dist/esm/api/Conversions.js.map +1 -0
- package/dist/esm/api/ImpostersGroup.js +30 -0
- package/dist/esm/api/ImpostersGroup.js.map +1 -0
- package/dist/esm/api/ImpostersHandlers.js +354 -0
- package/dist/esm/api/ImpostersHandlers.js.map +1 -0
- package/dist/esm/api/SystemGroup.js +6 -0
- package/dist/esm/api/SystemGroup.js.map +1 -0
- package/dist/esm/api/SystemHandlers.js +67 -0
- package/dist/esm/api/SystemHandlers.js.map +1 -0
- package/dist/esm/cli/Commands.js +98 -0
- package/dist/esm/cli/Commands.js.map +1 -0
- package/dist/esm/cli/ConfigLoader.js +25 -0
- package/dist/esm/cli/ConfigLoader.js.map +1 -0
- package/dist/esm/client/HandlerHttpClient.js +42 -0
- package/dist/esm/client/HandlerHttpClient.js.map +1 -0
- package/dist/esm/client/ImpostersClient.js +10 -0
- package/dist/esm/client/ImpostersClient.js.map +1 -0
- package/dist/esm/client/index.js +4 -0
- package/dist/esm/client/index.js.map +1 -0
- package/dist/esm/client/testing.js +86 -0
- package/dist/esm/client/testing.js.map +1 -0
- package/dist/esm/domain/imposter.js +103 -0
- package/dist/esm/domain/imposter.js.map +1 -0
- package/dist/esm/domain/route.js +164 -0
- package/dist/esm/domain/route.js.map +1 -0
- package/dist/esm/index.js +60 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/layers/ApiLayer.js +11 -0
- package/dist/esm/layers/ApiLayer.js.map +1 -0
- package/dist/esm/layers/MainLayer.js +20 -0
- package/dist/esm/layers/MainLayer.js.map +1 -0
- package/dist/esm/matching/ExpressionEvaluator.js +94 -0
- package/dist/esm/matching/ExpressionEvaluator.js.map +1 -0
- package/dist/esm/matching/RequestMatcher.js +135 -0
- package/dist/esm/matching/RequestMatcher.js.map +1 -0
- package/dist/esm/matching/ResponseGenerator.js +71 -0
- package/dist/esm/matching/ResponseGenerator.js.map +1 -0
- package/dist/esm/matching/TemplateEngine.js +47 -0
- package/dist/esm/matching/TemplateEngine.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/dist/esm/repositories/ImposterRepository.js +110 -0
- package/dist/esm/repositories/ImposterRepository.js.map +1 -0
- package/dist/esm/schemas/ConfigFileSchema.js +37 -0
- package/dist/esm/schemas/ConfigFileSchema.js.map +1 -0
- package/dist/esm/schemas/ImposterSchema.js +195 -0
- package/dist/esm/schemas/ImposterSchema.js.map +1 -0
- package/dist/esm/schemas/RequestLogSchema.js +44 -0
- package/dist/esm/schemas/RequestLogSchema.js.map +1 -0
- package/dist/esm/schemas/StubSchema.js +77 -0
- package/dist/esm/schemas/StubSchema.js.map +1 -0
- package/dist/esm/schemas/common.js +59 -0
- package/dist/esm/schemas/common.js.map +1 -0
- package/dist/esm/server/AdminServer.js +27 -0
- package/dist/esm/server/AdminServer.js.map +1 -0
- package/dist/esm/server/BunServer.js +6 -0
- package/dist/esm/server/BunServer.js.map +1 -0
- package/dist/esm/server/FiberManager.js +14 -0
- package/dist/esm/server/FiberManager.js.map +1 -0
- package/dist/esm/server/ImposterServer.js +225 -0
- package/dist/esm/server/ImposterServer.js.map +1 -0
- package/dist/esm/services/AppConfig.js +11 -0
- package/dist/esm/services/AppConfig.js.map +1 -0
- package/dist/esm/services/MetricsService.js +105 -0
- package/dist/esm/services/MetricsService.js.map +1 -0
- package/dist/esm/services/PortAllocator.js +41 -0
- package/dist/esm/services/PortAllocator.js.map +1 -0
- package/dist/esm/services/ProxyService.js +101 -0
- package/dist/esm/services/ProxyService.js.map +1 -0
- package/dist/esm/services/RequestLogger.js +53 -0
- package/dist/esm/services/RequestLogger.js.map +1 -0
- package/dist/esm/services/Uuid.js +3 -0
- package/dist/esm/services/Uuid.js.map +1 -0
- package/dist/esm/services/UuidLive.js +9 -0
- package/dist/esm/services/UuidLive.js.map +1 -0
- package/dist/esm/ui/UiRouter.js +235 -0
- package/dist/esm/ui/UiRouter.js.map +1 -0
- package/dist/esm/ui/admin/AdminLayout.js +29 -0
- package/dist/esm/ui/admin/AdminLayout.js.map +1 -0
- package/dist/esm/ui/admin/AdminUiRouter.js +148 -0
- package/dist/esm/ui/admin/AdminUiRouter.js.map +1 -0
- package/dist/esm/ui/admin/pages/AdminDashboard.js +48 -0
- package/dist/esm/ui/admin/pages/AdminDashboard.js.map +1 -0
- package/dist/esm/ui/admin/partials.js +54 -0
- package/dist/esm/ui/admin/partials.js.map +1 -0
- package/dist/esm/ui/html.js +32 -0
- package/dist/esm/ui/html.js.map +1 -0
- package/dist/esm/ui/layout.js +32 -0
- package/dist/esm/ui/layout.js.map +1 -0
- package/dist/esm/ui/pages/dashboard.js +44 -0
- package/dist/esm/ui/pages/dashboard.js.map +1 -0
- package/dist/esm/ui/pages/request-detail.js +112 -0
- package/dist/esm/ui/pages/request-detail.js.map +1 -0
- package/dist/esm/ui/pages/requests.js +112 -0
- package/dist/esm/ui/pages/requests.js.map +1 -0
- package/dist/esm/ui/pages/stubs.js +39 -0
- package/dist/esm/ui/pages/stubs.js.map +1 -0
- package/dist/esm/ui/partials.js +91 -0
- package/dist/esm/ui/partials.js.map +1 -0
- package/domain/imposter/package.json +6 -0
- package/domain/route/package.json +6 -0
- package/layers/ApiLayer/package.json +6 -0
- package/layers/MainLayer/package.json +6 -0
- package/matching/ExpressionEvaluator/package.json +6 -0
- package/matching/RequestMatcher/package.json +6 -0
- package/matching/ResponseGenerator/package.json +6 -0
- package/matching/TemplateEngine/package.json +6 -0
- package/package.json +435 -0
- package/repositories/ImposterRepository/package.json +6 -0
- package/schemas/ConfigFileSchema/package.json +6 -0
- package/schemas/ImposterSchema/package.json +6 -0
- package/schemas/RequestLogSchema/package.json +6 -0
- package/schemas/StubSchema/package.json +6 -0
- package/schemas/common/package.json +6 -0
- package/server/AdminServer/package.json +6 -0
- package/server/BunServer/package.json +6 -0
- package/server/FiberManager/package.json +6 -0
- package/server/ImposterServer/package.json +6 -0
- package/services/AppConfig/package.json +6 -0
- package/services/MetricsService/package.json +6 -0
- package/services/PortAllocator/package.json +6 -0
- package/services/ProxyService/package.json +6 -0
- package/services/RequestLogger/package.json +6 -0
- package/services/Uuid/package.json +6 -0
- package/services/UuidLive/package.json +6 -0
- package/src/Program.ts +1 -0
- package/src/api/AdminApi.ts +7 -0
- package/src/api/ApiErrors.ts +20 -0
- package/src/api/ApiSchemas.ts +36 -0
- package/src/api/Conversions.ts +34 -0
- package/src/api/ImpostersGroup.ts +103 -0
- package/src/api/ImpostersHandlers.ts +387 -0
- package/src/api/SystemGroup.ts +12 -0
- package/src/api/SystemHandlers.ts +76 -0
- package/src/cli/Commands.ts +119 -0
- package/src/cli/ConfigLoader.ts +41 -0
- package/src/client/HandlerHttpClient.ts +50 -0
- package/src/client/ImpostersClient.ts +21 -0
- package/src/client/index.ts +9 -0
- package/src/client/testing.ts +105 -0
- package/src/domain/imposter.ts +186 -0
- package/src/domain/route.ts +255 -0
- package/src/index.ts +153 -0
- package/src/layers/ApiLayer.ts +21 -0
- package/src/layers/MainLayer.ts +43 -0
- package/src/matching/ExpressionEvaluator.ts +102 -0
- package/src/matching/RequestMatcher.ts +162 -0
- package/src/matching/ResponseGenerator.ts +86 -0
- package/src/matching/TemplateEngine.ts +54 -0
- package/src/repositories/ImposterRepository.ts +145 -0
- package/src/schemas/ConfigFileSchema.ts +32 -0
- package/src/schemas/ImposterSchema.ts +232 -0
- package/src/schemas/RequestLogSchema.ts +38 -0
- package/src/schemas/StubSchema.ts +90 -0
- package/src/schemas/common.ts +95 -0
- package/src/server/AdminServer.ts +22 -0
- package/src/server/BunServer.ts +19 -0
- package/src/server/FiberManager.ts +25 -0
- package/src/server/ImposterServer.ts +244 -0
- package/src/services/AppConfig.ts +22 -0
- package/src/services/MetricsService.ts +157 -0
- package/src/services/PortAllocator.ts +68 -0
- package/src/services/ProxyService.ts +139 -0
- package/src/services/RequestLogger.ts +87 -0
- package/src/services/Uuid.ts +9 -0
- package/src/services/UuidLive.ts +9 -0
- package/src/types/bun.d.ts +6 -0
- package/src/ui/UiRouter.ts +278 -0
- package/src/ui/admin/AdminLayout.ts +36 -0
- package/src/ui/admin/AdminUiRouter.ts +170 -0
- package/src/ui/admin/pages/AdminDashboard.ts +54 -0
- package/src/ui/admin/partials.ts +83 -0
- package/src/ui/html.ts +37 -0
- package/src/ui/layout.ts +44 -0
- package/src/ui/pages/dashboard.ts +64 -0
- package/src/ui/pages/request-detail.ts +142 -0
- package/src/ui/pages/requests.ts +141 -0
- package/src/ui/pages/stubs.ts +52 -0
- package/src/ui/partials.ts +133 -0
- package/ui/UiRouter/package.json +6 -0
- package/ui/admin/AdminLayout/package.json +6 -0
- package/ui/admin/AdminUiRouter/package.json +6 -0
- package/ui/admin/pages/AdminDashboard/package.json +6 -0
- package/ui/admin/partials/package.json +6 -0
- package/ui/html/package.json +6 -0
- package/ui/layout/package.json +6 -0
- package/ui/pages/dashboard/package.json +6 -0
- package/ui/pages/requests/package.json +6 -0
- package/ui/pages/stubs/package.json +6 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Clock, DateTime, Effect } from "effect";
|
|
2
|
+
import * as Duration from "effect/Duration";
|
|
3
|
+
import * as Schema from "effect/Schema";
|
|
4
|
+
// Common enums
|
|
5
|
+
export const ImposterStatus = /*#__PURE__*/Schema.Literal("running", "stopped", "starting", "stopping");
|
|
6
|
+
export const Protocol = /*#__PURE__*/Schema.Literal("HTTP");
|
|
7
|
+
// Utility schemas for validation
|
|
8
|
+
export const PositiveInteger = /*#__PURE__*/Schema.Number.pipe(/*#__PURE__*/Schema.int(), /*#__PURE__*/Schema.positive(), /*#__PURE__*/Schema.brand("PositiveInteger"));
|
|
9
|
+
export const NonEmptyString = /*#__PURE__*/Schema.String.pipe(/*#__PURE__*/Schema.minLength(1), /*#__PURE__*/Schema.brand("NonEmptyString"));
|
|
10
|
+
export const PortNumber = /*#__PURE__*/Schema.Number.pipe(/*#__PURE__*/Schema.int(), /*#__PURE__*/Schema.between(1024, 65535), /*#__PURE__*/Schema.brand("PortNumber"));
|
|
11
|
+
export const PaginationQuery = /*#__PURE__*/Schema.Struct({
|
|
12
|
+
// PositiveInteger.make() is safe here — 50 is a compile-time constant that always passes validation
|
|
13
|
+
limit: /*#__PURE__*/Schema.optionalWith(PositiveInteger, {
|
|
14
|
+
default: () => PositiveInteger.make(50)
|
|
15
|
+
}),
|
|
16
|
+
offset: /*#__PURE__*/Schema.optionalWith(/*#__PURE__*/Schema.Number.pipe(/*#__PURE__*/Schema.int(), /*#__PURE__*/Schema.nonNegative()), {
|
|
17
|
+
default: () => 0
|
|
18
|
+
})
|
|
19
|
+
});
|
|
20
|
+
export const PaginationMeta = /*#__PURE__*/Schema.Struct({
|
|
21
|
+
total: /*#__PURE__*/Schema.Number.pipe(/*#__PURE__*/Schema.int(), /*#__PURE__*/Schema.nonNegative()),
|
|
22
|
+
limit: PositiveInteger,
|
|
23
|
+
offset: /*#__PURE__*/Schema.Number.pipe(/*#__PURE__*/Schema.int(), /*#__PURE__*/Schema.nonNegative()),
|
|
24
|
+
hasMore: Schema.Boolean
|
|
25
|
+
});
|
|
26
|
+
export const ErrorCode = /*#__PURE__*/Schema.Union(/*#__PURE__*/
|
|
27
|
+
// Validation errors
|
|
28
|
+
Schema.Literal("VALIDATION_ERROR"), /*#__PURE__*/Schema.Literal("INVALID_ENDPOINT"), /*#__PURE__*/
|
|
29
|
+
// Resource errors
|
|
30
|
+
Schema.Literal("IMPOSTER_NOT_FOUND"), /*#__PURE__*/Schema.Literal("PORT_IN_USE"), /*#__PURE__*/Schema.Literal("IMPOSTER_BUSY"), /*#__PURE__*/
|
|
31
|
+
// System errors
|
|
32
|
+
Schema.Literal("SYSTEM_ERROR"), /*#__PURE__*/Schema.Literal("CONFIRMATION_REQUIRED"), /*#__PURE__*/
|
|
33
|
+
// Conflict errors
|
|
34
|
+
Schema.Literal("ENDPOINT_CONFLICT"));
|
|
35
|
+
export const ErrorDetails = /*#__PURE__*/Schema.Struct({
|
|
36
|
+
code: ErrorCode,
|
|
37
|
+
message: NonEmptyString,
|
|
38
|
+
field: /*#__PURE__*/Schema.optional(Schema.String),
|
|
39
|
+
value: /*#__PURE__*/Schema.optional(Schema.Unknown),
|
|
40
|
+
details: /*#__PURE__*/Schema.optional(/*#__PURE__*/Schema.Record({
|
|
41
|
+
key: Schema.String,
|
|
42
|
+
value: Schema.Unknown
|
|
43
|
+
}))
|
|
44
|
+
});
|
|
45
|
+
export const ErrorResponse = /*#__PURE__*/Schema.Struct({
|
|
46
|
+
error: ErrorDetails
|
|
47
|
+
});
|
|
48
|
+
// Common query filters
|
|
49
|
+
export const StatusFilter = /*#__PURE__*/Schema.optional(ImposterStatus);
|
|
50
|
+
export const ProtocolFilter = /*#__PURE__*/Schema.optional(Protocol);
|
|
51
|
+
// DateTime schemas using Effect's DateTime
|
|
52
|
+
export const DateTimeSchema = Schema.DateTimeUtc;
|
|
53
|
+
// Helper to create current DateTime
|
|
54
|
+
export const currentDateTime = /*#__PURE__*/Effect.map(Clock.currentTimeMillis, ms => DateTime.unsafeMake(ms));
|
|
55
|
+
// Helper to format duration as uptime string (HH:MM:SS)
|
|
56
|
+
export const formatDurationAsUptime = duration => {
|
|
57
|
+
return Duration.format(duration);
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","names":["Clock","DateTime","Effect","Duration","Schema","ImposterStatus","Literal","Protocol","PositiveInteger","Number","pipe","int","positive","brand","NonEmptyString","String","minLength","PortNumber","between","PaginationQuery","Struct","limit","optionalWith","default","make","offset","nonNegative","PaginationMeta","total","hasMore","Boolean","ErrorCode","Union","ErrorDetails","code","message","field","optional","value","Unknown","details","Record","key","ErrorResponse","error","StatusFilter","ProtocolFilter","DateTimeSchema","DateTimeUtc","currentDateTime","map","currentTimeMillis","ms","unsafeMake","formatDurationAsUptime","duration","format"],"sources":["../../../src/schemas/common.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { HttpApiBuilder } from "@effect/platform";
|
|
2
|
+
import * as Layer from "effect/Layer";
|
|
3
|
+
import { ApiLayer } from "../layers/ApiLayer";
|
|
4
|
+
import { MainLayer } from "../layers/MainLayer";
|
|
5
|
+
import { makeAdminUiRouter } from "../ui/admin/AdminUiRouter";
|
|
6
|
+
export const FullLayer = /*#__PURE__*/ApiLayer.pipe(/*#__PURE__*/Layer.provide(MainLayer));
|
|
7
|
+
export const makeWebHandler = () => HttpApiBuilder.toWebHandler(FullLayer);
|
|
8
|
+
export const makeCompositeHandler = adminPort => {
|
|
9
|
+
const {
|
|
10
|
+
dispose,
|
|
11
|
+
handler: apiHandler
|
|
12
|
+
} = HttpApiBuilder.toWebHandler(FullLayer);
|
|
13
|
+
const adminUiRouter = makeAdminUiRouter({
|
|
14
|
+
apiHandler,
|
|
15
|
+
adminPort
|
|
16
|
+
});
|
|
17
|
+
const handler = async request => {
|
|
18
|
+
const uiResponse = await adminUiRouter(request);
|
|
19
|
+
if (uiResponse !== null) return uiResponse;
|
|
20
|
+
return apiHandler(request);
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
handler,
|
|
24
|
+
dispose
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=AdminServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdminServer.js","names":["HttpApiBuilder","Layer","ApiLayer","MainLayer","makeAdminUiRouter","FullLayer","pipe","provide","makeWebHandler","toWebHandler","makeCompositeHandler","adminPort","dispose","handler","apiHandler","adminUiRouter","request","uiResponse"],"sources":["../../../src/server/AdminServer.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,cAAc,QAAQ,kBAAkB;AACjD,OAAO,KAAKC,KAAK,MAAM,cAAc;AACrC,SAASC,QAAQ,QAAQ,oBAAoB;AAC7C,SAASC,SAAS,QAAQ,qBAAqB;AAC/C,SAASC,iBAAiB,QAAQ,2BAA2B;AAE7D,OAAO,MAAMC,SAAS,gBAAGH,QAAQ,CAACI,IAAI,cAACL,KAAK,CAACM,OAAO,CAACJ,SAAS,CAAC,CAAC;AAEhE,OAAO,MAAMK,cAAc,GAAGA,CAAA,KAAMR,cAAc,CAACS,YAAY,CAACJ,SAAS,CAAC;AAE1E,OAAO,MAAMK,oBAAoB,GAAIC,SAAiB,IAAI;EACxD,MAAM;IAAEC,OAAO;IAAEC,OAAO,EAAEC;EAAU,CAAE,GAAGd,cAAc,CAACS,YAAY,CAACJ,SAAS,CAAC;EAC/E,MAAMU,aAAa,GAAGX,iBAAiB,CAAC;IAAEU,UAAU;IAAEH;EAAS,CAAE,CAAC;EAElE,MAAME,OAAO,GAAG,MAAOG,OAAgB,IAAuB;IAC5D,MAAMC,UAAU,GAAG,MAAMF,aAAa,CAACC,OAAO,CAAC;IAC/C,IAAIC,UAAU,KAAK,IAAI,EAAE,OAAOA,UAAU;IAC1C,OAAOH,UAAU,CAACE,OAAO,CAAC;EAC5B,CAAC;EAED,OAAO;IAAEH,OAAO;IAAED;EAAO,CAAE;AAC7B,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Context, Layer } from "effect";
|
|
2
|
+
export class ServerFactory extends Context.Tag("ServerFactory")() {}
|
|
3
|
+
export const BunServerFactoryLive = /*#__PURE__*/Layer.succeed(ServerFactory, {
|
|
4
|
+
create: options => Bun.serve(options)
|
|
5
|
+
});
|
|
6
|
+
//# sourceMappingURL=BunServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BunServer.js","names":["Context","Layer","ServerFactory","Tag","BunServerFactoryLive","succeed","create","options","Bun","serve"],"sources":["../../../src/server/BunServer.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,OAAO,EAAEC,KAAK,QAAQ,QAAQ;AAcvC,OAAM,MAAOC,aAAc,SAAQF,OAAO,CAACG,GAAG,CAAC,eAAe,CAAC,EAAqC;AAEpG,OAAO,MAAMC,oBAAoB,gBAAGH,KAAK,CAACI,OAAO,CAACH,aAAa,EAAE;EAC/DI,MAAM,EAAGC,OAAO,IAAKC,GAAG,CAACC,KAAK,CAACF,OAAO;CACvC,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Context, Effect, FiberMap, Layer } from "effect";
|
|
2
|
+
export class FiberManager extends Context.Tag("FiberManager")() {}
|
|
3
|
+
export const FiberManagerLive = /*#__PURE__*/Layer.scoped(FiberManager, /*#__PURE__*/Effect.gen(function* () {
|
|
4
|
+
const fiberMap = yield* FiberMap.make();
|
|
5
|
+
const start = (id, effect) => FiberMap.run(fiberMap, id, effect);
|
|
6
|
+
const stop = id => FiberMap.remove(fiberMap, id);
|
|
7
|
+
const isRunning = id => FiberMap.has(fiberMap, id);
|
|
8
|
+
return {
|
|
9
|
+
start,
|
|
10
|
+
stop,
|
|
11
|
+
isRunning
|
|
12
|
+
};
|
|
13
|
+
}));
|
|
14
|
+
//# sourceMappingURL=FiberManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FiberManager.js","names":["Context","Effect","FiberMap","Layer","FiberManager","Tag","FiberManagerLive","scoped","gen","fiberMap","make","start","id","effect","run","stop","remove","isRunning","has"],"sources":["../../../src/server/FiberManager.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,OAAO,EAAEC,MAAM,EAAEC,QAAQ,EAAEC,KAAK,QAAQ,QAAQ;AAQzD,OAAM,MAAOC,YAAa,SAAQJ,OAAO,CAACK,GAAG,CAAC,cAAc,CAAC,EAAmC;AAEhG,OAAO,MAAMC,gBAAgB,gBAAGH,KAAK,CAACI,MAAM,CAC1CH,YAAY,eACZH,MAAM,CAACO,GAAG,CAAC,aAAS;EAClB,MAAMC,QAAQ,GAAG,OAAOP,QAAQ,CAACQ,IAAI,EAAU;EAE/C,MAAMC,KAAK,GAAGA,CAACC,EAAU,EAAEC,MAAqC,KAC9DX,QAAQ,CAACY,GAAG,CAACL,QAAQ,EAAEG,EAAE,EAAEC,MAAM,CAAC;EAEpC,MAAME,IAAI,GAAIH,EAAU,IAA0BV,QAAQ,CAACc,MAAM,CAACP,QAAQ,EAAEG,EAAE,CAAC;EAE/E,MAAMK,SAAS,GAAIL,EAAU,IAA6BV,QAAQ,CAACgB,GAAG,CAACT,QAAQ,EAAEG,EAAE,CAAC;EAEpF,OAAO;IAAED,KAAK;IAAEI,IAAI;IAAEE;EAAS,CAAE;AACnC,CAAC,CAAC,CACH","ignoreList":[]}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { Context, Data, Effect, HashMap, Layer, Ref, Runtime } from "effect";
|
|
2
|
+
import * as DateTime from "effect/DateTime";
|
|
3
|
+
import { ImposterConfig } from "../domain/imposter";
|
|
4
|
+
import { extractRequestContext, findMatchingStub } from "../matching/RequestMatcher";
|
|
5
|
+
import { buildResponse, makeResponseState } from "../matching/ResponseGenerator";
|
|
6
|
+
import { ImposterRepository } from "../repositories/ImposterRepository";
|
|
7
|
+
import { NonEmptyString } from "../schemas/common";
|
|
8
|
+
import { MetricsService } from "../services/MetricsService";
|
|
9
|
+
import { ProxyService } from "../services/ProxyService";
|
|
10
|
+
import { RequestLogger } from "../services/RequestLogger";
|
|
11
|
+
import { makeUiRouter } from "../ui/UiRouter";
|
|
12
|
+
import { ServerFactory } from "./BunServer";
|
|
13
|
+
import { FiberManager } from "./FiberManager";
|
|
14
|
+
export class ImposterServerError extends Data.TaggedError("ImposterServerError") {}
|
|
15
|
+
export class ImposterServer extends Context.Tag("ImposterServer")() {}
|
|
16
|
+
export const ImposterServerLive = /*#__PURE__*/Layer.effect(ImposterServer, /*#__PURE__*/Effect.gen(function* () {
|
|
17
|
+
const repo = yield* ImposterRepository;
|
|
18
|
+
const fiberManager = yield* FiberManager;
|
|
19
|
+
const serverFactory = yield* ServerFactory;
|
|
20
|
+
const requestLogger = yield* RequestLogger;
|
|
21
|
+
const metricsService = yield* MetricsService;
|
|
22
|
+
const proxyService = yield* ProxyService;
|
|
23
|
+
const stateMapRef = yield* Ref.make(HashMap.empty());
|
|
24
|
+
const start = id => Effect.gen(function* () {
|
|
25
|
+
const record = yield* repo.get(id);
|
|
26
|
+
const config = record.config;
|
|
27
|
+
// Create per-imposter state
|
|
28
|
+
const stubsRef = yield* Ref.make(record.stubs);
|
|
29
|
+
const proxyConfigRef = yield* Ref.make(config.proxy);
|
|
30
|
+
const responseState = yield* makeResponseState();
|
|
31
|
+
// Store state for hot-reload
|
|
32
|
+
yield* Ref.update(stateMapRef, HashMap.set(id, {
|
|
33
|
+
stubsRef,
|
|
34
|
+
proxyConfigRef
|
|
35
|
+
}));
|
|
36
|
+
// Capture runtime for running effects inside fetch handler
|
|
37
|
+
const rt = yield* Effect.runtime();
|
|
38
|
+
const runPromise = Runtime.runPromise(rt);
|
|
39
|
+
// UI router for /_admin pages
|
|
40
|
+
const uiRouter = makeUiRouter({
|
|
41
|
+
id,
|
|
42
|
+
config,
|
|
43
|
+
stubsRef,
|
|
44
|
+
repo,
|
|
45
|
+
requestLogger,
|
|
46
|
+
runPromise
|
|
47
|
+
});
|
|
48
|
+
const handler = async request => {
|
|
49
|
+
// Try UI router first (returns null if not a /_admin path)
|
|
50
|
+
const uiResponse = await uiRouter(request);
|
|
51
|
+
if (uiResponse !== null) return uiResponse;
|
|
52
|
+
return runPromise(Effect.gen(function* () {
|
|
53
|
+
const startTime = Date.now();
|
|
54
|
+
const stubs = yield* Ref.get(stubsRef);
|
|
55
|
+
const ctx = yield* Effect.promise(() => extractRequestContext(request));
|
|
56
|
+
const stub = findMatchingStub(ctx, stubs);
|
|
57
|
+
let response;
|
|
58
|
+
let proxied = false;
|
|
59
|
+
if (!stub) {
|
|
60
|
+
const proxyConfig = yield* Ref.get(proxyConfigRef);
|
|
61
|
+
if (proxyConfig) {
|
|
62
|
+
const url = new URL(request.url);
|
|
63
|
+
response = yield* proxyService.forward(ctx, proxyConfig, url).pipe(Effect.catchTag("ProxyError", err => Effect.succeed(new Response(JSON.stringify({
|
|
64
|
+
error: "Proxy failed",
|
|
65
|
+
target: err.targetUrl,
|
|
66
|
+
reason: err.reason
|
|
67
|
+
}), {
|
|
68
|
+
status: 502,
|
|
69
|
+
headers: {
|
|
70
|
+
"content-type": "application/json"
|
|
71
|
+
}
|
|
72
|
+
}))));
|
|
73
|
+
proxied = true;
|
|
74
|
+
// Record mode: save as stub + update stubsRef
|
|
75
|
+
if (proxyConfig.mode === "record" && response.status < 500) {
|
|
76
|
+
const responseClone = response.clone();
|
|
77
|
+
const newStub = yield* proxyService.recordAsStub(ctx, responseClone);
|
|
78
|
+
yield* repo.addStub(id, newStub).pipe(Effect.catchAll(() => Effect.void));
|
|
79
|
+
const freshStubs = yield* repo.getStubs(id).pipe(Effect.catchAll(() => Effect.succeed([])));
|
|
80
|
+
yield* Ref.set(stubsRef, freshStubs);
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
response = new Response(JSON.stringify({
|
|
84
|
+
error: "No matching stub found",
|
|
85
|
+
method: ctx.method,
|
|
86
|
+
path: ctx.path
|
|
87
|
+
}), {
|
|
88
|
+
status: 404,
|
|
89
|
+
headers: {
|
|
90
|
+
"content-type": "application/json"
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
const responses = stub.responses;
|
|
96
|
+
const index = yield* responseState.getNextIndex(id, stub.id, responses.length, stub.responseMode);
|
|
97
|
+
const responseConfig = responses[index];
|
|
98
|
+
const delay = responseConfig.delay;
|
|
99
|
+
if (delay !== undefined && delay > 0) {
|
|
100
|
+
yield* Effect.sleep(`${delay} millis`);
|
|
101
|
+
}
|
|
102
|
+
response = yield* Effect.promise(() => buildResponse(responseConfig, ctx));
|
|
103
|
+
}
|
|
104
|
+
// Capture response for logging
|
|
105
|
+
const respText = yield* Effect.promise(() => response.text());
|
|
106
|
+
const respHeaders = {};
|
|
107
|
+
response.headers.forEach((val, key) => {
|
|
108
|
+
respHeaders[key] = val;
|
|
109
|
+
});
|
|
110
|
+
// Reconstruct since .text() consumed body
|
|
111
|
+
response = new Response(respText, {
|
|
112
|
+
status: response.status,
|
|
113
|
+
headers: response.headers
|
|
114
|
+
});
|
|
115
|
+
const logBody = respText.length > 10240 ? respText.slice(0, 10240) : respText || undefined;
|
|
116
|
+
const duration = Date.now() - startTime;
|
|
117
|
+
const logEntry = {
|
|
118
|
+
id: NonEmptyString.make(crypto.randomUUID()),
|
|
119
|
+
imposterId: NonEmptyString.make(id),
|
|
120
|
+
timestamp: DateTime.unsafeMake(startTime),
|
|
121
|
+
request: {
|
|
122
|
+
method: ctx.method,
|
|
123
|
+
path: ctx.path,
|
|
124
|
+
headers: ctx.headers,
|
|
125
|
+
query: ctx.query,
|
|
126
|
+
body: ctx.body
|
|
127
|
+
},
|
|
128
|
+
response: {
|
|
129
|
+
status: response.status,
|
|
130
|
+
headers: respHeaders,
|
|
131
|
+
...(logBody !== undefined ? {
|
|
132
|
+
body: logBody
|
|
133
|
+
} : {}),
|
|
134
|
+
...(stub ? {
|
|
135
|
+
matchedStubId: NonEmptyString.make(stub.id)
|
|
136
|
+
} : {}),
|
|
137
|
+
proxied
|
|
138
|
+
},
|
|
139
|
+
duration
|
|
140
|
+
};
|
|
141
|
+
yield* requestLogger.log(logEntry).pipe(Effect.catchAll(() => Effect.void));
|
|
142
|
+
yield* metricsService.recordRequest(logEntry).pipe(Effect.catchAll(() => Effect.void));
|
|
143
|
+
return response;
|
|
144
|
+
}).pipe(Effect.catchAllCause(cause => Effect.succeed(new Response(JSON.stringify({
|
|
145
|
+
error: "Internal server error",
|
|
146
|
+
details: String(cause)
|
|
147
|
+
}), {
|
|
148
|
+
status: 500,
|
|
149
|
+
headers: {
|
|
150
|
+
"content-type": "application/json"
|
|
151
|
+
}
|
|
152
|
+
})))));
|
|
153
|
+
};
|
|
154
|
+
// Build the long-running fiber effect with acquireRelease
|
|
155
|
+
const fiberEffect = Effect.acquireRelease(Effect.try({
|
|
156
|
+
try: () => serverFactory.create({
|
|
157
|
+
port: config.port,
|
|
158
|
+
fetch: handler
|
|
159
|
+
}),
|
|
160
|
+
catch: err => new ImposterServerError({
|
|
161
|
+
imposterId: id,
|
|
162
|
+
reason: `Failed to bind port ${config.port}: ${err}`
|
|
163
|
+
})
|
|
164
|
+
}), server => Effect.sync(() => server.stop(true))).pipe(Effect.andThen(Effect.never), Effect.scoped);
|
|
165
|
+
// Wrap fiber in onError for crash supervision
|
|
166
|
+
const supervisedEffect = fiberEffect.pipe(Effect.onError(() => Effect.gen(function* () {
|
|
167
|
+
yield* Ref.update(stateMapRef, HashMap.remove(id));
|
|
168
|
+
yield* repo.update(id, r => ({
|
|
169
|
+
...r,
|
|
170
|
+
config: ImposterConfig({
|
|
171
|
+
...r.config,
|
|
172
|
+
status: "stopped"
|
|
173
|
+
})
|
|
174
|
+
})).pipe(Effect.catchAll(() => Effect.void));
|
|
175
|
+
yield* responseState.reset(id);
|
|
176
|
+
})));
|
|
177
|
+
yield* fiberManager.start(id, supervisedEffect);
|
|
178
|
+
// Update status to running
|
|
179
|
+
yield* repo.update(id, r => ({
|
|
180
|
+
...r,
|
|
181
|
+
config: ImposterConfig({
|
|
182
|
+
...r.config,
|
|
183
|
+
status: "running"
|
|
184
|
+
})
|
|
185
|
+
})).pipe(Effect.catchTag("ImposterNotFoundError", () => Effect.void));
|
|
186
|
+
});
|
|
187
|
+
const stop = id => Effect.gen(function* () {
|
|
188
|
+
yield* fiberManager.stop(id);
|
|
189
|
+
yield* Ref.update(stateMapRef, HashMap.remove(id));
|
|
190
|
+
yield* repo.update(id, r => ({
|
|
191
|
+
...r,
|
|
192
|
+
config: ImposterConfig({
|
|
193
|
+
...r.config,
|
|
194
|
+
status: "stopped"
|
|
195
|
+
})
|
|
196
|
+
})).pipe(Effect.catchAll(() => Effect.void));
|
|
197
|
+
yield* requestLogger.removeImposter(id);
|
|
198
|
+
});
|
|
199
|
+
const updateStubs = id => Effect.gen(function* () {
|
|
200
|
+
const stubs = yield* repo.getStubs(id).pipe(Effect.catchAll(() => Effect.succeed([])));
|
|
201
|
+
const stateMap = yield* Ref.get(stateMapRef);
|
|
202
|
+
const state = HashMap.get(stateMap, id);
|
|
203
|
+
if (state._tag === "Some") {
|
|
204
|
+
yield* Ref.set(state.value.stubsRef, stubs);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
const updateProxyConfig = id => Effect.gen(function* () {
|
|
208
|
+
const record = yield* repo.get(id).pipe(Effect.catchAll(() => Effect.succeed(null)));
|
|
209
|
+
if (record === null) return;
|
|
210
|
+
const stateMap = yield* Ref.get(stateMapRef);
|
|
211
|
+
const state = HashMap.get(stateMap, id);
|
|
212
|
+
if (state._tag === "Some") {
|
|
213
|
+
yield* Ref.set(state.value.proxyConfigRef, record.config.proxy);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
const isRunning = id => fiberManager.isRunning(id);
|
|
217
|
+
return {
|
|
218
|
+
start,
|
|
219
|
+
stop,
|
|
220
|
+
updateStubs,
|
|
221
|
+
updateProxyConfig,
|
|
222
|
+
isRunning
|
|
223
|
+
};
|
|
224
|
+
}));
|
|
225
|
+
//# sourceMappingURL=ImposterServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImposterServer.js","names":["Context","Data","Effect","HashMap","Layer","Ref","Runtime","DateTime","ImposterConfig","extractRequestContext","findMatchingStub","buildResponse","makeResponseState","ImposterRepository","NonEmptyString","MetricsService","ProxyService","RequestLogger","makeUiRouter","ServerFactory","FiberManager","ImposterServerError","TaggedError","ImposterServer","Tag","ImposterServerLive","effect","gen","repo","fiberManager","serverFactory","requestLogger","metricsService","proxyService","stateMapRef","make","empty","start","id","record","get","config","stubsRef","stubs","proxyConfigRef","proxy","responseState","update","set","rt","runtime","runPromise","uiRouter","handler","request","uiResponse","startTime","Date","now","ctx","promise","stub","response","proxied","proxyConfig","url","URL","forward","pipe","catchTag","err","succeed","Response","JSON","stringify","error","target","targetUrl","reason","status","headers","mode","responseClone","clone","newStub","recordAsStub","addStub","catchAll","void","freshStubs","getStubs","method","path","responses","index","getNextIndex","length","responseMode","responseConfig","delay","undefined","sleep","respText","text","respHeaders","forEach","val","key","logBody","slice","duration","logEntry","crypto","randomUUID","imposterId","timestamp","unsafeMake","query","body","matchedStubId","log","recordRequest","catchAllCause","cause","details","String","fiberEffect","acquireRelease","try","create","port","fetch","catch","server","sync","stop","andThen","never","scoped","supervisedEffect","onError","remove","r","reset","removeImposter","updateStubs","stateMap","state","_tag","value","updateProxyConfig","isRunning"],"sources":["../../../src/server/ImposterServer.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,OAAO,EAAEC,IAAI,EAAEC,MAAM,EAAEC,OAAO,EAAEC,KAAK,EAAEC,GAAG,EAAEC,OAAO,QAAQ,QAAQ;AAC5E,OAAO,KAAKC,QAAQ,MAAM,iBAAiB;AAC3C,SAASC,cAAc,QAA4D,oBAAoB;AACvG,SAASC,qBAAqB,EAAEC,gBAAgB,QAAQ,4BAA4B;AACpF,SAASC,aAAa,EAAEC,iBAAiB,QAAQ,+BAA+B;AAChF,SAASC,kBAAkB,QAAQ,oCAAoC;AACvE,SAASC,cAAc,QAAQ,mBAAmB;AAGlD,SAASC,cAAc,QAAQ,4BAA4B;AAC3D,SAASC,YAAY,QAAQ,0BAA0B;AACvD,SAASC,aAAa,QAAQ,2BAA2B;AACzD,SAASC,YAAY,QAAQ,gBAAgB;AAC7C,SAASC,aAAa,QAAQ,aAAa;AAC3C,SAASC,YAAY,QAAQ,gBAAgB;AAE7C,OAAM,MAAOC,mBAAoB,SAAQpB,IAAI,CAACqB,WAAW,CAAC,qBAAqB,CAG7E;AAUF,OAAM,MAAOC,cAAe,SAAQvB,OAAO,CAACwB,GAAG,CAAC,gBAAgB,CAAC,EAAuC;AAOxG,OAAO,MAAMC,kBAAkB,gBAAGrB,KAAK,CAACsB,MAAM,CAC5CH,cAAc,eACdrB,MAAM,CAACyB,GAAG,CAAC,aAAS;EAClB,MAAMC,IAAI,GAAG,OAAOf,kBAAkB;EACtC,MAAMgB,YAAY,GAAG,OAAOT,YAAY;EACxC,MAAMU,aAAa,GAAG,OAAOX,aAAa;EAC1C,MAAMY,aAAa,GAAG,OAAOd,aAAa;EAC1C,MAAMe,cAAc,GAAG,OAAOjB,cAAc;EAC5C,MAAMkB,YAAY,GAAG,OAAOjB,YAAY;EACxC,MAAMkB,WAAW,GAAG,OAAO7B,GAAG,CAAC8B,IAAI,CAAyChC,OAAO,CAACiC,KAAK,EAAE,CAAC;EAE5F,MAAMC,KAAK,GAAIC,EAAU,IACvBpC,MAAM,CAACyB,GAAG,CAAC,aAAS;IAClB,MAAMY,MAAM,GAAG,OAAOX,IAAI,CAACY,GAAG,CAACF,EAAE,CAAC;IAClC,MAAMG,MAAM,GAAGF,MAAM,CAACE,MAAM;IAE5B;IACA,MAAMC,QAAQ,GAAG,OAAOrC,GAAG,CAAC8B,IAAI,CAAsBI,MAAM,CAACI,KAAK,CAAC;IACnE,MAAMC,cAAc,GAAG,OAAOvC,GAAG,CAAC8B,IAAI,CAAgCM,MAAM,CAACI,KAAK,CAAC;IACnF,MAAMC,aAAa,GAAG,OAAOlC,iBAAiB,EAAE;IAEhD;IACA,OAAOP,GAAG,CAAC0C,MAAM,CAACb,WAAW,EAAE/B,OAAO,CAAC6C,GAAG,CAACV,EAAE,EAAE;MAAEI,QAAQ;MAAEE;IAAc,CAAmB,CAAC,CAAC;IAE9F;IACA,MAAMK,EAAE,GAAG,OAAO/C,MAAM,CAACgD,OAAO,EAAS;IACzC,MAAMC,UAAU,GAAG7C,OAAO,CAAC6C,UAAU,CAACF,EAAE,CAAC;IAEzC;IACA,MAAMG,QAAQ,GAAGlC,YAAY,CAAC;MAAEoB,EAAE;MAAEG,MAAM;MAAEC,QAAQ;MAAEd,IAAI;MAAEG,aAAa;MAAEoB;IAAU,CAAE,CAAC;IAExF,MAAME,OAAO,GAAG,MAAOC,OAAgB,IAAuB;MAC5D;MACA,MAAMC,UAAU,GAAG,MAAMH,QAAQ,CAACE,OAAO,CAAC;MAC1C,IAAIC,UAAU,KAAK,IAAI,EAAE,OAAOA,UAAU;MAE1C,OAAOJ,UAAU,CACfjD,MAAM,CAACyB,GAAG,CAAC,aAAS;QAClB,MAAM6B,SAAS,GAAGC,IAAI,CAACC,GAAG,EAAE;QAC5B,MAAMf,KAAK,GAAG,OAAOtC,GAAG,CAACmC,GAAG,CAACE,QAAQ,CAAC;QACtC,MAAMiB,GAAG,GAAG,OAAOzD,MAAM,CAAC0D,OAAO,CAAC,MAAMnD,qBAAqB,CAAC6C,OAAO,CAAC,CAAC;QACvE,MAAMO,IAAI,GAAGnD,gBAAgB,CAACiD,GAAG,EAAEhB,KAAK,CAAC;QAEzC,IAAImB,QAAkB;QACtB,IAAIC,OAAO,GAAG,KAAK;QACnB,IAAI,CAACF,IAAI,EAAE;UACT,MAAMG,WAAW,GAAG,OAAO3D,GAAG,CAACmC,GAAG,CAACI,cAAc,CAAC;UAClD,IAAIoB,WAAW,EAAE;YACf,MAAMC,GAAG,GAAG,IAAIC,GAAG,CAACZ,OAAO,CAACW,GAAG,CAAC;YAChCH,QAAQ,GAAG,OAAO7B,YAAY,CAACkC,OAAO,CAACR,GAAG,EAAEK,WAAW,EAAEC,GAAG,CAAC,CAACG,IAAI,CAChElE,MAAM,CAACmE,QAAQ,CAAC,YAAY,EAAGC,GAAG,IAChCpE,MAAM,CAACqE,OAAO,CACZ,IAAIC,QAAQ,CACVC,IAAI,CAACC,SAAS,CAAC;cAAEC,KAAK,EAAE,cAAc;cAAEC,MAAM,EAAEN,GAAG,CAACO,SAAS;cAAEC,MAAM,EAAER,GAAG,CAACQ;YAAM,CAAE,CAAC,EACpF;cAAEC,MAAM,EAAE,GAAG;cAAEC,OAAO,EAAE;gBAAE,cAAc,EAAE;cAAkB;YAAE,CAAE,CACjE,CACF,CAAC,CACL;YACDjB,OAAO,GAAG,IAAI;YACd;YACA,IAAIC,WAAW,CAACiB,IAAI,KAAK,QAAQ,IAAInB,QAAQ,CAACiB,MAAM,GAAG,GAAG,EAAE;cAC1D,MAAMG,aAAa,GAAGpB,QAAQ,CAACqB,KAAK,EAAE;cACtC,MAAMC,OAAO,GAAG,OAAOnD,YAAY,CAACoD,YAAY,CAAC1B,GAAG,EAAEuB,aAAa,CAAC;cACpE,OAAOtD,IAAI,CAAC0D,OAAO,CAAChD,EAAE,EAAE8C,OAAO,CAAC,CAAChB,IAAI,CAAClE,MAAM,CAACqF,QAAQ,CAAC,MAAMrF,MAAM,CAACsF,IAAI,CAAC,CAAC;cACzE,MAAMC,UAAU,GAAG,OAAO7D,IAAI,CAAC8D,QAAQ,CAACpD,EAAE,CAAC,CAAC8B,IAAI,CAC9ClE,MAAM,CAACqF,QAAQ,CAAC,MAAMrF,MAAM,CAACqE,OAAO,CAAC,EAAyB,CAAC,CAAC,CACjE;cACD,OAAOlE,GAAG,CAAC2C,GAAG,CAACN,QAAQ,EAAE+C,UAAU,CAAC;YACtC;UACF,CAAC,MAAM;YACL3B,QAAQ,GAAG,IAAIU,QAAQ,CACrBC,IAAI,CAACC,SAAS,CAAC;cAAEC,KAAK,EAAE,wBAAwB;cAAEgB,MAAM,EAAEhC,GAAG,CAACgC,MAAM;cAAEC,IAAI,EAAEjC,GAAG,CAACiC;YAAI,CAAE,CAAC,EACvF;cAAEb,MAAM,EAAE,GAAG;cAAEC,OAAO,EAAE;gBAAE,cAAc,EAAE;cAAkB;YAAE,CAAE,CACjE;UACH;QACF,CAAC,MAAM;UACL,MAAMa,SAAS,GAAGhC,IAAI,CAACgC,SAAS;UAChC,MAAMC,KAAK,GAAG,OAAOhD,aAAa,CAACiD,YAAY,CAACzD,EAAE,EAAEuB,IAAI,CAACvB,EAAE,EAAEuD,SAAS,CAACG,MAAM,EAAEnC,IAAI,CAACoC,YAAY,CAAC;UACjG,MAAMC,cAAc,GAAGL,SAAS,CAACC,KAAK,CAAE;UACxC,MAAMK,KAAK,GAAGD,cAAc,CAACC,KAAK;UAClC,IAAIA,KAAK,KAAKC,SAAS,IAAID,KAAK,GAAG,CAAC,EAAE;YACpC,OAAOjG,MAAM,CAACmG,KAAK,CAAC,GAAGF,KAAK,SAAS,CAAC;UACxC;UACArC,QAAQ,GAAG,OAAO5D,MAAM,CAAC0D,OAAO,CAAC,MAAMjD,aAAa,CAACuF,cAAc,EAAEvC,GAAG,CAAC,CAAC;QAC5E;QAEA;QACA,MAAM2C,QAAQ,GAAG,OAAOpG,MAAM,CAAC0D,OAAO,CAAC,MAAME,QAAQ,CAACyC,IAAI,EAAE,CAAC;QAC7D,MAAMC,WAAW,GAA2B,EAAE;QAC9C1C,QAAQ,CAACkB,OAAO,CAACyB,OAAO,CAAC,CAACC,GAAG,EAAEC,GAAG,KAAI;UACpCH,WAAW,CAACG,GAAG,CAAC,GAAGD,GAAG;QACxB,CAAC,CAAC;QACF;QACA5C,QAAQ,GAAG,IAAIU,QAAQ,CAAC8B,QAAQ,EAAE;UAAEvB,MAAM,EAAEjB,QAAQ,CAACiB,MAAM;UAAEC,OAAO,EAAElB,QAAQ,CAACkB;QAAO,CAAE,CAAC;QAEzF,MAAM4B,OAAO,GAAGN,QAAQ,CAACN,MAAM,GAAG,KAAK,GAAGM,QAAQ,CAACO,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,GAAIP,QAAQ,IAAIF,SAAU;QAE5F,MAAMU,QAAQ,GAAGrD,IAAI,CAACC,GAAG,EAAE,GAAGF,SAAS;QACvC,MAAMuD,QAAQ,GAAoB;UAChCzE,EAAE,EAAExB,cAAc,CAACqB,IAAI,CAAC6E,MAAM,CAACC,UAAU,EAAE,CAAC;UAC5CC,UAAU,EAAEpG,cAAc,CAACqB,IAAI,CAACG,EAAE,CAAC;UACnC6E,SAAS,EAAE5G,QAAQ,CAAC6G,UAAU,CAAC5D,SAAS,CAAC;UACzCF,OAAO,EAAE;YACPqC,MAAM,EAAEhC,GAAG,CAACgC,MAAM;YAClBC,IAAI,EAAEjC,GAAG,CAACiC,IAAI;YACdZ,OAAO,EAAErB,GAAG,CAACqB,OAAO;YACpBqC,KAAK,EAAE1D,GAAG,CAAC0D,KAAK;YAChBC,IAAI,EAAE3D,GAAG,CAAC2D;WACX;UACDxD,QAAQ,EAAE;YACRiB,MAAM,EAAEjB,QAAQ,CAACiB,MAAM;YACvBC,OAAO,EAAEwB,WAAW;YACpB,IAAII,OAAO,KAAKR,SAAS,GAAG;cAAEkB,IAAI,EAAEV;YAAO,CAAE,GAAG,EAAE,CAAC;YACnD,IAAI/C,IAAI,GAAG;cAAE0D,aAAa,EAAEzG,cAAc,CAACqB,IAAI,CAAC0B,IAAI,CAACvB,EAAE;YAAC,CAAE,GAAG,EAAE,CAAC;YAChEyB;WACD;UACD+C;SACD;QACD,OAAO/E,aAAa,CAACyF,GAAG,CAACT,QAAQ,CAAC,CAAC3C,IAAI,CAAClE,MAAM,CAACqF,QAAQ,CAAC,MAAMrF,MAAM,CAACsF,IAAI,CAAC,CAAC;QAC3E,OAAOxD,cAAc,CAACyF,aAAa,CAACV,QAAQ,CAAC,CAAC3C,IAAI,CAAClE,MAAM,CAACqF,QAAQ,CAAC,MAAMrF,MAAM,CAACsF,IAAI,CAAC,CAAC;QAEtF,OAAO1B,QAAQ;MACjB,CAAC,CAAC,CAACM,IAAI,CACLlE,MAAM,CAACwH,aAAa,CAAEC,KAAK,IACzBzH,MAAM,CAACqE,OAAO,CACZ,IAAIC,QAAQ,CACVC,IAAI,CAACC,SAAS,CAAC;QAAEC,KAAK,EAAE,uBAAuB;QAAEiD,OAAO,EAAEC,MAAM,CAACF,KAAK;MAAC,CAAE,CAAC,EAC1E;QAAE5C,MAAM,EAAE,GAAG;QAAEC,OAAO,EAAE;UAAE,cAAc,EAAE;QAAkB;MAAE,CAAE,CACjE,CACF,CACF,CACF,CACF;IACH,CAAC;IAED;IACA,MAAM8C,WAAW,GAAG5H,MAAM,CAAC6H,cAAc,CACvC7H,MAAM,CAAC8H,GAAG,CAAC;MACTA,GAAG,EAAEA,CAAA,KAAMlG,aAAa,CAACmG,MAAM,CAAC;QAAEC,IAAI,EAAEzF,MAAM,CAACyF,IAAI;QAAEC,KAAK,EAAE9E;MAAO,CAAE,CAAC;MACtE+E,KAAK,EAAG9D,GAAG,IACT,IAAIjD,mBAAmB,CAAC;QAAE6F,UAAU,EAAE5E,EAAE;QAAEwC,MAAM,EAAE,uBAAuBrC,MAAM,CAACyF,IAAI,KAAK5D,GAAG;MAAE,CAAE;KACnG,CAAC,EACD+D,MAAM,IAAKnI,MAAM,CAACoI,IAAI,CAAC,MAAMD,MAAM,CAACE,IAAI,CAAC,IAAI,CAAC,CAAC,CACjD,CAACnE,IAAI,CACJlE,MAAM,CAACsI,OAAO,CAACtI,MAAM,CAACuI,KAAK,CAAC,EAC5BvI,MAAM,CAACwI,MAAM,CACd;IAED;IACA,MAAMC,gBAAgB,GAAGb,WAAW,CAAC1D,IAAI,CACvClE,MAAM,CAAC0I,OAAO,CAAC,MACb1I,MAAM,CAACyB,GAAG,CAAC,aAAS;MAClB,OAAOtB,GAAG,CAAC0C,MAAM,CAACb,WAAW,EAAE/B,OAAO,CAAC0I,MAAM,CAACvG,EAAE,CAAC,CAAC;MAClD,OAAOV,IAAI,CAACmB,MAAM,CAACT,EAAE,EAAGwG,CAAC,KAAM;QAC7B,GAAGA,CAAC;QACJrG,MAAM,EAAEjC,cAAc,CAAC;UAAE,GAAGsI,CAAC,CAACrG,MAAM;UAAEsC,MAAM,EAAE;QAAS,CAAE;OAC1D,CAAC,CAAC,CAACX,IAAI,CAAClE,MAAM,CAACqF,QAAQ,CAAC,MAAMrF,MAAM,CAACsF,IAAI,CAAC,CAAC;MAC5C,OAAO1C,aAAa,CAACiG,KAAK,CAACzG,EAAE,CAAC;IAChC,CAAC,CAAC,CACH,CAC+B;IAElC,OAAOT,YAAY,CAACQ,KAAK,CAACC,EAAE,EAAEqG,gBAAgB,CAAC;IAE/C;IACA,OAAO/G,IAAI,CAACmB,MAAM,CAACT,EAAE,EAAGwG,CAAC,KAAM;MAC7B,GAAGA,CAAC;MACJrG,MAAM,EAAEjC,cAAc,CAAC;QAAE,GAAGsI,CAAC,CAACrG,MAAM;QAAEsC,MAAM,EAAE;MAAS,CAAE;KAC1D,CAAC,CAAC,CAACX,IAAI,CAAClE,MAAM,CAACmE,QAAQ,CAAC,uBAAuB,EAAE,MAAMnE,MAAM,CAACsF,IAAI,CAAC,CAAC;EACvE,CAAC,CAAC;EAEJ,MAAM+C,IAAI,GAAIjG,EAAU,IACtBpC,MAAM,CAACyB,GAAG,CAAC,aAAS;IAClB,OAAOE,YAAY,CAAC0G,IAAI,CAACjG,EAAE,CAAC;IAC5B,OAAOjC,GAAG,CAAC0C,MAAM,CAACb,WAAW,EAAE/B,OAAO,CAAC0I,MAAM,CAACvG,EAAE,CAAC,CAAC;IAClD,OAAOV,IAAI,CAACmB,MAAM,CAACT,EAAE,EAAGwG,CAAC,KAAM;MAC7B,GAAGA,CAAC;MACJrG,MAAM,EAAEjC,cAAc,CAAC;QAAE,GAAGsI,CAAC,CAACrG,MAAM;QAAEsC,MAAM,EAAE;MAAS,CAAE;KAC1D,CAAC,CAAC,CAACX,IAAI,CAAClE,MAAM,CAACqF,QAAQ,CAAC,MAAMrF,MAAM,CAACsF,IAAI,CAAC,CAAC;IAC5C,OAAOzD,aAAa,CAACiH,cAAc,CAAC1G,EAAE,CAAC;EACzC,CAAC,CAAC;EAEJ,MAAM2G,WAAW,GAAI3G,EAAU,IAC7BpC,MAAM,CAACyB,GAAG,CAAC,aAAS;IAClB,MAAMgB,KAAK,GAAG,OAAOf,IAAI,CAAC8D,QAAQ,CAACpD,EAAE,CAAC,CAAC8B,IAAI,CAAClE,MAAM,CAACqF,QAAQ,CAAC,MAAMrF,MAAM,CAACqE,OAAO,CAAC,EAAyB,CAAC,CAAC,CAAC;IAC7G,MAAM2E,QAAQ,GAAG,OAAO7I,GAAG,CAACmC,GAAG,CAACN,WAAW,CAAC;IAC5C,MAAMiH,KAAK,GAAGhJ,OAAO,CAACqC,GAAG,CAAC0G,QAAQ,EAAE5G,EAAE,CAAC;IACvC,IAAI6G,KAAK,CAACC,IAAI,KAAK,MAAM,EAAE;MACzB,OAAO/I,GAAG,CAAC2C,GAAG,CAACmG,KAAK,CAACE,KAAK,CAAC3G,QAAQ,EAAEC,KAAK,CAAC;IAC7C;EACF,CAAC,CAAC;EAEJ,MAAM2G,iBAAiB,GAAIhH,EAAU,IACnCpC,MAAM,CAACyB,GAAG,CAAC,aAAS;IAClB,MAAMY,MAAM,GAAG,OAAOX,IAAI,CAACY,GAAG,CAACF,EAAE,CAAC,CAAC8B,IAAI,CAAClE,MAAM,CAACqF,QAAQ,CAAC,MAAMrF,MAAM,CAACqE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpF,IAAIhC,MAAM,KAAK,IAAI,EAAE;IACrB,MAAM2G,QAAQ,GAAG,OAAO7I,GAAG,CAACmC,GAAG,CAACN,WAAW,CAAC;IAC5C,MAAMiH,KAAK,GAAGhJ,OAAO,CAACqC,GAAG,CAAC0G,QAAQ,EAAE5G,EAAE,CAAC;IACvC,IAAI6G,KAAK,CAACC,IAAI,KAAK,MAAM,EAAE;MACzB,OAAO/I,GAAG,CAAC2C,GAAG,CAACmG,KAAK,CAACE,KAAK,CAACzG,cAAc,EAAEL,MAAM,CAACE,MAAM,CAACI,KAAK,CAAC;IACjE;EACF,CAAC,CAAC;EAEJ,MAAM0G,SAAS,GAAIjH,EAAU,IAA6BT,YAAY,CAAC0H,SAAS,CAACjH,EAAE,CAAC;EAEpF,OAAO;IAAED,KAAK;IAAEkG,IAAI;IAAEU,WAAW;IAAEK,iBAAiB;IAAEC;EAAS,CAAgC;AACjG,CAAC,CAAC,CACH","ignoreList":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Config, Context, Layer } from "effect";
|
|
2
|
+
export class AppConfig extends Context.Tag("AppConfig")() {}
|
|
3
|
+
const config = /*#__PURE__*/Config.all({
|
|
4
|
+
adminPort: /*#__PURE__*/Config.number("ADMIN_PORT").pipe(/*#__PURE__*/Config.withDefault(2525)),
|
|
5
|
+
portRangeMin: /*#__PURE__*/Config.number("PORT_RANGE_MIN").pipe(/*#__PURE__*/Config.withDefault(3000)),
|
|
6
|
+
portRangeMax: /*#__PURE__*/Config.number("PORT_RANGE_MAX").pipe(/*#__PURE__*/Config.withDefault(4000)),
|
|
7
|
+
maxImposters: /*#__PURE__*/Config.number("MAX_IMPOSTERS").pipe(/*#__PURE__*/Config.withDefault(100)),
|
|
8
|
+
logLevel: /*#__PURE__*/Config.literal("debug", "info", "warn", "error")("LOG_LEVEL").pipe(/*#__PURE__*/Config.withDefault("info"))
|
|
9
|
+
});
|
|
10
|
+
export const AppConfigLive = /*#__PURE__*/Layer.effect(AppConfig, config);
|
|
11
|
+
//# sourceMappingURL=AppConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AppConfig.js","names":["Config","Context","Layer","AppConfig","Tag","config","all","adminPort","number","pipe","withDefault","portRangeMin","portRangeMax","maxImposters","logLevel","literal","AppConfigLive","effect"],"sources":["../../../src/services/AppConfig.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,MAAM,EAAEC,OAAO,EAAEC,KAAK,QAAQ,QAAQ;AAU/C,OAAM,MAAOC,SAAU,SAAQF,OAAO,CAACG,GAAG,CAAC,WAAW,CAAC,EAA6B;AAEpF,MAAMC,MAAM,gBAAGL,MAAM,CAACM,GAAG,CAAC;EACxBC,SAAS,eAAEP,MAAM,CAACQ,MAAM,CAAC,YAAY,CAAC,CAACC,IAAI,cAACT,MAAM,CAACU,WAAW,CAAC,IAAI,CAAC,CAAC;EACrEC,YAAY,eAAEX,MAAM,CAACQ,MAAM,CAAC,gBAAgB,CAAC,CAACC,IAAI,cAACT,MAAM,CAACU,WAAW,CAAC,IAAI,CAAC,CAAC;EAC5EE,YAAY,eAAEZ,MAAM,CAACQ,MAAM,CAAC,gBAAgB,CAAC,CAACC,IAAI,cAACT,MAAM,CAACU,WAAW,CAAC,IAAI,CAAC,CAAC;EAC5EG,YAAY,eAAEb,MAAM,CAACQ,MAAM,CAAC,eAAe,CAAC,CAACC,IAAI,cAACT,MAAM,CAACU,WAAW,CAAC,GAAG,CAAC,CAAC;EAC1EI,QAAQ,eAAEd,MAAM,CAACe,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,WAAW,CAAC,CACpEN,IAAI,cAACT,MAAM,CAACU,WAAW,CAAC,MAAe,CAAC;CAC5C,CAAC;AAEF,OAAO,MAAMM,aAAa,gBAAGd,KAAK,CAACe,MAAM,CAACd,SAAS,EAAEE,MAAM,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Context, Effect, HashMap, Layer, Ref } from "effect";
|
|
2
|
+
import * as DateTime from "effect/DateTime";
|
|
3
|
+
const BUFFER_SIZE = 1000;
|
|
4
|
+
const makeEmptyMetrics = now => ({
|
|
5
|
+
totalRequests: 0,
|
|
6
|
+
requestsByMethod: {},
|
|
7
|
+
requestsByStatusCode: {},
|
|
8
|
+
responseTimes: new Float64Array(BUFFER_SIZE),
|
|
9
|
+
responseTimeIndex: 0,
|
|
10
|
+
responseTimeCount: 0,
|
|
11
|
+
firstRequestAt: now,
|
|
12
|
+
lastRequestAt: now,
|
|
13
|
+
errorCount: 0
|
|
14
|
+
});
|
|
15
|
+
const computePercentile = (sorted, p) => {
|
|
16
|
+
if (sorted.length === 0) return 0;
|
|
17
|
+
const index = Math.ceil(p / 100 * sorted.length) - 1;
|
|
18
|
+
return sorted[Math.max(0, index)];
|
|
19
|
+
};
|
|
20
|
+
const computeStats = metrics => {
|
|
21
|
+
const count = metrics.responseTimeCount;
|
|
22
|
+
const total = metrics.totalRequests;
|
|
23
|
+
// Compute average response time
|
|
24
|
+
let sumRT = 0;
|
|
25
|
+
for (let i = 0; i < Math.min(count, BUFFER_SIZE); i++) {
|
|
26
|
+
sumRT += metrics.responseTimes[i];
|
|
27
|
+
}
|
|
28
|
+
const avgRT = count > 0 ? sumRT / Math.min(count, BUFFER_SIZE) : 0;
|
|
29
|
+
// Compute requests per minute
|
|
30
|
+
const elapsedMs = DateTime.toEpochMillis(metrics.lastRequestAt) - DateTime.toEpochMillis(metrics.firstRequestAt);
|
|
31
|
+
const elapsedMinutes = elapsedMs / 60000;
|
|
32
|
+
const rpm = elapsedMinutes > 0 ? total / elapsedMinutes : total;
|
|
33
|
+
// Compute error rate
|
|
34
|
+
const errorRate = total > 0 ? metrics.errorCount / total : 0;
|
|
35
|
+
// Compute percentiles
|
|
36
|
+
const bufferLen = Math.min(count, BUFFER_SIZE);
|
|
37
|
+
const sorted = Array.from(metrics.responseTimes.subarray(0, bufferLen)).sort((a, b) => a - b);
|
|
38
|
+
return {
|
|
39
|
+
totalRequests: total,
|
|
40
|
+
requestsPerMinute: Math.round(rpm * 100) / 100,
|
|
41
|
+
averageResponseTime: Math.round(avgRT * 100) / 100,
|
|
42
|
+
errorRate: Math.round(errorRate * 10000) / 10000,
|
|
43
|
+
requestsByMethod: {
|
|
44
|
+
...metrics.requestsByMethod
|
|
45
|
+
},
|
|
46
|
+
requestsByStatusCode: {
|
|
47
|
+
...metrics.requestsByStatusCode
|
|
48
|
+
},
|
|
49
|
+
...(total > 0 ? {
|
|
50
|
+
lastRequestAt: metrics.lastRequestAt
|
|
51
|
+
} : {}),
|
|
52
|
+
...(bufferLen > 0 ? {
|
|
53
|
+
p50ResponseTime: computePercentile(sorted, 50),
|
|
54
|
+
p95ResponseTime: computePercentile(sorted, 95),
|
|
55
|
+
p99ResponseTime: computePercentile(sorted, 99)
|
|
56
|
+
} : {})
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
export class MetricsService extends Context.Tag("MetricsService")() {}
|
|
60
|
+
export const MetricsServiceLive = /*#__PURE__*/Layer.effect(MetricsService, /*#__PURE__*/Effect.gen(function* () {
|
|
61
|
+
const storeRef = yield* Ref.make(HashMap.empty());
|
|
62
|
+
const recordRequest = entry => Ref.update(storeRef, store => {
|
|
63
|
+
const existing = HashMap.get(store, entry.imposterId);
|
|
64
|
+
const now = entry.timestamp;
|
|
65
|
+
const metrics = existing._tag === "Some" ? existing.value : makeEmptyMetrics(now);
|
|
66
|
+
metrics.totalRequests += 1;
|
|
67
|
+
// Method counts
|
|
68
|
+
const method = entry.request.method.toUpperCase();
|
|
69
|
+
metrics.requestsByMethod[method] = (metrics.requestsByMethod[method] ?? 0) + 1;
|
|
70
|
+
// Status code counts
|
|
71
|
+
const statusKey = String(entry.response.status);
|
|
72
|
+
metrics.requestsByStatusCode[statusKey] = (metrics.requestsByStatusCode[statusKey] ?? 0) + 1;
|
|
73
|
+
// Response time circular buffer
|
|
74
|
+
metrics.responseTimes[metrics.responseTimeIndex % BUFFER_SIZE] = entry.duration;
|
|
75
|
+
metrics.responseTimeIndex = (metrics.responseTimeIndex + 1) % BUFFER_SIZE;
|
|
76
|
+
metrics.responseTimeCount += 1;
|
|
77
|
+
// Error tracking (4xx + 5xx)
|
|
78
|
+
if (entry.response.status >= 400) {
|
|
79
|
+
metrics.errorCount += 1;
|
|
80
|
+
}
|
|
81
|
+
metrics.lastRequestAt = now;
|
|
82
|
+
return HashMap.set(store, entry.imposterId, metrics);
|
|
83
|
+
});
|
|
84
|
+
const getStats = imposterId => Ref.get(storeRef).pipe(Effect.map(store => {
|
|
85
|
+
const existing = HashMap.get(store, imposterId);
|
|
86
|
+
if (existing._tag === "None") {
|
|
87
|
+
return {
|
|
88
|
+
totalRequests: 0,
|
|
89
|
+
requestsPerMinute: 0,
|
|
90
|
+
averageResponseTime: 0,
|
|
91
|
+
errorRate: 0,
|
|
92
|
+
requestsByMethod: {},
|
|
93
|
+
requestsByStatusCode: {}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return computeStats(existing.value);
|
|
97
|
+
}));
|
|
98
|
+
const resetStats = imposterId => Ref.update(storeRef, HashMap.remove(imposterId));
|
|
99
|
+
return {
|
|
100
|
+
recordRequest,
|
|
101
|
+
getStats,
|
|
102
|
+
resetStats
|
|
103
|
+
};
|
|
104
|
+
}));
|
|
105
|
+
//# sourceMappingURL=MetricsService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetricsService.js","names":["Context","Effect","HashMap","Layer","Ref","DateTime","BUFFER_SIZE","makeEmptyMetrics","now","totalRequests","requestsByMethod","requestsByStatusCode","responseTimes","Float64Array","responseTimeIndex","responseTimeCount","firstRequestAt","lastRequestAt","errorCount","computePercentile","sorted","p","length","index","Math","ceil","max","computeStats","metrics","count","total","sumRT","i","min","avgRT","elapsedMs","toEpochMillis","elapsedMinutes","rpm","errorRate","bufferLen","Array","from","subarray","sort","a","b","requestsPerMinute","round","averageResponseTime","p50ResponseTime","p95ResponseTime","p99ResponseTime","MetricsService","Tag","MetricsServiceLive","effect","gen","storeRef","make","empty","recordRequest","entry","update","store","existing","get","imposterId","timestamp","_tag","value","method","request","toUpperCase","statusKey","String","response","status","duration","set","getStats","pipe","map","resetStats","remove"],"sources":["../../../src/services/MetricsService.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Context, Data, Effect, HashSet, Layer, Ref } from "effect";
|
|
2
|
+
import { AppConfig } from "./AppConfig";
|
|
3
|
+
export class PortAllocatorError extends Data.TaggedError("PortAllocatorError") {}
|
|
4
|
+
export class PortExhaustedError extends Data.TaggedError("PortExhaustedError") {}
|
|
5
|
+
export class PortAllocator extends Context.Tag("PortAllocator")() {}
|
|
6
|
+
export const PortAllocatorLive = /*#__PURE__*/Layer.effect(PortAllocator, /*#__PURE__*/Effect.gen(function* () {
|
|
7
|
+
const config = yield* AppConfig;
|
|
8
|
+
const portsRef = yield* Ref.make(HashSet.empty());
|
|
9
|
+
const allocate = preferred => {
|
|
10
|
+
if (preferred !== undefined) {
|
|
11
|
+
return Ref.modify(portsRef, ports => {
|
|
12
|
+
if (HashSet.has(ports, preferred)) {
|
|
13
|
+
return [Effect.fail(new PortAllocatorError({
|
|
14
|
+
reason: `Port ${preferred} is already allocated`,
|
|
15
|
+
port: preferred
|
|
16
|
+
})), ports];
|
|
17
|
+
}
|
|
18
|
+
return [Effect.succeed(preferred), HashSet.add(ports, preferred)];
|
|
19
|
+
}).pipe(Effect.flatten);
|
|
20
|
+
}
|
|
21
|
+
return Ref.modify(portsRef, ports => {
|
|
22
|
+
for (let port = config.portRangeMin; port <= config.portRangeMax; port++) {
|
|
23
|
+
if (!HashSet.has(ports, port)) {
|
|
24
|
+
return [Effect.succeed(port), HashSet.add(ports, port)];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return [Effect.fail(new PortExhaustedError({
|
|
28
|
+
rangeMin: config.portRangeMin,
|
|
29
|
+
rangeMax: config.portRangeMax
|
|
30
|
+
})), ports];
|
|
31
|
+
}).pipe(Effect.flatten);
|
|
32
|
+
};
|
|
33
|
+
const release = port => Ref.update(portsRef, HashSet.remove(port));
|
|
34
|
+
const isAvailable = port => Ref.get(portsRef).pipe(Effect.map(ports => !HashSet.has(ports, port)));
|
|
35
|
+
return {
|
|
36
|
+
allocate,
|
|
37
|
+
release,
|
|
38
|
+
isAvailable
|
|
39
|
+
};
|
|
40
|
+
}));
|
|
41
|
+
//# sourceMappingURL=PortAllocator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortAllocator.js","names":["Context","Data","Effect","HashSet","Layer","Ref","AppConfig","PortAllocatorError","TaggedError","PortExhaustedError","PortAllocator","Tag","PortAllocatorLive","effect","gen","config","portsRef","make","empty","allocate","preferred","undefined","modify","ports","has","fail","reason","port","succeed","add","pipe","flatten","portRangeMin","portRangeMax","rangeMin","rangeMax","release","update","remove","isAvailable","get","map"],"sources":["../../../src/services/PortAllocator.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,OAAO,EAAEC,IAAI,EAAEC,MAAM,EAAEC,OAAO,EAAEC,KAAK,EAAEC,GAAG,QAAQ,QAAQ;AACnE,SAASC,SAAS,QAAQ,aAAa;AAEvC,OAAM,MAAOC,kBAAmB,SAAQN,IAAI,CAACO,WAAW,CAAC,oBAAoB,CAG3E;AAEF,OAAM,MAAOC,kBAAmB,SAAQR,IAAI,CAACO,WAAW,CAAC,oBAAoB,CAG3E;AAQF,OAAM,MAAOE,aAAc,SAAQV,OAAO,CAACW,GAAG,CAAC,eAAe,CAAC,EAAqC;AAEpG,OAAO,MAAMC,iBAAiB,gBAAGR,KAAK,CAACS,MAAM,CAC3CH,aAAa,eACbR,MAAM,CAACY,GAAG,CAAC,aAAS;EAClB,MAAMC,MAAM,GAAG,OAAOT,SAAS;EAC/B,MAAMU,QAAQ,GAAG,OAAOX,GAAG,CAACY,IAAI,CAACd,OAAO,CAACe,KAAK,EAAU,CAAC;EAOzD,MAAMC,QAAQ,GAAIC,SAAkB,IAAoE;IACtG,IAAIA,SAAS,KAAKC,SAAS,EAAE;MAC3B,OAAOhB,GAAG,CAACiB,MAAM,CAACN,QAAQ,EAAGO,KAAK,IAAoB;QACpD,IAAIpB,OAAO,CAACqB,GAAG,CAACD,KAAK,EAAEH,SAAS,CAAC,EAAE;UACjC,OAAO,CACLlB,MAAM,CAACuB,IAAI,CACT,IAAIlB,kBAAkB,CAAC;YAAEmB,MAAM,EAAE,QAAQN,SAAS,uBAAuB;YAAEO,IAAI,EAAEP;UAAS,CAAE,CAAC,CAC9F,EACDG,KAAK,CACN;QACH;QACA,OAAO,CAACrB,MAAM,CAAC0B,OAAO,CAACR,SAAS,CAAC,EAAEjB,OAAO,CAAC0B,GAAG,CAACN,KAAK,EAAEH,SAAS,CAAC,CAAC;MACnE,CAAC,CAAC,CAACU,IAAI,CAAC5B,MAAM,CAAC6B,OAAO,CAAC;IACzB;IAEA,OAAO1B,GAAG,CAACiB,MAAM,CAACN,QAAQ,EAAGO,KAAK,IAAoB;MACpD,KAAK,IAAII,IAAI,GAAGZ,MAAM,CAACiB,YAAY,EAAEL,IAAI,IAAIZ,MAAM,CAACkB,YAAY,EAAEN,IAAI,EAAE,EAAE;QACxE,IAAI,CAACxB,OAAO,CAACqB,GAAG,CAACD,KAAK,EAAEI,IAAI,CAAC,EAAE;UAC7B,OAAO,CAACzB,MAAM,CAAC0B,OAAO,CAACD,IAAI,CAAC,EAAExB,OAAO,CAAC0B,GAAG,CAACN,KAAK,EAAEI,IAAI,CAAC,CAAC;QACzD;MACF;MACA,OAAO,CACLzB,MAAM,CAACuB,IAAI,CAAC,IAAIhB,kBAAkB,CAAC;QAAEyB,QAAQ,EAAEnB,MAAM,CAACiB,YAAY;QAAEG,QAAQ,EAAEpB,MAAM,CAACkB;MAAY,CAAE,CAAC,CAAC,EACrGV,KAAK,CACN;IACH,CAAC,CAAC,CAACO,IAAI,CAAC5B,MAAM,CAAC6B,OAAO,CAAC;EACzB,CAAC;EAED,MAAMK,OAAO,GAAIT,IAAY,IAA0BtB,GAAG,CAACgC,MAAM,CAACrB,QAAQ,EAAEb,OAAO,CAACmC,MAAM,CAACX,IAAI,CAAC,CAAC;EAEjG,MAAMY,WAAW,GAAIZ,IAAY,IAC/BtB,GAAG,CAACmC,GAAG,CAACxB,QAAQ,CAAC,CAACc,IAAI,CAAC5B,MAAM,CAACuC,GAAG,CAAElB,KAAK,IAAK,CAACpB,OAAO,CAACqB,GAAG,CAACD,KAAK,EAAEI,IAAI,CAAC,CAAC,CAAC;EAE1E,OAAO;IAAER,QAAQ;IAAEiB,OAAO;IAAEG;EAAW,CAAE;AAC3C,CAAC,CAAC,CACH","ignoreList":[]}
|