@effect-app/infra 4.0.0-beta.98 → 4.0.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/CHANGELOG.md +2891 -0
- package/_check.sh +1 -1
- package/dist/CUPS.d.ts +28 -9
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/CUPS.js +35 -14
- package/dist/ClusterCosmos.d.ts +67 -0
- package/dist/ClusterCosmos.d.ts.map +1 -0
- package/dist/ClusterCosmos.js +588 -0
- package/dist/ClusterServiceBus.d.ts +67 -0
- package/dist/ClusterServiceBus.d.ts.map +1 -0
- package/dist/ClusterServiceBus.js +84 -0
- package/dist/{api/ContextProvider.d.ts → ContextProvider.d.ts} +7 -4
- package/dist/ContextProvider.d.ts.map +1 -0
- package/dist/ContextProvider.js +40 -0
- package/dist/Emailer/Sendgrid.d.ts +110 -146
- package/dist/Emailer/Sendgrid.d.ts.map +1 -1
- package/dist/Emailer/Sendgrid.js +24 -19
- package/dist/Emailer/fake.d.ts +1 -1
- package/dist/Emailer/fake.d.ts.map +1 -1
- package/dist/Emailer/fake.js +4 -4
- package/dist/MainFiberSet.d.ts +11 -7
- package/dist/MainFiberSet.d.ts.map +1 -1
- package/dist/MainFiberSet.js +22 -6
- package/dist/QueueMaker/errors.d.ts +3 -1
- package/dist/QueueMaker/errors.d.ts.map +1 -1
- package/dist/QueueMaker/errors.js +4 -2
- package/dist/{adapters/SQL → SQL}/Model.d.ts +34 -45
- package/dist/SQL/Model.d.ts.map +1 -0
- package/dist/SQL/Model.js +469 -0
- package/dist/SQL.d.ts.map +1 -0
- package/dist/{adapters/SQL.js → SQL.js} +1 -1
- package/dist/Store/Cosmos/query.d.ts +16 -4
- package/dist/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/Store/Cosmos/query.js +238 -42
- package/dist/Store/Cosmos.d.ts +2 -2
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +394 -319
- package/dist/Store/Disk.d.ts +4 -4
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +91 -39
- package/dist/Store/Memory.d.ts +7 -10
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +348 -78
- package/dist/Store/SQL/Pg.d.ts +2 -2
- package/dist/Store/SQL/Pg.d.ts.map +1 -1
- package/dist/Store/SQL/Pg.js +229 -154
- package/dist/Store/SQL/query.d.ts +19 -3
- package/dist/Store/SQL/query.d.ts.map +1 -1
- package/dist/Store/SQL/query.js +306 -12
- package/dist/Store/SQL.d.ts +22 -5
- package/dist/Store/SQL.d.ts.map +1 -1
- package/dist/Store/SQL.js +369 -98
- package/dist/Store/codeFilter.d.ts +4 -4
- package/dist/Store/codeFilter.d.ts.map +1 -1
- package/dist/Store/codeFilter.js +71 -22
- package/dist/Store/index.d.ts +6 -4
- package/dist/Store/index.d.ts.map +1 -1
- package/dist/Store/index.js +9 -6
- package/dist/Store/jsonDocument.d.ts +67 -0
- package/dist/Store/jsonDocument.d.ts.map +1 -0
- package/dist/Store/jsonDocument.js +107 -0
- package/dist/Store/utils.d.ts +21 -2
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +253 -10
- package/dist/WorkflowEngineCosmos.d.ts +30 -0
- package/dist/WorkflowEngineCosmos.d.ts.map +1 -0
- package/dist/WorkflowEngineCosmos.js +542 -0
- package/dist/WorkflowEngineSqlite.d.ts +24 -0
- package/dist/WorkflowEngineSqlite.d.ts.map +1 -0
- package/dist/WorkflowEngineSqlite.js +550 -0
- package/dist/arbs.d.ts +6 -3
- package/dist/arbs.d.ts.map +1 -1
- package/dist/arbs.js +20 -4
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +5 -0
- package/dist/cosmos-client.d.ts +40 -0
- package/dist/cosmos-client.d.ts.map +1 -0
- package/dist/cosmos-client.js +41 -0
- package/dist/errorReporter.d.ts +6 -4
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +23 -27
- package/dist/fileUtil.d.ts +1 -1
- package/dist/fileUtil.d.ts.map +1 -1
- package/dist/fileUtil.js +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/internal/RequestContextMiddleware.d.ts +5 -0
- package/dist/internal/RequestContextMiddleware.d.ts.map +1 -0
- package/dist/internal/RequestContextMiddleware.js +45 -0
- package/dist/internal/auth.d.ts +53 -0
- package/dist/internal/auth.d.ts.map +1 -0
- package/dist/internal/auth.js +180 -0
- package/dist/internal/events.d.ts +11 -0
- package/dist/internal/events.d.ts.map +1 -0
- package/dist/internal/events.js +49 -0
- package/dist/{api/internal → internal}/health.d.ts +1 -1
- package/dist/internal/health.d.ts.map +1 -0
- package/dist/internal/health.js +5 -0
- package/dist/{api/layerUtils.d.ts → layerUtils.d.ts} +10 -2
- package/dist/layerUtils.d.ts.map +1 -0
- package/dist/layerUtils.js +17 -0
- package/dist/logger/jsonLogger.d.ts +1 -1
- package/dist/logger/jsonLogger.d.ts.map +1 -1
- package/dist/logger/jsonLogger.js +5 -3
- package/dist/logger/logFmtLogger.d.ts +1 -1
- package/dist/logger/logFmtLogger.d.ts.map +1 -1
- package/dist/logger/logFmtLogger.js +3 -3
- package/dist/logger/shared.d.ts +2 -2
- package/dist/logger/shared.d.ts.map +1 -1
- package/dist/logger/shared.js +6 -6
- package/dist/logger.d.ts.map +1 -1
- package/dist/middlewares.d.ts.map +1 -0
- package/dist/{api/middlewares.js → middlewares.js} +1 -1
- package/dist/{adapters/mongo-client.d.ts → mongo-client.d.ts} +2 -1
- package/dist/mongo-client.d.ts.map +1 -0
- package/dist/mongo-client.js +15 -0
- package/dist/otel.d.ts +75 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +84 -0
- package/dist/rateLimit.d.ts +11 -3
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +7 -12
- package/dist/{adapters/redis-client.d.ts → redis-client.d.ts} +4 -1
- package/dist/redis-client.d.ts.map +1 -0
- package/dist/redis-client.js +98 -0
- package/dist/{api/reportError.d.ts → reportError.d.ts} +1 -1
- package/dist/reportError.d.ts.map +1 -0
- package/dist/reportError.js +28 -0
- package/dist/{api/routing → routing}/middleware/RouterMiddleware.d.ts +2 -1
- package/dist/routing/middleware/RouterMiddleware.d.ts.map +1 -0
- package/dist/{api/routing → routing}/middleware/RouterMiddleware.js +1 -1
- package/dist/{api/routing → routing}/middleware/middleware.d.ts +11 -6
- package/dist/routing/middleware/middleware.d.ts.map +1 -0
- package/dist/routing/middleware/middleware.js +152 -0
- package/dist/{api/routing → routing}/middleware.d.ts +0 -1
- package/dist/routing/middleware.d.ts.map +1 -0
- package/dist/{api/routing → routing}/middleware.js +1 -2
- package/dist/routing/schema/jwt.d.ts.map +1 -0
- package/dist/routing/schema/jwt.js +12 -0
- package/dist/routing/tsort.d.ts.map +1 -0
- package/dist/routing/tsort.js +51 -0
- package/dist/{api/routing → routing}/utils.d.ts +3 -3
- package/dist/routing/utils.d.ts.map +1 -0
- package/dist/routing/utils.js +45 -0
- package/dist/routing.d.ts +182 -0
- package/dist/routing.d.ts.map +1 -0
- package/dist/routing.js +256 -0
- package/dist/test.d.ts +2 -2
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +5 -5
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +14 -0
- package/docs/cluster-storage.md +26 -0
- package/docs/workflow-engine.md +262 -0
- package/examples/query.ts +23 -19
- package/package.json +36 -364
- package/src/CUPS.ts +53 -14
- package/src/ClusterCosmos.ts +1170 -0
- package/src/ClusterServiceBus.ts +244 -0
- package/src/{api/ContextProvider.ts → ContextProvider.ts} +10 -7
- package/src/Emailer/Sendgrid.ts +83 -60
- package/src/Emailer/fake.ts +4 -4
- package/src/MainFiberSet.ts +31 -12
- package/src/QueueMaker/errors.ts +3 -1
- package/src/{adapters/SQL → SQL}/Model.ts +48 -47
- package/src/SQL.ts +1 -0
- package/src/Store/Cosmos/query.ts +275 -55
- package/src/Store/Cosmos.ts +597 -515
- package/src/Store/Disk.ts +145 -71
- package/src/Store/Memory.ts +420 -115
- package/src/Store/SQL/Pg.ts +352 -268
- package/src/Store/SQL/query.ts +366 -20
- package/src/Store/SQL.ts +742 -293
- package/src/Store/codeFilter.ts +78 -28
- package/src/Store/index.ts +18 -13
- package/src/Store/jsonDocument.ts +143 -0
- package/src/Store/utils.ts +307 -30
- package/src/WorkflowEngineCosmos.ts +749 -0
- package/src/WorkflowEngineSqlite.ts +813 -0
- package/src/arbs.ts +25 -5
- package/src/cosmos-client.ts +72 -0
- package/src/errorReporter.ts +68 -78
- package/src/fileUtil.ts +1 -1
- package/src/index.ts +2 -1
- package/src/{api/internal → internal}/RequestContextMiddleware.ts +23 -6
- package/src/internal/auth.ts +272 -0
- package/src/{api/internal → internal}/events.ts +18 -9
- package/src/{api/layerUtils.ts → layerUtils.ts} +7 -3
- package/src/logger/jsonLogger.ts +5 -3
- package/src/logger/logFmtLogger.ts +3 -3
- package/src/logger/shared.ts +6 -5
- package/src/middlewares.ts +10 -0
- package/src/{adapters/mongo-client.ts → mongo-client.ts} +3 -1
- package/src/otel.ts +177 -0
- package/src/rateLimit.ts +35 -24
- package/src/{adapters/redis-client.ts → redis-client.ts} +6 -2
- package/src/{api/reportError.ts → reportError.ts} +3 -2
- package/src/{api/routing → routing}/middleware/RouterMiddleware.ts +2 -1
- package/src/{api/routing → routing}/middleware/middleware.ts +75 -50
- package/src/routing/middleware.ts +4 -0
- package/src/{api/routing → routing}/schema/jwt.ts +2 -2
- package/src/{api/routing → routing}/utils.ts +2 -1
- package/src/routing.ts +823 -0
- package/src/test.ts +6 -6
- package/src/vitest.ts +1 -1
- package/test/arbs-magnitude.test.ts +33 -0
- package/test/arbs.test.ts +41 -0
- package/test/auth.test.ts +101 -0
- package/test/cluster-cosmos.test.ts +634 -0
- package/test/cluster-servicebus.test.ts +180 -0
- package/test/cluster-sqlite.test.ts +207 -0
- package/test/contextProvider.test.ts +11 -8
- package/test/controller.test.ts +23 -28
- package/test/cosmos-container-throughput.test.ts +80 -0
- package/test/cosmos-query.test.ts +368 -0
- package/test/dist/arbs-magnitude.test.d.ts.map +1 -0
- package/test/dist/arbs.test.d.ts.map +1 -0
- package/test/dist/auth.test.d.ts.map +1 -0
- package/test/dist/cluster-cosmos.test.d.ts.map +1 -0
- package/test/dist/cluster-servicebus.test.d.ts.map +1 -0
- package/test/dist/cluster-sqlite.test.d.ts.map +1 -0
- package/test/dist/contextProvider.test.d.ts.map +1 -1
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/cosmos-container-throughput.test.d.ts.map +1 -0
- package/test/dist/cosmos-query.test.d.ts.map +1 -0
- package/test/dist/fixtures.d.ts +17 -9
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +8 -3
- package/test/dist/json-lower.test.d.ts.map +1 -0
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/dist/rawQuery.test.d.ts.map +1 -1
- package/test/dist/repository-ext.test.d.ts.map +1 -0
- package/test/dist/repository-legacy-document.test.d.ts.map +1 -0
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/dist/router-generator.test.d.ts.map +1 -0
- package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
- package/test/dist/rpc-context-map-streaming.test.d.ts.map +1 -0
- package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
- package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
- package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
- package/test/dist/workflow-engine-cosmos.test.d.ts.map +1 -0
- package/test/dist/workflow-engine-sqlite.test.d.ts.map +1 -0
- package/test/fixtures.ts +7 -2
- package/test/json-lower.test.ts +129 -0
- package/test/layerUtils.test.ts +2 -2
- package/test/query.test.ts +1232 -42
- package/test/rawQuery.test.ts +432 -7
- package/test/repository-ext.test.ts +456 -0
- package/test/repository-legacy-document.test.ts +394 -0
- package/test/requires.test.ts +7 -3
- package/test/router-generator.test.ts +187 -0
- package/test/routing-interruptibility.test.ts +66 -0
- package/test/rpc-context-map-streaming.test.ts +265 -0
- package/test/rpc-e2e-invalidation.test.ts +421 -0
- package/test/rpc-multi-middleware.test.ts +17 -11
- package/test/rpc-stream-fullstack.test.ts +307 -0
- package/test/sql-store.test.ts +1202 -47
- package/test/validateSample.test.ts +70 -42
- package/test/workflow-engine-cosmos.test.ts +345 -0
- package/test/workflow-engine-sqlite.test.ts +297 -0
- package/tsconfig.examples.json +1 -1
- package/tsconfig.json +9 -1
- package/tsconfig.src.json +35 -35
- package/tsconfig.test.json +2 -2
- package/dist/Emailer/service.d.ts +0 -55
- package/dist/Emailer/service.d.ts.map +0 -1
- package/dist/Emailer/service.js +0 -6
- package/dist/Emailer.d.ts +0 -2
- package/dist/Emailer.d.ts.map +0 -1
- package/dist/Emailer.js +0 -2
- package/dist/Model/Repository/ext.d.ts +0 -41
- package/dist/Model/Repository/ext.d.ts.map +0 -1
- package/dist/Model/Repository/ext.js +0 -65
- package/dist/Model/Repository/internal/internal.d.ts +0 -59
- package/dist/Model/Repository/internal/internal.d.ts.map +0 -1
- package/dist/Model/Repository/internal/internal.js +0 -320
- package/dist/Model/Repository/legacy.d.ts +0 -19
- package/dist/Model/Repository/legacy.d.ts.map +0 -1
- package/dist/Model/Repository/legacy.js +0 -2
- package/dist/Model/Repository/makeRepo.d.ts +0 -49
- package/dist/Model/Repository/makeRepo.d.ts.map +0 -1
- package/dist/Model/Repository/makeRepo.js +0 -24
- package/dist/Model/Repository/service.d.ts +0 -89
- package/dist/Model/Repository/service.d.ts.map +0 -1
- package/dist/Model/Repository/service.js +0 -2
- package/dist/Model/Repository/validation.d.ts +0 -43
- package/dist/Model/Repository/validation.d.ts.map +0 -1
- package/dist/Model/Repository/validation.js +0 -32
- package/dist/Model/Repository.d.ts +0 -6
- package/dist/Model/Repository.d.ts.map +0 -1
- package/dist/Model/Repository.js +0 -6
- package/dist/Model/dsl.d.ts +0 -32
- package/dist/Model/dsl.d.ts.map +0 -1
- package/dist/Model/dsl.js +0 -44
- package/dist/Model/filter/filterApi.d.ts +0 -30
- package/dist/Model/filter/filterApi.d.ts.map +0 -1
- package/dist/Model/filter/filterApi.js +0 -2
- package/dist/Model/filter/types/errors.d.ts +0 -29
- package/dist/Model/filter/types/errors.d.ts.map +0 -1
- package/dist/Model/filter/types/errors.js +0 -2
- package/dist/Model/filter/types/fields.d.ts +0 -15
- package/dist/Model/filter/types/fields.d.ts.map +0 -1
- package/dist/Model/filter/types/fields.js +0 -2
- package/dist/Model/filter/types/path/common.d.ts +0 -316
- package/dist/Model/filter/types/path/common.d.ts.map +0 -1
- package/dist/Model/filter/types/path/common.js +0 -2
- package/dist/Model/filter/types/path/eager.d.ts +0 -95
- package/dist/Model/filter/types/path/eager.d.ts.map +0 -1
- package/dist/Model/filter/types/path/eager.js +0 -31
- package/dist/Model/filter/types/path/index.d.ts +0 -4
- package/dist/Model/filter/types/path/index.d.ts.map +0 -1
- package/dist/Model/filter/types/path/index.js +0 -3
- package/dist/Model/filter/types/utils.d.ts +0 -79
- package/dist/Model/filter/types/utils.d.ts.map +0 -1
- package/dist/Model/filter/types/utils.js +0 -2
- package/dist/Model/filter/types/validator.d.ts +0 -30
- package/dist/Model/filter/types/validator.d.ts.map +0 -1
- package/dist/Model/filter/types/validator.js +0 -2
- package/dist/Model/filter/types.d.ts +0 -5
- package/dist/Model/filter/types.d.ts.map +0 -1
- package/dist/Model/filter/types.js +0 -7
- package/dist/Model/query/dsl.d.ts +0 -248
- package/dist/Model/query/dsl.d.ts.map +0 -1
- package/dist/Model/query/dsl.js +0 -104
- package/dist/Model/query/new-kid-interpreter.d.ts +0 -28
- package/dist/Model/query/new-kid-interpreter.d.ts.map +0 -1
- package/dist/Model/query/new-kid-interpreter.js +0 -165
- package/dist/Model/query.d.ts +0 -15
- package/dist/Model/query.d.ts.map +0 -1
- package/dist/Model/query.js +0 -3
- package/dist/Model.d.ts +0 -4
- package/dist/Model.d.ts.map +0 -1
- package/dist/Model.js +0 -4
- package/dist/Operations.d.ts +0 -55
- package/dist/Operations.d.ts.map +0 -1
- package/dist/Operations.js +0 -102
- package/dist/OperationsRepo.d.ts +0 -41
- package/dist/OperationsRepo.d.ts.map +0 -1
- package/dist/OperationsRepo.js +0 -14
- package/dist/QueueMaker/SQLQueue.d.ts +0 -14
- package/dist/QueueMaker/SQLQueue.d.ts.map +0 -1
- package/dist/QueueMaker/SQLQueue.js +0 -132
- package/dist/QueueMaker/memQueue.d.ts +0 -11
- package/dist/QueueMaker/memQueue.d.ts.map +0 -1
- package/dist/QueueMaker/memQueue.js +0 -76
- package/dist/QueueMaker/sbqueue.d.ts +0 -12
- package/dist/QueueMaker/sbqueue.d.ts.map +0 -1
- package/dist/QueueMaker/sbqueue.js +0 -91
- package/dist/QueueMaker/service.d.ts +0 -11
- package/dist/QueueMaker/service.d.ts.map +0 -1
- package/dist/QueueMaker/service.js +0 -4
- package/dist/RequestContext.d.ts +0 -68
- package/dist/RequestContext.d.ts.map +0 -1
- package/dist/RequestContext.js +0 -49
- package/dist/RequestFiberSet.d.ts +0 -36
- package/dist/RequestFiberSet.d.ts.map +0 -1
- package/dist/RequestFiberSet.js +0 -78
- package/dist/Store/ContextMapContainer.d.ts +0 -25
- package/dist/Store/ContextMapContainer.d.ts.map +0 -1
- package/dist/Store/ContextMapContainer.js +0 -77
- package/dist/Store/service.d.ts +0 -111
- package/dist/Store/service.d.ts.map +0 -1
- package/dist/Store/service.js +0 -79
- package/dist/Store.d.ts +0 -2
- package/dist/Store.d.ts.map +0 -1
- package/dist/Store.js +0 -2
- package/dist/adapters/SQL/Model.d.ts.map +0 -1
- package/dist/adapters/SQL/Model.js +0 -478
- package/dist/adapters/SQL.d.ts.map +0 -1
- package/dist/adapters/ServiceBus.d.ts +0 -58
- package/dist/adapters/ServiceBus.d.ts.map +0 -1
- package/dist/adapters/ServiceBus.js +0 -99
- package/dist/adapters/cosmos-client.d.ts +0 -14
- package/dist/adapters/cosmos-client.d.ts.map +0 -1
- package/dist/adapters/cosmos-client.js +0 -9
- package/dist/adapters/index.d.ts +0 -2
- package/dist/adapters/index.d.ts.map +0 -1
- package/dist/adapters/index.js +0 -2
- package/dist/adapters/logger.d.ts +0 -9
- package/dist/adapters/logger.d.ts.map +0 -1
- package/dist/adapters/logger.js +0 -3
- package/dist/adapters/memQueue.d.ts +0 -13
- package/dist/adapters/memQueue.d.ts.map +0 -1
- package/dist/adapters/memQueue.js +0 -20
- package/dist/adapters/mongo-client.d.ts.map +0 -1
- package/dist/adapters/mongo-client.js +0 -13
- package/dist/adapters/redis-client.d.ts.map +0 -1
- package/dist/adapters/redis-client.js +0 -94
- package/dist/api/ContextProvider.d.ts.map +0 -1
- package/dist/api/ContextProvider.js +0 -38
- package/dist/api/codec.d.ts.map +0 -1
- package/dist/api/codec.js +0 -5
- package/dist/api/internal/RequestContextMiddleware.d.ts +0 -5
- package/dist/api/internal/RequestContextMiddleware.d.ts.map +0 -1
- package/dist/api/internal/RequestContextMiddleware.js +0 -35
- package/dist/api/internal/auth.d.ts +0 -15
- package/dist/api/internal/auth.d.ts.map +0 -1
- package/dist/api/internal/auth.js +0 -47
- package/dist/api/internal/events.d.ts +0 -9
- package/dist/api/internal/events.d.ts.map +0 -1
- package/dist/api/internal/events.js +0 -42
- package/dist/api/internal/health.d.ts.map +0 -1
- package/dist/api/internal/health.js +0 -5
- package/dist/api/layerUtils.d.ts.map +0 -1
- package/dist/api/layerUtils.js +0 -16
- package/dist/api/middlewares.d.ts.map +0 -1
- package/dist/api/reportError.d.ts.map +0 -1
- package/dist/api/reportError.js +0 -27
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +0 -1
- package/dist/api/routing/middleware/middleware.d.ts.map +0 -1
- package/dist/api/routing/middleware/middleware.js +0 -130
- package/dist/api/routing/middleware.d.ts.map +0 -1
- package/dist/api/routing/schema/jwt.d.ts.map +0 -1
- package/dist/api/routing/schema/jwt.js +0 -12
- package/dist/api/routing/tsort.d.ts.map +0 -1
- package/dist/api/routing/tsort.js +0 -51
- package/dist/api/routing/utils.d.ts.map +0 -1
- package/dist/api/routing/utils.js +0 -44
- package/dist/api/routing.d.ts +0 -134
- package/dist/api/routing.d.ts.map +0 -1
- package/dist/api/routing.js +0 -167
- package/dist/api/setupRequest.d.ts +0 -15
- package/dist/api/setupRequest.d.ts.map +0 -1
- package/dist/api/setupRequest.js +0 -49
- package/dist/api/util.d.ts.map +0 -1
- package/dist/api/util.js +0 -14
- package/eslint.config.mjs +0 -24
- package/src/Emailer/service.ts +0 -52
- package/src/Emailer.ts +0 -1
- package/src/Model/Repository/ext.ts +0 -283
- package/src/Model/Repository/internal/internal.ts +0 -580
- package/src/Model/Repository/legacy.ts +0 -27
- package/src/Model/Repository/makeRepo.ts +0 -139
- package/src/Model/Repository/service.ts +0 -627
- package/src/Model/Repository/validation.ts +0 -31
- package/src/Model/Repository.ts +0 -5
- package/src/Model/dsl.ts +0 -128
- package/src/Model/filter/filterApi.ts +0 -60
- package/src/Model/filter/types/errors.ts +0 -47
- package/src/Model/filter/types/fields.ts +0 -50
- package/src/Model/filter/types/path/common.ts +0 -404
- package/src/Model/filter/types/path/eager.ts +0 -298
- package/src/Model/filter/types/path/index.ts +0 -4
- package/src/Model/filter/types/utils.ts +0 -128
- package/src/Model/filter/types/validator.ts +0 -46
- package/src/Model/filter/types.ts +0 -6
- package/src/Model/query/dsl.ts +0 -2110
- package/src/Model/query/new-kid-interpreter.ts +0 -210
- package/src/Model/query.ts +0 -13
- package/src/Model.ts +0 -3
- package/src/Operations.ts +0 -235
- package/src/OperationsRepo.ts +0 -16
- package/src/QueueMaker/SQLQueue.ts +0 -190
- package/src/QueueMaker/memQueue.ts +0 -130
- package/src/QueueMaker/sbqueue.ts +0 -137
- package/src/QueueMaker/service.ts +0 -17
- package/src/RequestContext.ts +0 -63
- package/src/RequestFiberSet.ts +0 -105
- package/src/Store/ContextMapContainer.ts +0 -116
- package/src/Store/index.test.ts.bak +0 -112
- package/src/Store/service.ts +0 -193
- package/src/Store.ts +0 -1
- package/src/adapters/SQL.ts +0 -1
- package/src/adapters/ServiceBus.ts +0 -209
- package/src/adapters/cosmos-client.ts +0 -16
- package/src/adapters/index.ts +0 -0
- package/src/adapters/logger.ts +0 -3
- package/src/adapters/memQueue.ts +0 -21
- package/src/api/internal/auth.ts +0 -68
- package/src/api/middlewares.ts +0 -10
- package/src/api/routing/middleware.ts +0 -6
- package/src/api/routing.ts +0 -598
- package/src/api/setupRequest.ts +0 -104
- package/test/dist/date-query.test.d.ts.map +0 -1
- package/tsconfig.json.bak +0 -12
- /package/dist/{adapters/SQL.d.ts → SQL.d.ts} +0 -0
- /package/dist/{api/codec.d.ts → codec.d.ts} +0 -0
- /package/dist/{api/middlewares.d.ts → middlewares.d.ts} +0 -0
- /package/dist/{api/routing → routing}/schema/jwt.d.ts +0 -0
- /package/dist/{api/routing → routing}/tsort.d.ts +0 -0
- /package/dist/{api/util.d.ts → util.d.ts} +0 -0
- /package/src/{api/codec.ts → codec.ts} +0 -0
- /package/src/{api/internal → internal}/health.ts +0 -0
- /package/src/{api/routing → routing}/tsort.ts +0 -0
- /package/src/{api/util.ts → util.ts} +0 -0
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Effect from "effect-app/Effect"
|
|
2
2
|
import { HttpHeaders, HttpServerResponse } from "effect-app/http"
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
3
|
+
import * as S from "effect-app/Schema"
|
|
4
|
+
import { setupStreamingRequestContextFromCurrent } from "effect-app/setupRequest"
|
|
5
|
+
import { storeId } from "effect-app/Store"
|
|
6
|
+
import * as Duration from "effect/Duration"
|
|
7
|
+
import { pipe } from "effect/Function"
|
|
8
|
+
import * as Schedule from "effect/Schedule"
|
|
9
|
+
import * as Stream from "effect/Stream"
|
|
10
|
+
import { reportError } from "../errorReporter.ts"
|
|
5
11
|
|
|
6
12
|
// Tell the client to retry every 10 seconds if connectivity is lost
|
|
7
13
|
const setRetry = Stream.succeed("retry: 10000")
|
|
@@ -22,16 +28,19 @@ export const makeSSE = <A extends { id: any }, SI, SRD, SRE>(
|
|
|
22
28
|
// https://discord.com/channels/795981131316985866/1098177242598756412/1389646879675125861
|
|
23
29
|
Effect
|
|
24
30
|
.gen(function*() {
|
|
25
|
-
|
|
26
|
-
yield* Effect.
|
|
27
|
-
yield* Effect.
|
|
31
|
+
const ns = yield* storeId
|
|
32
|
+
yield* Effect.annotateCurrentSpan({ "network.connection.id": id.toString() })
|
|
33
|
+
yield* Effect.logInfo("$ start listening to events, id: " + id.toString() + ", ns: " + ns)
|
|
34
|
+
yield* Effect.addFinalizer(() =>
|
|
35
|
+
Effect.logInfo("$ end listening to events, id: " + id.toString() + ", ns: " + ns)
|
|
36
|
+
)
|
|
28
37
|
|
|
29
38
|
const enc = new TextEncoder()
|
|
30
39
|
|
|
31
40
|
const encode = S.encodeEffect(S.fromJsonString(S.toCodecJson(schema)))
|
|
32
41
|
|
|
33
42
|
const eventStream = Stream.mapEffect(
|
|
34
|
-
events,
|
|
43
|
+
Stream.filter(events, (_) => _.namespace === ns),
|
|
35
44
|
(_) =>
|
|
36
45
|
encode(_.evt)
|
|
37
46
|
.pipe(Effect.map((data) => `id: ${_.evt.id}\ndata: ${data}`))
|
|
@@ -42,7 +51,7 @@ export const makeSSE = <A extends { id: any }, SI, SRD, SRE>(
|
|
|
42
51
|
Stream.merge(keepAlive),
|
|
43
52
|
// Keep this unary so pipe receives a function, not a Stream value.
|
|
44
53
|
(self) => Stream.merge(self, eventStream, { haltStrategy: "either" }),
|
|
45
|
-
Stream.tapCause((cause) => Effect.logError("SSE error", cause)),
|
|
54
|
+
Stream.tapCause((cause) => Effect.logError("SSE error, id: " + id.toString() + ", ns: " + ns, cause)),
|
|
46
55
|
Stream.map((_) => enc.encode(_ + "\n\n"))
|
|
47
56
|
)
|
|
48
57
|
|
|
@@ -65,4 +74,4 @@ export const makeSSE = <A extends { id: any }, SI, SRD, SRE>(
|
|
|
65
74
|
)
|
|
66
75
|
return res
|
|
67
76
|
})
|
|
68
|
-
.pipe(Effect.tapCause(reportError("Request")),
|
|
77
|
+
.pipe(Effect.tapCause(reportError("Request")), setupStreamingRequestContextFromCurrent("events"))
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import type { NonEmptyReadonlyArray } from "effect-app/Array"
|
|
3
|
+
import * as Context from "effect-app/Context"
|
|
4
|
+
import * as Effect from "effect-app/Effect"
|
|
5
|
+
import type * as Layer from "effect-app/Layer"
|
|
6
|
+
import * as Option from "effect-app/Option"
|
|
7
|
+
import { InfraLogger } from "./logger.ts"
|
|
4
8
|
|
|
5
9
|
// TODO: These LayerUtils are flaky, like in dependencies as a readonly array, it breaks when there are two entries
|
|
6
10
|
// we should look at Service.MakeDeps[E/RIn/ROut] etc.
|
|
@@ -33,7 +37,7 @@ export type ContextTagWithDefault<Id, A, LayerE, LayerR> =
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
export namespace ContextTagWithDefault {
|
|
36
|
-
export type Base<A> =
|
|
40
|
+
export type Base<A> = { readonly Service: A } & { Default: Layer.Layer<any, any, any> }
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
export type GetContext<T> = T extends Context.Context<infer Y> ? Y : never
|
package/src/logger/jsonLogger.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Array from "effect-app/Array"
|
|
2
|
+
import { spanAttributes } from "effect-app/RequestContext"
|
|
3
|
+
import * as Cause from "effect/Cause"
|
|
4
|
+
import * as Logger from "effect/Logger"
|
|
2
5
|
import { CurrentLogAnnotations, CurrentLogSpans } from "effect/References"
|
|
3
|
-
import {
|
|
4
|
-
import { getRequestContextFromFiber } from "./shared.js"
|
|
6
|
+
import { getRequestContextFromFiber } from "./shared.ts"
|
|
5
7
|
|
|
6
8
|
export const jsonLogger = Logger.make<unknown, void>(
|
|
7
9
|
({ cause, date, fiber, logLevel, message }) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import { getRequestContextFromFiber } from "./shared.
|
|
1
|
+
import { spanAttributes } from "effect-app/RequestContext"
|
|
2
|
+
import * as Logger from "effect/Logger"
|
|
3
|
+
import { getRequestContextFromFiber } from "./shared.ts"
|
|
4
4
|
|
|
5
5
|
export const logfmtLogger = Logger.make<unknown, void>(
|
|
6
6
|
(options) => {
|
package/src/logger/shared.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Option from "effect-app/Option"
|
|
2
|
+
import { LocaleRef, RequestContext } from "effect-app/RequestContext"
|
|
2
3
|
import { NonEmptyString255 } from "effect-app/Schema"
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
4
|
+
import { storeId } from "effect-app/Store"
|
|
5
|
+
import type * as Fiber from "effect/Fiber"
|
|
5
6
|
|
|
6
7
|
export function getRequestContextFromFiber(fiber: Fiber.Fiber<unknown, unknown>) {
|
|
7
|
-
const span = Option.fromNullishOr(fiber.
|
|
8
|
+
const span = Option.fromNullishOr(fiber.cache.span)
|
|
8
9
|
const locale = fiber.getRef(LocaleRef)
|
|
9
10
|
const namespace = fiber.getRef(storeId)
|
|
10
|
-
return
|
|
11
|
+
return RequestContext.make({
|
|
11
12
|
span: Option.map(span, (s) => ({ spanId: s.spanId, traceId: s.traceId, sampled: s.sampled })).pipe(
|
|
12
13
|
Option.getOrElse(() => ({ spanId: "bogus", sampled: true, traceId: "bogus" }))
|
|
13
14
|
),
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mechanism for extendning behaviour of all handlers on the server.
|
|
3
|
+
*
|
|
4
|
+
* @since 1.0.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from "./internal/auth.ts"
|
|
8
|
+
export * from "./internal/events.ts"
|
|
9
|
+
export * from "./internal/health.ts"
|
|
10
|
+
export * from "./internal/RequestContextMiddleware.ts"
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Context from "effect-app/Context"
|
|
2
|
+
import * as Effect from "effect-app/Effect"
|
|
3
|
+
import * as Layer from "effect-app/Layer"
|
|
2
4
|
import { MongoClient as MongoClient_ } from "mongodb"
|
|
3
5
|
|
|
4
6
|
// TODO: we should probably share a single client...
|
package/src/otel.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry semantic-convention helpers for span attributes.
|
|
3
|
+
*
|
|
4
|
+
* Aligns repository / queue / cache adapters with stable OTel semconv keys so
|
|
5
|
+
* downstream collectors and dashboards work without per-adapter mappings.
|
|
6
|
+
*
|
|
7
|
+
* - Database: https://opentelemetry.io/docs/specs/semconv/database/
|
|
8
|
+
* - Messaging: https://opentelemetry.io/docs/specs/semconv/messaging/
|
|
9
|
+
* - Cosmos DB: https://opentelemetry.io/docs/specs/semconv/database/cosmosdb/
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as Effect from "effect-app/Effect"
|
|
13
|
+
import * as Metric from "effect/Metric"
|
|
14
|
+
|
|
15
|
+
export type DbSystem =
|
|
16
|
+
| "postgresql"
|
|
17
|
+
| "sqlite"
|
|
18
|
+
| "cosmosdb"
|
|
19
|
+
| "mongodb"
|
|
20
|
+
| "redis"
|
|
21
|
+
| "other_sql"
|
|
22
|
+
| "memory"
|
|
23
|
+
| "disk"
|
|
24
|
+
|
|
25
|
+
export interface DbSpanOptions {
|
|
26
|
+
/** OTel `db.operation.name` (e.g. `find`, `all`, `filter`, `set`). */
|
|
27
|
+
readonly operation: string
|
|
28
|
+
readonly system: DbSystem
|
|
29
|
+
/** Logical collection / table / container name. */
|
|
30
|
+
readonly collection: string
|
|
31
|
+
/** Tenant / namespace / database name. */
|
|
32
|
+
readonly namespace?: string | undefined
|
|
33
|
+
/** Application-level entity / model name (custom: `app.entity`). */
|
|
34
|
+
readonly entity?: string | undefined
|
|
35
|
+
/** Sanitized / parameterized query text. Never include bound values. */
|
|
36
|
+
readonly query?: string | undefined
|
|
37
|
+
/** Optional fragments merged into final attributes (e.g. id, partition). */
|
|
38
|
+
readonly extra?: Record<string, unknown> | undefined
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const dbAttributes = (a: DbSpanOptions): Record<string, unknown> => ({
|
|
42
|
+
"db.system.name": a.system,
|
|
43
|
+
"db.operation.name": a.operation,
|
|
44
|
+
"db.collection.name": a.collection,
|
|
45
|
+
...(a.namespace !== undefined && { "db.namespace": a.namespace }),
|
|
46
|
+
...(a.query !== undefined && { "db.query.text": a.query }),
|
|
47
|
+
...(a.entity !== undefined && { "app.entity": a.entity }),
|
|
48
|
+
...a.extra
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
const dbOperationDuration = Metric.histogram("db.client.operation.duration", {
|
|
52
|
+
boundaries: [0.1, 0.5, 1, 2, 5, 10, 25, 50, 100, 250, 500, 1_000, 2_500, 5_000, 10_000],
|
|
53
|
+
description: "Caller-observed database operation duration in milliseconds"
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
const timeDbOperation = (a: DbSpanOptions) => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
57
|
+
Effect.clockWith((clock) => {
|
|
58
|
+
const startedAt = clock.currentTimeNanosUnsafe()
|
|
59
|
+
return Effect.onExit(self, () => {
|
|
60
|
+
const durationMs = Number(clock.currentTimeNanosUnsafe() - startedAt) / 1_000_000
|
|
61
|
+
return Effect.all([
|
|
62
|
+
Effect.annotateCurrentSpan({ "db.operation.duration_ms": durationMs }),
|
|
63
|
+
Metric.update(
|
|
64
|
+
Metric.withAttributes(dbOperationDuration, {
|
|
65
|
+
"db.system.name": a.system,
|
|
66
|
+
"db.operation.name": a.operation,
|
|
67
|
+
...(a.entity !== undefined && { "app.entity": a.entity })
|
|
68
|
+
}),
|
|
69
|
+
durationMs
|
|
70
|
+
)
|
|
71
|
+
], { discard: true })
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Wrap an effect with an OTel-semconv database span.
|
|
77
|
+
*
|
|
78
|
+
* Span name follows the low-cardinality convention: `<operation> <collection>`.
|
|
79
|
+
*/
|
|
80
|
+
export const withDbSpan = (a: DbSpanOptions) =>
|
|
81
|
+
Effect.withSpan(
|
|
82
|
+
`${a.operation} ${a.collection}`,
|
|
83
|
+
{ attributes: dbAttributes(a), kind: "client" as const },
|
|
84
|
+
{ captureStackTrace: false }
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Annotate the current span with OTel-semconv database attributes.
|
|
89
|
+
*
|
|
90
|
+
* Use when the caller already owns the span (e.g. a repository) and the
|
|
91
|
+
* adapter should only contribute db.* semconv attrs without opening a child.
|
|
92
|
+
* Annotates before running so attrs persist even on failure.
|
|
93
|
+
* No-op if there is no current span.
|
|
94
|
+
*/
|
|
95
|
+
export const annotateDb = (a: DbSpanOptions) => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
|
|
96
|
+
Effect.flatMap(Effect.annotateCurrentSpan(dbAttributes(a)), () => self.pipe(timeDbOperation(a)))
|
|
97
|
+
|
|
98
|
+
/** Annotate the current span with response metrics from a DB call. */
|
|
99
|
+
export const annotateDbResponse = (m: {
|
|
100
|
+
readonly returnedRows?: number | undefined
|
|
101
|
+
readonly responseBytes?: number | undefined
|
|
102
|
+
}) =>
|
|
103
|
+
Effect.annotateCurrentSpan({
|
|
104
|
+
...(m.returnedRows !== undefined && { "db.response.returned_rows": m.returnedRows }),
|
|
105
|
+
...(m.responseBytes !== undefined && { "db.response.body.size": m.responseBytes })
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
/** Cosmos-specific response annotations. */
|
|
109
|
+
export const annotateCosmosResponse = (m: {
|
|
110
|
+
readonly requestCharge?: number | undefined
|
|
111
|
+
readonly returnedRows?: number | undefined
|
|
112
|
+
readonly responseBytes?: number | undefined
|
|
113
|
+
readonly statusCode?: number | undefined
|
|
114
|
+
}) =>
|
|
115
|
+
Effect.annotateCurrentSpan({
|
|
116
|
+
...(m.requestCharge !== undefined && { "azure.cosmosdb.operation.request_charge": m.requestCharge }),
|
|
117
|
+
...(m.statusCode !== undefined && { "db.response.status_code": String(m.statusCode) }),
|
|
118
|
+
...(m.returnedRows !== undefined && { "db.response.returned_rows": m.returnedRows }),
|
|
119
|
+
...(m.responseBytes !== undefined && { "db.response.body.size": m.responseBytes })
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
export type MessagingSystem =
|
|
123
|
+
| "servicebus"
|
|
124
|
+
| "rabbitmq"
|
|
125
|
+
| "kafka"
|
|
126
|
+
| "memory"
|
|
127
|
+
| "sql"
|
|
128
|
+
|
|
129
|
+
export type MessagingOperation =
|
|
130
|
+
| "publish"
|
|
131
|
+
| "create"
|
|
132
|
+
| "receive"
|
|
133
|
+
| "process"
|
|
134
|
+
| "settle"
|
|
135
|
+
|
|
136
|
+
export interface MessagingSpanOptions {
|
|
137
|
+
readonly operation: MessagingOperation
|
|
138
|
+
readonly system: MessagingSystem
|
|
139
|
+
/** Queue / topic name. */
|
|
140
|
+
readonly destination: string
|
|
141
|
+
readonly messageId?: string | undefined
|
|
142
|
+
readonly conversationId?: string | undefined
|
|
143
|
+
readonly bodySize?: number | undefined
|
|
144
|
+
readonly extra?: Record<string, unknown> | undefined
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const messagingAttributes = (a: MessagingSpanOptions): Record<string, unknown> => ({
|
|
148
|
+
"messaging.system": a.system,
|
|
149
|
+
"messaging.operation.name": a.operation,
|
|
150
|
+
"messaging.destination.name": a.destination,
|
|
151
|
+
...(a.messageId !== undefined && { "messaging.message.id": a.messageId }),
|
|
152
|
+
...(a.conversationId !== undefined && { "messaging.message.conversation_id": a.conversationId }),
|
|
153
|
+
...(a.bodySize !== undefined && { "messaging.message.body.size": a.bodySize }),
|
|
154
|
+
...a.extra
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
/** Wrap an effect with an OTel-semconv messaging span. */
|
|
158
|
+
export const withMessagingSpan = (
|
|
159
|
+
a: MessagingSpanOptions,
|
|
160
|
+
kind: "producer" | "consumer"
|
|
161
|
+
) =>
|
|
162
|
+
Effect.withSpan(
|
|
163
|
+
`${a.operation} ${a.destination}`,
|
|
164
|
+
{ kind, attributes: messagingAttributes(a) },
|
|
165
|
+
{ captureStackTrace: false }
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
/** Build messaging span options without wrapping (for Effect.fn / setupRequestContextWithCustomSpan). */
|
|
169
|
+
export const messagingSpanArgs = (
|
|
170
|
+
a: MessagingSpanOptions,
|
|
171
|
+
kind: "producer" | "consumer"
|
|
172
|
+
) =>
|
|
173
|
+
({
|
|
174
|
+
name: `${a.operation} ${a.destination}`,
|
|
175
|
+
kind,
|
|
176
|
+
attributes: messagingAttributes(a)
|
|
177
|
+
}) as const
|
package/src/rateLimit.ts
CHANGED
|
@@ -20,8 +20,13 @@
|
|
|
20
20
|
// }
|
|
21
21
|
// }
|
|
22
22
|
|
|
23
|
-
import
|
|
23
|
+
import * as Array from "effect-app/Array"
|
|
24
|
+
import type { NonEmptyArray } from "effect-app/Array"
|
|
25
|
+
import * as Effect from "effect-app/Effect"
|
|
26
|
+
import { dual } from "effect-app/Function"
|
|
27
|
+
import type * as Duration from "effect/Duration"
|
|
24
28
|
import type { Semaphore } from "effect/Semaphore"
|
|
29
|
+
import type { Concurrency } from "effect/Types"
|
|
25
30
|
|
|
26
31
|
/**
|
|
27
32
|
* Executes the specified effect, acquiring the specified number of permits
|
|
@@ -45,36 +50,42 @@ export function SEM_withPermitsDuration(permits: number, duration: Duration.Dura
|
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
export
|
|
49
|
-
|
|
50
|
-
forEachItem: (item: T, iWithinBatch: number, batchI: number) => Effect.Effect<A, E, R>,
|
|
51
|
-
forEachBatch: (a: NonEmptyArray<A>, i: number) => Effect.Effect<A2, E2, R2>
|
|
52
|
-
) {
|
|
53
|
-
return (items: Iterable<T>) =>
|
|
54
|
-
Effect.forEach(
|
|
55
|
-
Array.chunksOf(items, n),
|
|
56
|
-
(_, i) =>
|
|
57
|
-
Effect
|
|
58
|
-
.forEach(_, (_, j) => forEachItem(_, j, i), { concurrency: "inherit" })
|
|
59
|
-
.pipe(Effect.flatMap((_) => forEachBatch(_, i))),
|
|
60
|
-
{ concurrency: "inherit" }
|
|
61
|
-
)
|
|
53
|
+
export interface BatchOptions {
|
|
54
|
+
readonly concurrency?: Concurrency | undefined
|
|
62
55
|
}
|
|
63
56
|
|
|
64
|
-
export
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
)
|
|
69
|
-
|
|
57
|
+
export const batch: {
|
|
58
|
+
<T, A, E, R, A2, E2, R2>(
|
|
59
|
+
n: number,
|
|
60
|
+
forEachItem: (item: T, iWithinBatch: number, batchI: number) => Effect.Effect<A, E, R>,
|
|
61
|
+
forEachBatch: (a: NonEmptyArray<A>, i: number) => Effect.Effect<A2, E2, R2>,
|
|
62
|
+
options?: BatchOptions
|
|
63
|
+
): (items: Iterable<T>) => Effect.Effect<Array<A2>, E | E2, R | R2>
|
|
64
|
+
<T, A, E, R, A2, E2, R2>(
|
|
65
|
+
items: Iterable<T>,
|
|
66
|
+
n: number,
|
|
67
|
+
forEachItem: (item: T, iWithinBatch: number, batchI: number) => Effect.Effect<A, E, R>,
|
|
68
|
+
forEachBatch: (a: NonEmptyArray<A>, i: number) => Effect.Effect<A2, E2, R2>,
|
|
69
|
+
options?: BatchOptions
|
|
70
|
+
): Effect.Effect<Array<A2>, E | E2, R | R2>
|
|
71
|
+
} = dual(
|
|
72
|
+
(args) => typeof args[0] !== "number",
|
|
73
|
+
<T, A, E, R, A2, E2, R2>(
|
|
74
|
+
items: Iterable<T>,
|
|
75
|
+
n: number,
|
|
76
|
+
forEachItem: (item: T, iWithinBatch: number, batchI: number) => Effect.Effect<A, E, R>,
|
|
77
|
+
forEachBatch: (a: NonEmptyArray<A>, i: number) => Effect.Effect<A2, E2, R2>,
|
|
78
|
+
options?: BatchOptions
|
|
79
|
+
) =>
|
|
70
80
|
Effect.forEach(
|
|
71
81
|
Array.chunksOf(items, n),
|
|
72
82
|
(_, i) =>
|
|
73
83
|
Effect
|
|
74
|
-
.forEach(_, (_, j) => forEachItem(_, j, i), { concurrency:
|
|
75
|
-
.pipe(Effect.flatMap((_) => forEachBatch(_, i)))
|
|
84
|
+
.forEach(_, (_, j) => forEachItem(_, j, i), { concurrency: options?.concurrency })
|
|
85
|
+
.pipe(Effect.flatMap((_) => forEachBatch(_, i))),
|
|
86
|
+
{ concurrency: options?.concurrency }
|
|
76
87
|
)
|
|
77
|
-
|
|
88
|
+
)
|
|
78
89
|
|
|
79
90
|
// export function rateLimit(
|
|
80
91
|
// n: number,
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Context from "effect-app/Context"
|
|
2
|
+
import * as Effect from "effect-app/Effect"
|
|
3
|
+
import * as Layer from "effect-app/Layer"
|
|
4
|
+
import * as Option from "effect-app/Option"
|
|
5
|
+
import * as Data from "effect/Data"
|
|
2
6
|
import type { RedisClient as Client } from "redis"
|
|
3
7
|
import Redlock from "redlock"
|
|
4
8
|
|
|
5
9
|
export class ConnectionException extends Data.TaggedError("ConnectionException")<{ cause: Error; message: string }> {
|
|
6
10
|
constructor(cause: Error) {
|
|
7
|
-
super({ message: "A connection error
|
|
11
|
+
super({ message: "A connection error occurred", cause })
|
|
8
12
|
}
|
|
9
13
|
}
|
|
10
14
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as Effect from "effect-app/Effect"
|
|
2
|
+
import * as Cause from "effect/Cause"
|
|
3
|
+
import { logError, reportError } from "./errorReporter.ts"
|
|
3
4
|
|
|
4
5
|
// const onExitReportError = (name: string, unknownOnly?: boolean) => {
|
|
5
6
|
// const report = reportError(name)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
4
|
-
import
|
|
4
|
+
import type * as Context from "effect-app/Context"
|
|
5
|
+
import type * as Layer from "effect-app/Layer"
|
|
5
6
|
import { type GetContextConfig, type RpcContextMap } from "effect-app/rpc/RpcContextMap"
|
|
6
7
|
import { type RpcMiddlewareV4 } from "effect-app/rpc/RpcMiddleware"
|
|
7
8
|
// module:
|
|
@@ -1,22 +1,67 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { Cause, Config, Effect, Layer, Schema } from "effect"
|
|
3
2
|
import { ConfigureInterruptibilityMiddleware, DevMode, DevModeMiddleware, LoggerMiddleware, RequestCacheMiddleware } from "effect-app/middleware"
|
|
4
3
|
import { RpcContextMap, type RpcMiddleware } from "effect-app/rpc"
|
|
5
4
|
import { pretty } from "effect-app/utils"
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
5
|
+
import * as Array from "effect/Array"
|
|
6
|
+
import * as Cause from "effect/Cause"
|
|
7
|
+
import * as Config from "effect/Config"
|
|
8
|
+
import * as Context from "effect/Context"
|
|
9
|
+
import * as Effect from "effect/Effect"
|
|
10
|
+
import * as Layer from "effect/Layer"
|
|
11
|
+
import { type Rpc } from "effect/rpc"
|
|
12
|
+
import * as Schema from "effect/Schema"
|
|
13
|
+
import { logError, reportError } from "../../errorReporter.ts"
|
|
14
|
+
import { InfraLogger } from "../../logger.ts"
|
|
15
|
+
import { WithNsTransaction } from "../../Store/SQL.ts"
|
|
11
16
|
|
|
12
17
|
const logRequestError = logError("Request")
|
|
13
18
|
const reportRequestError = reportError("Request")
|
|
14
19
|
|
|
20
|
+
// Summarize an rpc payload for the `rpc.request.payload` span attribute.
|
|
21
|
+
// Scalars are kept (long strings snipped), nested objects are recursed into up
|
|
22
|
+
// to `PAYLOAD_MAX_DEPTH` so useful inputs (carrier, packageType, dimensions, ids,
|
|
23
|
+
// …) are captured. Arrays are sampled to the first `PAYLOAD_ARRAY_HEAD` elements
|
|
24
|
+
// (with a `…N more` marker when longer) so pack/pick item arrays — one entry per
|
|
25
|
+
// article, quantity folded into `amount` — are diagnosable without dumping the
|
|
26
|
+
// whole tail on every (high-frequency) SaveItems.
|
|
27
|
+
const PAYLOAD_MAX_DEPTH = 4
|
|
28
|
+
const PAYLOAD_ARRAY_HEAD = 20
|
|
29
|
+
const REDACTED_KEYS = new Set(["password", "secret", "token"])
|
|
30
|
+
|
|
31
|
+
const summarizePayloadValue = (key: string, value: unknown, depth: number): unknown => {
|
|
32
|
+
if (REDACTED_KEYS.has(key)) return "<redacted>"
|
|
33
|
+
if (typeof value === "string") return value.length > 256 ? value.substring(0, 253) + "..." : value
|
|
34
|
+
if (typeof value === "number" || typeof value === "boolean") return value
|
|
35
|
+
if (value === null || value === undefined) return `${value}`
|
|
36
|
+
if (Array.isArray(value)) {
|
|
37
|
+
if (depth >= PAYLOAD_MAX_DEPTH) return `Array[${value.length}]`
|
|
38
|
+
const head = value.slice(0, PAYLOAD_ARRAY_HEAD).map((v) => summarizePayloadValue(key, v, depth + 1))
|
|
39
|
+
return value.length > PAYLOAD_ARRAY_HEAD ? [...head, `…${value.length - PAYLOAD_ARRAY_HEAD} more`] : head
|
|
40
|
+
}
|
|
41
|
+
if (typeof value === "object") {
|
|
42
|
+
return depth >= PAYLOAD_MAX_DEPTH
|
|
43
|
+
? `Object[${Object.keys(value).length}]`
|
|
44
|
+
: Object.entries(value).reduce((prev, [k, v]) => {
|
|
45
|
+
prev[k] = summarizePayloadValue(k, v, depth + 1)
|
|
46
|
+
return prev
|
|
47
|
+
}, {} as Record<string, unknown>)
|
|
48
|
+
}
|
|
49
|
+
return typeof value
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const summarizePayload = (payload: unknown): unknown =>
|
|
53
|
+
typeof payload === "object" && payload !== null
|
|
54
|
+
? Object.entries(payload).reduce((prev, [key, value]) => {
|
|
55
|
+
prev[key] = summarizePayloadValue(key, value, 1)
|
|
56
|
+
return prev
|
|
57
|
+
}, {} as Record<string, unknown>)
|
|
58
|
+
: payload
|
|
59
|
+
|
|
15
60
|
// TODO: do we need this as middleware or just as layer?
|
|
16
61
|
export const DevModeLive = Layer.effect(
|
|
17
62
|
DevMode,
|
|
18
63
|
Effect.gen(function*() {
|
|
19
|
-
const env = yield* Config.
|
|
64
|
+
const env = yield* Config.String("env").pipe(Config.withDefault("local-dev"))
|
|
20
65
|
return env !== "prod"
|
|
21
66
|
})
|
|
22
67
|
)
|
|
@@ -29,22 +74,20 @@ export const RequestCacheMiddlewareLive = Layer.succeed(
|
|
|
29
74
|
const isOptimisticConcurrencyException = (input: unknown) =>
|
|
30
75
|
typeof input === "object" && input !== null && "_tag" in input && input._tag === "OptimisticConcurrencyException"
|
|
31
76
|
|
|
77
|
+
export const RequestType = Context.Reference<"command" | "query">(
|
|
78
|
+
"@effect-app/infra/routing/RequestType",
|
|
79
|
+
{ defaultValue: () => "query" }
|
|
80
|
+
)
|
|
81
|
+
|
|
32
82
|
export const ConfigureInterruptibilityMiddlewareLive = Layer.effect(
|
|
33
83
|
ConfigureInterruptibilityMiddleware,
|
|
34
84
|
Effect.gen(function*() {
|
|
35
|
-
const cache = new Map()
|
|
36
|
-
const getCached = (key: string, schema: Schema.Top) => {
|
|
37
|
-
const existing = cache.get(key)
|
|
38
|
-
if (existing) return existing
|
|
39
|
-
const n = determineMethod(key, schema)
|
|
40
|
-
cache.set(key, n)
|
|
41
|
-
return n
|
|
42
|
-
}
|
|
43
85
|
return (effect, { rpc }) => {
|
|
44
|
-
const
|
|
86
|
+
const requestType = Context.get(rpc.annotations, RequestType)
|
|
87
|
+
const isCommand = requestType === "command"
|
|
45
88
|
|
|
46
|
-
effect = isCommand
|
|
47
|
-
? Effect.retry(
|
|
89
|
+
effect = isCommand
|
|
90
|
+
? Effect.retry(effect, { times: 1, while: isOptimisticConcurrencyException })
|
|
48
91
|
: Effect.interruptible(effect)
|
|
49
92
|
|
|
50
93
|
return effect
|
|
@@ -60,25 +103,8 @@ export const LoggerMiddlewareLive = Layer
|
|
|
60
103
|
return (effect, { headers, payload, rpc }) =>
|
|
61
104
|
Effect
|
|
62
105
|
.annotateCurrentSpan({
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
? Object.entries(payload).reduce((prev, [key, value]: [string, unknown]) => {
|
|
66
|
-
prev[key] = key === "password"
|
|
67
|
-
? "<redacted>"
|
|
68
|
-
: typeof value === "string" || typeof value === "number" || typeof value === "boolean"
|
|
69
|
-
? typeof value === "string" && value.length > 256
|
|
70
|
-
? (value.substring(0, 253) + "...")
|
|
71
|
-
: value
|
|
72
|
-
: Array.isArray(value)
|
|
73
|
-
? `Array[${value.length}]`
|
|
74
|
-
: value === null || value === undefined
|
|
75
|
-
? `${value}`
|
|
76
|
-
: typeof value === "object" && value
|
|
77
|
-
? `Object[${Object.keys(value).length}]`
|
|
78
|
-
: typeof value
|
|
79
|
-
return prev
|
|
80
|
-
}, {} as Record<string, string | number | boolean>)
|
|
81
|
-
: payload
|
|
106
|
+
"rpc.method": rpc._tag,
|
|
107
|
+
"rpc.request.payload": summarizePayload(payload)
|
|
82
108
|
})
|
|
83
109
|
.pipe(
|
|
84
110
|
Effect.andThen(effect),
|
|
@@ -142,11 +168,11 @@ export const DefaultGenericMiddlewaresLive = Layer.mergeAll(
|
|
|
142
168
|
* }) {}
|
|
143
169
|
* ```
|
|
144
170
|
*/
|
|
145
|
-
export const requiresTransactionConfig = RpcContextMap.makeCustom()(Schema.Never, false
|
|
171
|
+
export const requiresTransactionConfig = RpcContextMap.makeCustom()(Schema.Never, false)
|
|
146
172
|
|
|
147
173
|
/**
|
|
148
174
|
* Creates the middleware Effect for SQL transaction wrapping.
|
|
149
|
-
* Requires `
|
|
175
|
+
* Requires `WithNsTransaction` service.
|
|
150
176
|
* Reads `requiresTransaction` from the RPC config; defaults to `false`.
|
|
151
177
|
*
|
|
152
178
|
* @example
|
|
@@ -157,15 +183,14 @@ export const requiresTransactionConfig = RpcContextMap.makeCustom()(Schema.Never
|
|
|
157
183
|
* )
|
|
158
184
|
* ```
|
|
159
185
|
*/
|
|
160
|
-
export const makeSqlTransactionMiddleware = (
|
|
186
|
+
export const makeSqlTransactionMiddleware = Effect.fnUntraced(function*(
|
|
161
187
|
rcm: { getConfig: (rpc: Rpc.AnyWithProps) => { readonly requiresTransaction?: boolean } }
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
})
|
|
188
|
+
) {
|
|
189
|
+
const withTx = yield* WithNsTransaction
|
|
190
|
+
const mw: RpcMiddleware.RpcMiddlewareV4<never, never, never> = (effect, { rpc }) => {
|
|
191
|
+
const { requiresTransaction } = rcm.getConfig(rpc)
|
|
192
|
+
if (requiresTransaction !== true) return effect
|
|
193
|
+
return withTx(effect)
|
|
194
|
+
}
|
|
195
|
+
return mw
|
|
196
|
+
})
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
3
|
-
import { Effect, Option } from "effect"
|
|
4
3
|
import * as S from "effect-app/Schema"
|
|
4
|
+
import * as Effect from "effect/Effect"
|
|
5
5
|
import { jwtDecode, type JwtDecodeOptions } from "jwt-decode"
|
|
6
6
|
|
|
7
7
|
export const parseJwt = <Sch extends S.Top>(
|
|
@@ -15,7 +15,7 @@ export const parseJwt = <Sch extends S.Top>(
|
|
|
15
15
|
(s, _options) =>
|
|
16
16
|
Effect.try({
|
|
17
17
|
try: () => jwtDecode(s, options),
|
|
18
|
-
catch: (e: any) => new S.SchemaIssue.InvalidValue(
|
|
18
|
+
catch: (e: any) => new S.SchemaIssue.InvalidValue({ message: e?.message }, s)
|
|
19
19
|
})
|
|
20
20
|
)
|
|
21
21
|
.pipe(S.decodeTo(schema) as any)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as S from "effect-app/Schema"
|
|
2
2
|
import type { AST } from "effect-app/Schema"
|
|
3
|
+
import * as SchemaAST from "effect-app/SchemaAST"
|
|
3
4
|
|
|
4
5
|
const get = ["Get", "Index", "List", "All", "Find", "Search"]
|
|
5
6
|
const del = ["Delete", "Remove", "Destroy"]
|