@effect-app/infra 4.0.0-beta.22 → 4.0.0-beta.221
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 +1648 -0
- package/_check.sh +1 -1
- package/dist/CUPS.d.ts +12 -7
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/CUPS.js +16 -12
- package/dist/Emailer/Sendgrid.d.ts +15 -15
- package/dist/Emailer/Sendgrid.d.ts.map +1 -1
- package/dist/Emailer/Sendgrid.js +20 -16
- package/dist/Emailer/fake.d.ts +1 -1
- package/dist/Emailer/fake.js +2 -2
- package/dist/Emailer/service.d.ts +13 -4
- package/dist/Emailer/service.d.ts.map +1 -1
- package/dist/Emailer/service.js +4 -3
- package/dist/Emailer.d.ts +1 -1
- package/dist/MainFiberSet.d.ts +12 -9
- package/dist/MainFiberSet.d.ts.map +1 -1
- package/dist/MainFiberSet.js +7 -3
- package/dist/Model/Repository/Registry.d.ts +21 -0
- package/dist/Model/Repository/Registry.d.ts.map +1 -0
- package/dist/Model/Repository/Registry.js +18 -0
- package/dist/Model/Repository/ext.d.ts +35 -16
- package/dist/Model/Repository/ext.d.ts.map +1 -1
- package/dist/Model/Repository/ext.js +60 -3
- package/dist/Model/Repository/internal/internal.d.ts +9 -6
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +115 -51
- package/dist/Model/Repository/legacy.d.ts +4 -2
- package/dist/Model/Repository/legacy.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.d.ts +10 -6
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.js +5 -2
- package/dist/Model/Repository/service.d.ts +32 -24
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/Model/Repository/validation.d.ts +47 -18
- package/dist/Model/Repository/validation.d.ts.map +1 -1
- package/dist/Model/Repository/validation.js +6 -6
- package/dist/Model/Repository.d.ts +2 -1
- package/dist/Model/Repository.d.ts.map +1 -1
- package/dist/Model/Repository.js +2 -1
- package/dist/Model/dsl.d.ts +6 -5
- package/dist/Model/dsl.d.ts.map +1 -1
- package/dist/Model/dsl.js +2 -3
- package/dist/Model/filter/filterApi.d.ts +5 -5
- package/dist/Model/filter/filterApi.d.ts.map +1 -1
- package/dist/Model/filter/types/errors.d.ts +1 -1
- package/dist/Model/filter/types/fields.d.ts +1 -1
- package/dist/Model/filter/types/path/common.d.ts +1 -1
- package/dist/Model/filter/types/path/eager.d.ts +1 -1
- package/dist/Model/filter/types/path/eager.d.ts.map +1 -1
- package/dist/Model/filter/types/path/eager.js +1 -1
- package/dist/Model/filter/types/path/index.d.ts +1 -1
- package/dist/Model/filter/types/utils.d.ts +1 -1
- package/dist/Model/filter/types/validator.d.ts +1 -1
- package/dist/Model/filter/types.d.ts +1 -1
- package/dist/Model/query/dsl.d.ts +142 -17
- package/dist/Model/query/dsl.d.ts.map +1 -1
- package/dist/Model/query/dsl.js +190 -5
- package/dist/Model/query/new-kid-interpreter.d.ts +77 -8
- package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -1
- package/dist/Model/query/new-kid-interpreter.js +127 -6
- package/dist/Model/query.d.ts +1 -1
- package/dist/Model.d.ts +2 -1
- package/dist/Model.d.ts.map +1 -1
- package/dist/Model.js +2 -1
- package/dist/QueueMaker/SQLQueue.d.ts +7 -8
- package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
- package/dist/QueueMaker/SQLQueue.js +135 -117
- package/dist/QueueMaker/errors.d.ts +5 -3
- package/dist/QueueMaker/errors.d.ts.map +1 -1
- package/dist/QueueMaker/errors.js +4 -2
- package/dist/QueueMaker/memQueue.d.ts +9 -5
- package/dist/QueueMaker/memQueue.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.js +81 -65
- package/dist/QueueMaker/sbqueue.d.ts +8 -4
- package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/QueueMaker/sbqueue.js +57 -55
- package/dist/QueueMaker/service.d.ts +4 -2
- package/dist/QueueMaker/service.d.ts.map +1 -1
- package/dist/QueueMaker/service.js +1 -1
- package/dist/RequestContext.d.ts +75 -35
- package/dist/RequestContext.d.ts.map +1 -1
- package/dist/RequestContext.js +14 -14
- package/dist/RequestFiberSet.d.ts +10 -7
- package/dist/RequestFiberSet.d.ts.map +1 -1
- package/dist/RequestFiberSet.js +8 -3
- package/dist/Store/ContextMapContainer.d.ts +22 -3
- package/dist/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/Store/ContextMapContainer.js +17 -3
- package/dist/Store/Cosmos/query.d.ts +7 -2
- package/dist/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/Store/Cosmos/query.js +115 -35
- package/dist/Store/Cosmos.d.ts +2 -2
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +343 -244
- package/dist/Store/Disk.d.ts +3 -3
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +76 -36
- package/dist/Store/Memory.d.ts +7 -4
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +251 -58
- package/dist/Store/SQL/Pg.d.ts +4 -0
- package/dist/Store/SQL/Pg.d.ts.map +1 -0
- package/dist/Store/SQL/Pg.js +233 -0
- package/dist/Store/SQL/query.d.ts +43 -0
- package/dist/Store/SQL/query.d.ts.map +1 -0
- package/dist/Store/SQL/query.js +478 -0
- package/dist/Store/SQL.d.ts +21 -0
- package/dist/Store/SQL.d.ts.map +1 -0
- package/dist/Store/SQL.js +450 -0
- package/dist/Store/codeFilter.d.ts +2 -2
- package/dist/Store/codeFilter.d.ts.map +1 -1
- package/dist/Store/codeFilter.js +6 -3
- package/dist/Store/index.d.ts +6 -3
- package/dist/Store/index.d.ts.map +1 -1
- package/dist/Store/index.js +18 -4
- package/dist/Store/service.d.ts +26 -8
- package/dist/Store/service.d.ts.map +1 -1
- package/dist/Store/service.js +25 -6
- package/dist/Store/utils.d.ts +3 -2
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +5 -5
- package/dist/Store.d.ts +1 -1
- package/dist/adapters/SQL/Model.d.ts +32 -43
- package/dist/adapters/SQL/Model.d.ts.map +1 -1
- package/dist/adapters/SQL/Model.js +30 -39
- package/dist/adapters/SQL.d.ts +1 -1
- package/dist/adapters/ServiceBus.d.ts +14 -11
- package/dist/adapters/ServiceBus.d.ts.map +1 -1
- package/dist/adapters/ServiceBus.js +30 -21
- package/dist/adapters/cosmos-client.d.ts +5 -3
- package/dist/adapters/cosmos-client.d.ts.map +1 -1
- package/dist/adapters/cosmos-client.js +5 -3
- package/dist/adapters/index.d.ts +8 -2
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +8 -2
- package/dist/adapters/logger.d.ts +2 -2
- package/dist/adapters/logger.d.ts.map +1 -1
- package/dist/adapters/memQueue.d.ts +5 -3
- package/dist/adapters/memQueue.d.ts.map +1 -1
- package/dist/adapters/memQueue.js +6 -5
- package/dist/adapters/mongo-client.d.ts +4 -3
- package/dist/adapters/mongo-client.d.ts.map +1 -1
- package/dist/adapters/mongo-client.js +5 -3
- package/dist/adapters/redis-client.d.ts +6 -3
- package/dist/adapters/redis-client.d.ts.map +1 -1
- package/dist/adapters/redis-client.js +7 -3
- package/dist/api/ContextProvider.d.ts +12 -8
- package/dist/api/ContextProvider.d.ts.map +1 -1
- package/dist/api/ContextProvider.js +9 -7
- package/dist/api/codec.d.ts +1 -1
- package/dist/api/internal/RequestContextMiddleware.d.ts +3 -3
- package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
- package/dist/api/internal/RequestContextMiddleware.js +10 -6
- package/dist/api/internal/auth.d.ts +45 -7
- package/dist/api/internal/auth.d.ts.map +1 -1
- package/dist/api/internal/auth.js +162 -29
- package/dist/api/internal/events.d.ts +6 -4
- package/dist/api/internal/events.d.ts.map +1 -1
- package/dist/api/internal/events.js +16 -9
- package/dist/api/internal/health.d.ts +1 -1
- package/dist/api/layerUtils.d.ts +10 -6
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +7 -6
- package/dist/api/middlewares.d.ts +1 -1
- package/dist/api/reportError.d.ts +2 -2
- package/dist/api/reportError.d.ts.map +1 -1
- package/dist/api/reportError.js +3 -2
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +5 -4
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.d.ts +42 -3
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +53 -17
- package/dist/api/routing/middleware.d.ts +1 -2
- package/dist/api/routing/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware.js +1 -2
- package/dist/api/routing/schema/jwt.d.ts +1 -1
- package/dist/api/routing/schema/jwt.d.ts.map +1 -1
- package/dist/api/routing/schema/jwt.js +3 -2
- package/dist/api/routing/tsort.d.ts +1 -1
- package/dist/api/routing/tsort.d.ts.map +1 -1
- package/dist/api/routing/utils.d.ts +4 -4
- package/dist/api/routing/utils.d.ts.map +1 -1
- package/dist/api/routing/utils.js +3 -2
- package/dist/api/routing.d.ts +84 -37
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +115 -45
- package/dist/api/setupRequest.d.ts +10 -6
- package/dist/api/setupRequest.d.ts.map +1 -1
- package/dist/api/setupRequest.js +15 -7
- package/dist/api/util.d.ts +1 -1
- package/dist/arbs.d.ts +2 -2
- package/dist/arbs.d.ts.map +1 -1
- package/dist/arbs.js +5 -3
- package/dist/errorReporter.d.ts +7 -5
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +22 -26
- package/dist/errors.d.ts +1 -1
- package/dist/fileUtil.d.ts +2 -2
- package/dist/fileUtil.d.ts.map +1 -1
- package/dist/fileUtil.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/logger/jsonLogger.d.ts +2 -2
- package/dist/logger/jsonLogger.d.ts.map +1 -1
- package/dist/logger/jsonLogger.js +4 -2
- package/dist/logger/logFmtLogger.d.ts +2 -2
- package/dist/logger/logFmtLogger.d.ts.map +1 -1
- package/dist/logger/logFmtLogger.js +2 -2
- package/dist/logger/shared.d.ts +2 -2
- package/dist/logger/shared.d.ts.map +1 -1
- package/dist/logger/shared.js +3 -3
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/otel.d.ts +75 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +65 -0
- package/dist/rateLimit.d.ts +12 -4
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +7 -12
- package/dist/test.d.ts +3 -3
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +2 -2
- package/dist/vitest.d.ts +1 -1
- package/examples/query.ts +46 -38
- package/package.json +46 -37
- package/src/CUPS.ts +15 -11
- package/src/Emailer/Sendgrid.ts +21 -15
- package/src/Emailer/fake.ts +1 -1
- package/src/Emailer/service.ts +13 -3
- package/src/MainFiberSet.ts +9 -6
- package/src/Model/Repository/Registry.ts +34 -0
- package/src/Model/Repository/ext.ts +103 -11
- package/src/Model/Repository/internal/internal.ts +231 -149
- package/src/Model/Repository/legacy.ts +3 -1
- package/src/Model/Repository/makeRepo.ts +15 -10
- package/src/Model/Repository/service.ts +35 -23
- package/src/Model/Repository/validation.ts +5 -5
- package/src/Model/Repository.ts +1 -0
- package/src/Model/dsl.ts +5 -4
- package/src/Model/filter/types/path/eager.ts +1 -2
- package/src/Model/query/dsl.ts +353 -19
- package/src/Model/query/new-kid-interpreter.ts +211 -6
- package/src/Model.ts +1 -0
- package/src/QueueMaker/SQLQueue.ts +150 -153
- package/src/QueueMaker/errors.ts +3 -1
- package/src/QueueMaker/memQueue.ts +111 -105
- package/src/QueueMaker/sbqueue.ts +76 -88
- package/src/QueueMaker/service.ts +3 -1
- package/src/RequestContext.ts +15 -16
- package/src/RequestFiberSet.ts +8 -2
- package/src/Store/ContextMapContainer.ts +45 -2
- package/src/Store/Cosmos/query.ts +143 -44
- package/src/Store/Cosmos.ts +491 -350
- package/src/Store/Disk.ts +106 -66
- package/src/Store/Memory.ts +285 -87
- package/src/Store/SQL/Pg.ts +364 -0
- package/src/Store/SQL/query.ts +540 -0
- package/src/Store/SQL.ts +736 -0
- package/src/Store/codeFilter.ts +5 -2
- package/src/Store/index.ts +20 -3
- package/src/Store/service.ts +45 -10
- package/src/Store/utils.ts +25 -23
- package/src/adapters/SQL/Model.ts +42 -41
- package/src/adapters/ServiceBus.ts +131 -121
- package/src/adapters/cosmos-client.ts +4 -2
- package/src/adapters/index.ts +7 -0
- package/src/adapters/memQueue.ts +5 -4
- package/src/adapters/mongo-client.ts +4 -2
- package/src/adapters/redis-client.ts +6 -2
- package/src/api/ContextProvider.ts +17 -13
- package/src/api/internal/RequestContextMiddleware.ts +16 -5
- package/src/api/internal/auth.ts +248 -44
- package/src/api/internal/events.ts +19 -10
- package/src/api/layerUtils.ts +12 -8
- package/src/api/reportError.ts +2 -1
- package/src/api/routing/middleware/RouterMiddleware.ts +5 -4
- package/src/api/routing/middleware/middleware.ts +60 -15
- package/src/api/routing/middleware.ts +0 -2
- package/src/api/routing/schema/jwt.ts +2 -1
- package/src/api/routing/utils.ts +2 -1
- package/src/api/routing.ts +304 -131
- package/src/api/setupRequest.ts +31 -8
- package/src/arbs.ts +5 -3
- package/src/errorReporter.ts +65 -75
- package/src/fileUtil.ts +1 -1
- package/src/logger/jsonLogger.ts +3 -1
- package/src/logger/logFmtLogger.ts +1 -1
- package/src/logger/shared.ts +3 -2
- package/src/otel.ts +152 -0
- package/src/rateLimit.ts +34 -23
- package/src/test.ts +2 -2
- package/test/auth.test.ts +101 -0
- package/test/contextProvider.test.ts +14 -11
- package/test/controller.test.ts +25 -29
- package/test/dist/auth.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/date-query.test.d.ts.map +1 -0
- package/test/dist/fixtures.d.ts +30 -12
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +17 -10
- 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/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-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/sql-store.test.d.ts.map +1 -0
- package/test/fixtures.ts +16 -9
- package/test/layerUtils.test.ts +1 -1
- package/test/query.test.ts +819 -38
- package/test/rawQuery.test.ts +312 -20
- package/test/repository-ext.test.ts +62 -0
- package/test/requires.test.ts +10 -5
- package/test/router-generator.test.ts +187 -0
- package/test/routing-interruptibility.test.ts +66 -0
- package/test/rpc-e2e-invalidation.test.ts +256 -0
- package/test/rpc-multi-middleware.test.ts +84 -9
- package/test/rpc-stream-fullstack.test.ts +304 -0
- package/test/sql-store.test.ts +1592 -0
- package/test/validateSample.test.ts +17 -12
- package/tsconfig.examples.json +1 -1
- package/tsconfig.json +0 -1
- package/tsconfig.json.bak +2 -2
- package/tsconfig.src.json +35 -35
- package/tsconfig.test.json +2 -2
- 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/eslint.config.mjs +0 -24
- package/src/Operations.ts +0 -235
- package/src/OperationsRepo.ts +0 -16
package/src/Store/codeFilter.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
3
|
-
import
|
|
4
|
-
import
|
|
3
|
+
import * as Array from "effect-app/Array"
|
|
4
|
+
import * as Option from "effect-app/Option"
|
|
5
|
+
import { assertUnreachable } from "effect-app/utils"
|
|
5
6
|
import type { FilterR, FilterResult } from "../Model/filter/filterApi.js"
|
|
6
7
|
import type { FieldValues } from "../Model/filter/types.js"
|
|
8
|
+
import { get } from "./Memory.js"
|
|
7
9
|
import type { Filter } from "./service.js"
|
|
8
10
|
import { compare, greaterThan, greaterThanExclusive, lowerThan, lowerThanExclusive } from "./utils.js"
|
|
9
11
|
|
|
@@ -186,6 +188,7 @@ export const codeFilter3_ = <E>(state: readonly FilterResult[], sut: E): boolean
|
|
|
186
188
|
const statements: any[] = [] // must be defined here to be used by eval.
|
|
187
189
|
// always put everything inside a root scope.
|
|
188
190
|
const s = codeFilter3__([{ t: "where-scope", result: state, relation: "some" }], sut, statements, null, false)
|
|
191
|
+
// oxlint-disable-next-line no-eval
|
|
189
192
|
return eval(s)
|
|
190
193
|
}
|
|
191
194
|
|
package/src/Store/index.ts
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import
|
|
2
|
+
import * as Effect from "effect-app/Effect"
|
|
3
|
+
import * as Layer from "effect-app/Layer"
|
|
4
|
+
import * as Redacted from "effect/Redacted"
|
|
5
|
+
import type { SqlClient } from "effect/unstable/sql"
|
|
3
6
|
import { CosmosStoreLayer } from "./Cosmos.js"
|
|
4
7
|
import { DiskStoreLayer } from "./Disk.js"
|
|
5
8
|
import { MemoryStoreLive } from "./Memory.js"
|
|
6
9
|
// import { RedisStoreLayer } from "./Redis.js"
|
|
10
|
+
import { RepositoryRegistryLive } from "../Model.js"
|
|
7
11
|
import type { StorageConfig } from "./service.js"
|
|
12
|
+
import { SQLiteStoreLayer } from "./SQL.js"
|
|
13
|
+
import { PgStoreLayer } from "./SQL/Pg.js"
|
|
8
14
|
|
|
9
|
-
export function StoreMakerLayer(
|
|
15
|
+
export function StoreMakerLayer(
|
|
16
|
+
cfg: StorageConfig,
|
|
17
|
+
options?: { makeSqlClientLayer?: (namespace: string) => Layer.Layer<SqlClient.SqlClient> }
|
|
18
|
+
) {
|
|
10
19
|
return Effect
|
|
11
20
|
.sync(() => {
|
|
12
21
|
const storageUrl = Redacted.value(cfg.url)
|
|
@@ -19,6 +28,14 @@ export function StoreMakerLayer(cfg: StorageConfig) {
|
|
|
19
28
|
console.log("Using disk store at " + dir)
|
|
20
29
|
return DiskStoreLayer(cfg, dir)
|
|
21
30
|
}
|
|
31
|
+
if (storageUrl.startsWith("sqlite://")) {
|
|
32
|
+
console.log("Using SQLite store")
|
|
33
|
+
return SQLiteStoreLayer(cfg, options)
|
|
34
|
+
}
|
|
35
|
+
if (storageUrl.startsWith("pg://")) {
|
|
36
|
+
console.log("Using PostgreSQL store")
|
|
37
|
+
return PgStoreLayer(cfg)
|
|
38
|
+
}
|
|
22
39
|
// if (storageUrl.startsWith("redis://")) {
|
|
23
40
|
// console.log("Using Redis store")
|
|
24
41
|
// return RedisStoreLayer(cfg)
|
|
@@ -27,7 +44,7 @@ export function StoreMakerLayer(cfg: StorageConfig) {
|
|
|
27
44
|
console.log("Using Cosmos DB store")
|
|
28
45
|
return CosmosStoreLayer(cfg)
|
|
29
46
|
})
|
|
30
|
-
.pipe(Layer.unwrap)
|
|
47
|
+
.pipe(Layer.unwrap, Layer.merge(RepositoryRegistryLive))
|
|
31
48
|
}
|
|
32
49
|
|
|
33
50
|
export * from "./service.js"
|
package/src/Store/service.ts
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import type { UniqueKey } from "@azure/cosmos"
|
|
3
|
-
import {
|
|
3
|
+
import type { NonEmptyReadonlyArray } from "effect-app/Array"
|
|
4
|
+
import * as Context from "effect-app/Context"
|
|
5
|
+
import * as Effect from "effect-app/Effect"
|
|
6
|
+
import type * as Option from "effect-app/Option"
|
|
7
|
+
import type * as Redacted from "effect/Redacted"
|
|
8
|
+
import * as Semaphore from "effect/Semaphore"
|
|
4
9
|
import type { OptimisticConcurrencyException } from "../errors.js"
|
|
5
10
|
import type { FilterResult } from "../Model/filter/filterApi.js"
|
|
6
11
|
import type { FieldValues } from "../Model/filter/types.js"
|
|
7
12
|
import type { FieldPath } from "../Model/filter/types/path/index.js"
|
|
8
|
-
import {
|
|
13
|
+
import type { ComputedProjectionIrExpression, RawQuery } from "../Model/query.js"
|
|
9
14
|
|
|
10
15
|
export interface StoreConfig<E> {
|
|
11
16
|
partitionValue: (e?: E) => string
|
|
12
17
|
/**
|
|
13
|
-
* Primarily used for testing, creating namespaces in the database to separate data e.g to run multiple tests in isolation within the same database
|
|
14
|
-
*
|
|
18
|
+
* Primarily used for testing, creating namespaces in the database to separate data e.g to run multiple tests in isolation within the same database.
|
|
19
|
+
* Memory/Disk use separate store instances per namespace. CosmosDB uses namespace-prefixed partition keys. SQL uses a `_namespace` column.
|
|
15
20
|
*/
|
|
16
21
|
allowNamespace?: (namespace: string) => boolean
|
|
17
22
|
/**
|
|
@@ -60,7 +65,14 @@ export interface O<TFieldValues extends FieldValues> {
|
|
|
60
65
|
export interface FilterArgs<Encoded extends FieldValues, U extends keyof Encoded = never> {
|
|
61
66
|
t: Encoded
|
|
62
67
|
filter?: Filter | undefined
|
|
63
|
-
select?:
|
|
68
|
+
select?:
|
|
69
|
+
| NonEmptyReadonlyArray<
|
|
70
|
+
U | { key: string; subKeys: readonly string[] } | {
|
|
71
|
+
key: string
|
|
72
|
+
computed: ComputedProjectionIrExpression
|
|
73
|
+
}
|
|
74
|
+
>
|
|
75
|
+
| undefined
|
|
64
76
|
order?: NonEmptyReadonlyArray<O<NoInfer<Encoded>>>
|
|
65
77
|
limit?: number | undefined
|
|
66
78
|
skip?: number | undefined
|
|
@@ -87,9 +99,14 @@ export interface Store<
|
|
|
87
99
|
) => Effect.Effect<NonEmptyReadonlyArray<PM>, OptimisticConcurrencyException>
|
|
88
100
|
batchRemove: (ids: NonEmptyReadonlyArray<Encoded[IdKey]>, partitionKey?: string) => Effect.Effect<void>
|
|
89
101
|
queryRaw: <Out>(query: RawQuery<Encoded, Out>) => Effect.Effect<readonly Out[]>
|
|
102
|
+
/**
|
|
103
|
+
* Explicitly seed a namespace. Primary is seeded eagerly on initialization.
|
|
104
|
+
* Non-primary namespaces must be seeded explicitly before use.
|
|
105
|
+
*/
|
|
106
|
+
seedNamespace: (namespace: string) => Effect.Effect<void>
|
|
90
107
|
}
|
|
91
108
|
|
|
92
|
-
export class StoreMaker extends
|
|
109
|
+
export class StoreMaker extends Context.Opaque<StoreMaker, {
|
|
93
110
|
make: <IdKey extends keyof Encoded, Encoded extends FieldValues, R = never, E = never>(
|
|
94
111
|
name: string,
|
|
95
112
|
idKey: IdKey,
|
|
@@ -161,16 +178,34 @@ export const makeContextMap = () => {
|
|
|
161
178
|
// }
|
|
162
179
|
// }
|
|
163
180
|
|
|
181
|
+
const store = new Map<symbol, unknown>()
|
|
182
|
+
const sem = Semaphore.makeUnsafe(1)
|
|
183
|
+
|
|
164
184
|
return {
|
|
165
185
|
get: getEtag,
|
|
166
|
-
set: setEtag
|
|
167
|
-
|
|
186
|
+
set: setEtag,
|
|
187
|
+
getOrCreateStore: <T>(key: symbol, make: () => T): T => {
|
|
188
|
+
let value = store.get(key) as T | undefined
|
|
189
|
+
if (value === undefined) {
|
|
190
|
+
value = make()
|
|
191
|
+
store.set(key, value)
|
|
192
|
+
}
|
|
193
|
+
return value
|
|
194
|
+
},
|
|
195
|
+
getOrCreateStoreEffect: <T, E, R>(key: symbol, make: Effect.Effect<T, E, R>): Effect.Effect<T, E, R> =>
|
|
196
|
+
sem.withPermits(1)(Effect.uninterruptible(Effect.gen(function*() {
|
|
197
|
+
const value = store.get(key) as T | undefined
|
|
198
|
+
if (value !== undefined) return value
|
|
199
|
+
const v = yield* make
|
|
200
|
+
store.set(key, v)
|
|
201
|
+
return v
|
|
202
|
+
})))
|
|
168
203
|
}
|
|
169
204
|
}
|
|
170
205
|
|
|
171
206
|
const makeMap = Effect.sync(() => makeContextMap())
|
|
172
207
|
|
|
173
|
-
export class ContextMap extends
|
|
208
|
+
export class ContextMap extends Context.Opaque<ContextMap>()("effect-app/ContextMap", { make: makeMap }) {
|
|
174
209
|
}
|
|
175
210
|
|
|
176
211
|
export type PersistenceModelType<Encoded extends object> = Encoded & {
|
|
@@ -178,7 +213,7 @@ export type PersistenceModelType<Encoded extends object> = Encoded & {
|
|
|
178
213
|
}
|
|
179
214
|
|
|
180
215
|
export interface StorageConfig {
|
|
181
|
-
url: Redacted.Redacted
|
|
216
|
+
url: Redacted.Redacted
|
|
182
217
|
prefix: string
|
|
183
218
|
dbName: string
|
|
184
219
|
}
|
package/src/Store/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import crypto from "crypto"
|
|
2
|
-
import
|
|
2
|
+
import * as Effect from "effect-app/Effect"
|
|
3
|
+
import * as Option from "effect-app/Option"
|
|
3
4
|
import { OptimisticConcurrencyException } from "../errors.js"
|
|
4
5
|
import type { PersistenceModelType, SupportedValues2 } from "./service.js"
|
|
5
6
|
|
|
@@ -12,33 +13,34 @@ export const makeETag = <E extends PersistenceModelType<{}>>(
|
|
|
12
13
|
_etag: crypto.createHash("sha256").update(JSON.stringify(e)).digest("hex")
|
|
13
14
|
}) as any
|
|
14
15
|
|
|
15
|
-
export const makeUpdateETag =
|
|
16
|
-
(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
id: e[idKey] as string,
|
|
24
|
-
current: "",
|
|
25
|
-
found: e._etag,
|
|
26
|
-
code: 409
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (Option.isSome(current) && current.value._etag !== e._etag) {
|
|
16
|
+
export const makeUpdateETag = (type: string) =>
|
|
17
|
+
Effect.fnUntraced(function*<IdKey extends keyof E, E extends PersistenceModelType<{}>>(
|
|
18
|
+
e: E,
|
|
19
|
+
idKey: IdKey,
|
|
20
|
+
current: Option.Option<E>
|
|
21
|
+
) {
|
|
22
|
+
if (e._etag) {
|
|
23
|
+
if (Option.isNone(current)) {
|
|
31
24
|
return yield* new OptimisticConcurrencyException({
|
|
32
25
|
type,
|
|
33
|
-
id:
|
|
34
|
-
current:
|
|
26
|
+
id: e[idKey] as string,
|
|
27
|
+
current: "",
|
|
35
28
|
found: e._etag,
|
|
36
|
-
code:
|
|
29
|
+
code: 409
|
|
37
30
|
})
|
|
38
31
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
}
|
|
33
|
+
if (Option.isSome(current) && current.value._etag !== e._etag) {
|
|
34
|
+
return yield* new OptimisticConcurrencyException({
|
|
35
|
+
type,
|
|
36
|
+
id: current.value[idKey] as string,
|
|
37
|
+
current: current.value._etag,
|
|
38
|
+
found: e._etag,
|
|
39
|
+
code: 412
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
return makeETag(e)
|
|
43
|
+
})
|
|
42
44
|
|
|
43
45
|
export function lowercaseIfString<T>(val: T) {
|
|
44
46
|
if (typeof val === "string") {
|
|
@@ -24,6 +24,7 @@ import * as VariantSchema from "effect/unstable/schema/VariantSchema"
|
|
|
24
24
|
import { SqlClient } from "effect/unstable/sql/SqlClient"
|
|
25
25
|
import * as SqlResolver from "effect/unstable/sql/SqlResolver"
|
|
26
26
|
import * as SqlSchema from "effect/unstable/sql/SqlSchema"
|
|
27
|
+
import { type DbSystem, withDbSpan } from "../../otel.js"
|
|
27
28
|
|
|
28
29
|
const {
|
|
29
30
|
Class,
|
|
@@ -73,7 +74,7 @@ export {
|
|
|
73
74
|
* @since 1.0.0
|
|
74
75
|
* @category constructors
|
|
75
76
|
* @example
|
|
76
|
-
* import
|
|
77
|
+
* import * as Schema from "effect/Schema"
|
|
77
78
|
* import { Model } from "effect/unstable/schema"
|
|
78
79
|
*
|
|
79
80
|
* export const GroupId = Schema.Number.pipe(Schema.brand("GroupId"))
|
|
@@ -545,9 +546,15 @@ export const DateTimeUpdateFromNumber: DateTimeUpdateFromNumber = Field({
|
|
|
545
546
|
*/
|
|
546
547
|
export interface JsonFromString<S extends Schema.Top> extends
|
|
547
548
|
VariantSchema.Field<{
|
|
548
|
-
readonly select: Schema.fromJsonString<
|
|
549
|
-
|
|
550
|
-
|
|
549
|
+
readonly select: Schema.fromJsonString<
|
|
550
|
+
Schema.Codec<S["Type"], Schema.Json, S["DecodingServices"], S["EncodingServices"]>
|
|
551
|
+
>
|
|
552
|
+
readonly insert: Schema.fromJsonString<
|
|
553
|
+
Schema.Codec<S["Type"], Schema.Json, S["DecodingServices"], S["EncodingServices"]>
|
|
554
|
+
>
|
|
555
|
+
readonly update: Schema.fromJsonString<
|
|
556
|
+
Schema.Codec<S["Type"], Schema.Json, S["DecodingServices"], S["EncodingServices"]>
|
|
557
|
+
>
|
|
551
558
|
readonly json: S
|
|
552
559
|
readonly jsonCreate: S
|
|
553
560
|
readonly jsonUpdate: S
|
|
@@ -565,7 +572,7 @@ export interface JsonFromString<S extends Schema.Top> extends
|
|
|
565
572
|
export const JsonFromString = <S extends Schema.Top>(
|
|
566
573
|
schema: S
|
|
567
574
|
): JsonFromString<S> => {
|
|
568
|
-
const parsed = Schema.fromJsonString(schema)
|
|
575
|
+
const parsed = Schema.fromJsonString(Schema.toCodecJson(schema))
|
|
569
576
|
return Field({
|
|
570
577
|
select: parsed,
|
|
571
578
|
insert: parsed,
|
|
@@ -590,6 +597,7 @@ export const makeRepository = <
|
|
|
590
597
|
readonly spanPrefix: string
|
|
591
598
|
readonly idColumn: Id
|
|
592
599
|
readonly versionColumn?: string | undefined
|
|
600
|
+
readonly dbSystem?: DbSystem | undefined
|
|
593
601
|
}): Effect.Effect<
|
|
594
602
|
{
|
|
595
603
|
readonly insert: (
|
|
@@ -623,6 +631,15 @@ export const makeRepository = <
|
|
|
623
631
|
const idSchema = Model.fields[options.idColumn] as Schema.Top
|
|
624
632
|
const idColumn = options.idColumn as string
|
|
625
633
|
const versionColumn = options.versionColumn
|
|
634
|
+
const system: DbSystem = options.dbSystem ?? "other_sql"
|
|
635
|
+
const opSpan = (operation: string, idValue?: unknown) =>
|
|
636
|
+
withDbSpan({
|
|
637
|
+
operation,
|
|
638
|
+
system,
|
|
639
|
+
collection: options.tableName,
|
|
640
|
+
entity: options.spanPrefix,
|
|
641
|
+
...(idValue !== undefined && { extra: { "app.entity.id": idValue } })
|
|
642
|
+
})
|
|
626
643
|
|
|
627
644
|
const insertSchema = SqlSchema.findOne({
|
|
628
645
|
Request: Model.insert,
|
|
@@ -644,9 +661,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
|
|
|
644
661
|
): Effect.Effect<S["Type"], Schema.SchemaError, S["DecodingServices"] | S["insert"]["EncodingServices"]> =>
|
|
645
662
|
insertSchema(insert).pipe(
|
|
646
663
|
Effect.catchTag("NoSuchElementError", Effect.die),
|
|
647
|
-
|
|
648
|
-
captureStackTrace: false
|
|
649
|
-
})
|
|
664
|
+
opSpan("insert")
|
|
650
665
|
) as any
|
|
651
666
|
|
|
652
667
|
const insertVoidSchema = SqlSchema.void({
|
|
@@ -657,9 +672,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
|
|
|
657
672
|
insert: S["insert"]["Type"]
|
|
658
673
|
): Effect.Effect<void, Schema.SchemaError, S["insert"]["EncodingServices"]> =>
|
|
659
674
|
insertVoidSchema(insert).pipe(
|
|
660
|
-
|
|
661
|
-
captureStackTrace: false
|
|
662
|
-
})
|
|
675
|
+
opSpan("insertVoid")
|
|
663
676
|
) as any
|
|
664
677
|
|
|
665
678
|
const updateSchema = SqlSchema.findOne({
|
|
@@ -706,11 +719,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = ${request[idCol
|
|
|
706
719
|
): Effect.Effect<S["Type"], Schema.SchemaError, S["DecodingServices"] | S["update"]["EncodingServices"]> =>
|
|
707
720
|
updateSchema(update).pipe(
|
|
708
721
|
Effect.catchTag("NoSuchElementError", Effect.die),
|
|
709
|
-
|
|
710
|
-
attributes: { id: (update as any)[idColumn] }
|
|
711
|
-
}, {
|
|
712
|
-
captureStackTrace: false
|
|
713
|
-
})
|
|
722
|
+
opSpan("update", (update as any)[idColumn])
|
|
714
723
|
) as any
|
|
715
724
|
|
|
716
725
|
const updateVoidSchema = SqlSchema.void({
|
|
@@ -729,11 +738,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = ${request[idCol
|
|
|
729
738
|
update: S["update"]["Type"]
|
|
730
739
|
): Effect.Effect<void, Schema.SchemaError, S["update"]["EncodingServices"]> =>
|
|
731
740
|
updateVoidSchema(update).pipe(
|
|
732
|
-
|
|
733
|
-
attributes: { id: (update as any)[idColumn] }
|
|
734
|
-
}, {
|
|
735
|
-
captureStackTrace: false
|
|
736
|
-
})
|
|
741
|
+
opSpan("updateVoid", (update as any)[idColumn])
|
|
737
742
|
) as any
|
|
738
743
|
|
|
739
744
|
const findByIdSchema = SqlSchema.findOneOption({
|
|
@@ -749,9 +754,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = ${request[idCol
|
|
|
749
754
|
S["DecodingServices"] | S["fields"][Id]["EncodingServices"]
|
|
750
755
|
> =>
|
|
751
756
|
findByIdSchema(id).pipe(
|
|
752
|
-
|
|
753
|
-
captureStackTrace: false
|
|
754
|
-
})
|
|
757
|
+
opSpan("findById", id)
|
|
755
758
|
) as any
|
|
756
759
|
|
|
757
760
|
const deleteSchema = SqlSchema.void({
|
|
@@ -762,11 +765,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = ${request[idCol
|
|
|
762
765
|
id: S["fields"][Id]["Type"]
|
|
763
766
|
): Effect.Effect<void, Schema.SchemaError, S["fields"][Id]["EncodingServices"]> =>
|
|
764
767
|
deleteSchema(id).pipe(
|
|
765
|
-
|
|
766
|
-
attributes: { id }
|
|
767
|
-
}, {
|
|
768
|
-
captureStackTrace: false
|
|
769
|
-
})
|
|
768
|
+
opSpan("delete", id)
|
|
770
769
|
) as any
|
|
771
770
|
|
|
772
771
|
return { insert, insertVoid, update, updateVoid, findById, delete: delete_ } as const
|
|
@@ -789,6 +788,7 @@ export const makeDataLoaders = <
|
|
|
789
788
|
readonly idColumn: Id
|
|
790
789
|
readonly window: Input
|
|
791
790
|
readonly maxBatchSize?: number | undefined
|
|
791
|
+
readonly dbSystem?: DbSystem | undefined
|
|
792
792
|
}
|
|
793
793
|
): Effect.Effect<
|
|
794
794
|
{
|
|
@@ -821,6 +821,15 @@ export const makeDataLoaders = <
|
|
|
821
821
|
const idSchema = Model.fields[options.idColumn] as Schema.Top
|
|
822
822
|
const idColumn = options.idColumn as string
|
|
823
823
|
const setMaxBatchSize = options.maxBatchSize ? RequestResolver.batchN(options.maxBatchSize) : identity
|
|
824
|
+
const system: DbSystem = options.dbSystem ?? "other_sql"
|
|
825
|
+
const opSpan = (operation: string, idValue?: unknown) =>
|
|
826
|
+
withDbSpan({
|
|
827
|
+
operation,
|
|
828
|
+
system,
|
|
829
|
+
collection: options.tableName,
|
|
830
|
+
entity: options.spanPrefix,
|
|
831
|
+
...(idValue !== undefined && { extra: { "app.entity.id": idValue } })
|
|
832
|
+
})
|
|
824
833
|
|
|
825
834
|
const insertResolver = SqlResolver
|
|
826
835
|
.ordered({
|
|
@@ -854,9 +863,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
|
|
|
854
863
|
> =>
|
|
855
864
|
insertExecute(insert).pipe(
|
|
856
865
|
Effect.catchTag("ResultLengthMismatch", Effect.die),
|
|
857
|
-
|
|
858
|
-
captureStackTrace: false
|
|
859
|
-
})
|
|
866
|
+
opSpan("insert")
|
|
860
867
|
) as any
|
|
861
868
|
|
|
862
869
|
const insertVoidResolver = SqlResolver
|
|
@@ -874,9 +881,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
|
|
|
874
881
|
insert: S["insert"]["Type"]
|
|
875
882
|
): Effect.Effect<void, Schema.SchemaError, S["insert"]["EncodingServices"]> =>
|
|
876
883
|
insertVoidExecute(insert).pipe(
|
|
877
|
-
|
|
878
|
-
captureStackTrace: false
|
|
879
|
-
})
|
|
884
|
+
opSpan("insertVoid")
|
|
880
885
|
) as any
|
|
881
886
|
|
|
882
887
|
const findByIdResolver = SqlResolver
|
|
@@ -902,9 +907,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
|
|
|
902
907
|
S["DecodingServices"] | S["fields"][Id]["EncodingServices"]
|
|
903
908
|
> =>
|
|
904
909
|
findByIdExecute(id).pipe(
|
|
905
|
-
|
|
906
|
-
captureStackTrace: false
|
|
907
|
-
})
|
|
910
|
+
opSpan("findById", id)
|
|
908
911
|
) as any
|
|
909
912
|
|
|
910
913
|
const deleteResolver = SqlResolver
|
|
@@ -922,9 +925,7 @@ select * from ${sql(options.tableName)} where ${sql(idColumn)} = LAST_INSERT_ID(
|
|
|
922
925
|
id: S["fields"][Id]["Type"]
|
|
923
926
|
): Effect.Effect<void, Schema.SchemaError, S["fields"][Id]["EncodingServices"]> =>
|
|
924
927
|
deleteExecute(id).pipe(
|
|
925
|
-
|
|
926
|
-
captureStackTrace: false
|
|
927
|
-
})
|
|
928
|
+
opSpan("delete", id)
|
|
928
929
|
) as any
|
|
929
930
|
|
|
930
931
|
return { insert, insertVoid, findById, delete: delete_ } as const
|