@effect-app/infra 4.0.0-beta.22 → 4.0.0-beta.220
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 +1640 -0
- package/_check.sh +1 -1
- package/dist/CUPS.d.ts +7 -7
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/CUPS.js +10 -12
- package/dist/Emailer/Sendgrid.d.ts +14 -14
- package/dist/Emailer/Sendgrid.d.ts.map +1 -1
- package/dist/Emailer/Sendgrid.js +16 -15
- package/dist/Emailer/fake.d.ts +1 -1
- package/dist/Emailer/service.d.ts +10 -4
- package/dist/Emailer/service.d.ts.map +1 -1
- package/dist/Emailer/service.js +3 -3
- package/dist/Emailer.d.ts +1 -1
- package/dist/MainFiberSet.d.ts +9 -9
- package/dist/MainFiberSet.d.ts.map +1 -1
- package/dist/MainFiberSet.js +3 -3
- package/dist/Model/Repository/Registry.d.ts +20 -0
- package/dist/Model/Repository/Registry.d.ts.map +1 -0
- package/dist/Model/Repository/Registry.js +17 -0
- package/dist/Model/Repository/ext.d.ts +33 -15
- package/dist/Model/Repository/ext.d.ts.map +1 -1
- package/dist/Model/Repository/ext.js +54 -2
- package/dist/Model/Repository/internal/internal.d.ts +6 -6
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +103 -51
- package/dist/Model/Repository/legacy.d.ts +1 -1
- package/dist/Model/Repository/makeRepo.d.ts +7 -6
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.js +5 -1
- package/dist/Model/Repository/service.d.ts +28 -23
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/Model/Repository/validation.d.ts +46 -17
- package/dist/Model/Repository/validation.d.ts.map +1 -1
- package/dist/Model/Repository/validation.js +5 -5
- 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 +4 -4
- package/dist/Model/dsl.d.ts.map +1 -1
- 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 +139 -16
- package/dist/Model/query/dsl.d.ts.map +1 -1
- package/dist/Model/query/dsl.js +187 -1
- package/dist/Model/query/new-kid-interpreter.d.ts +76 -7
- package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -1
- package/dist/Model/query/new-kid-interpreter.js +122 -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 +5 -7
- package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
- package/dist/QueueMaker/SQLQueue.js +130 -116
- package/dist/QueueMaker/errors.d.ts +2 -2
- package/dist/QueueMaker/errors.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.d.ts +7 -4
- package/dist/QueueMaker/memQueue.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.js +75 -63
- package/dist/QueueMaker/sbqueue.d.ts +6 -3
- package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/QueueMaker/sbqueue.js +52 -53
- package/dist/QueueMaker/service.d.ts +1 -1
- package/dist/RequestContext.d.ts +74 -35
- package/dist/RequestContext.d.ts.map +1 -1
- package/dist/RequestContext.js +13 -14
- package/dist/RequestFiberSet.d.ts +7 -7
- package/dist/RequestFiberSet.d.ts.map +1 -1
- package/dist/RequestFiberSet.js +3 -3
- package/dist/Store/ContextMapContainer.d.ts +19 -3
- package/dist/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/Store/ContextMapContainer.js +13 -3
- package/dist/Store/Cosmos/query.d.ts +5 -1
- package/dist/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/Store/Cosmos/query.js +113 -34
- package/dist/Store/Cosmos.d.ts +1 -1
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +335 -243
- package/dist/Store/Disk.d.ts +2 -2
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +72 -35
- package/dist/Store/Memory.d.ts +6 -4
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +242 -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 +231 -0
- package/dist/Store/SQL/query.d.ts +42 -0
- package/dist/Store/SQL/query.d.ts.map +1 -0
- package/dist/Store/SQL/query.js +479 -0
- package/dist/Store/SQL.d.ts +20 -0
- package/dist/Store/SQL.d.ts.map +1 -0
- package/dist/Store/SQL.js +446 -0
- package/dist/Store/codeFilter.d.ts +1 -1
- package/dist/Store/codeFilter.d.ts.map +1 -1
- package/dist/Store/codeFilter.js +4 -2
- package/dist/Store/index.d.ts +5 -2
- package/dist/Store/index.d.ts.map +1 -1
- package/dist/Store/index.js +15 -3
- package/dist/Store/service.d.ts +22 -8
- package/dist/Store/service.d.ts.map +1 -1
- package/dist/Store/service.js +24 -6
- package/dist/Store/utils.d.ts +1 -1
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +3 -4
- package/dist/Store.d.ts +1 -1
- package/dist/adapters/SQL/Model.d.ts +31 -42
- package/dist/adapters/SQL/Model.d.ts.map +1 -1
- package/dist/adapters/SQL/Model.js +29 -38
- package/dist/adapters/SQL.d.ts +1 -1
- package/dist/adapters/ServiceBus.d.ts +11 -11
- package/dist/adapters/ServiceBus.d.ts.map +1 -1
- package/dist/adapters/ServiceBus.js +25 -21
- package/dist/adapters/cosmos-client.d.ts +3 -3
- package/dist/adapters/cosmos-client.d.ts.map +1 -1
- package/dist/adapters/cosmos-client.js +3 -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 +1 -1
- package/dist/adapters/logger.d.ts.map +1 -1
- package/dist/adapters/memQueue.d.ts +3 -3
- package/dist/adapters/memQueue.d.ts.map +1 -1
- package/dist/adapters/memQueue.js +3 -3
- package/dist/adapters/mongo-client.d.ts +3 -3
- package/dist/adapters/mongo-client.d.ts.map +1 -1
- package/dist/adapters/mongo-client.js +3 -3
- package/dist/adapters/redis-client.d.ts +3 -3
- package/dist/adapters/redis-client.d.ts.map +1 -1
- package/dist/adapters/redis-client.js +3 -3
- package/dist/api/ContextProvider.d.ts +8 -8
- package/dist/api/ContextProvider.d.ts.map +1 -1
- package/dist/api/ContextProvider.js +6 -6
- package/dist/api/codec.d.ts +1 -1
- package/dist/api/internal/RequestContextMiddleware.d.ts +2 -2
- package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
- package/dist/api/internal/RequestContextMiddleware.js +9 -6
- package/dist/api/internal/auth.d.ts +44 -6
- package/dist/api/internal/auth.d.ts.map +1 -1
- package/dist/api/internal/auth.js +160 -29
- package/dist/api/internal/events.d.ts +3 -3
- package/dist/api/internal/events.d.ts.map +1 -1
- package/dist/api/internal/events.js +10 -8
- package/dist/api/internal/health.d.ts +1 -1
- package/dist/api/layerUtils.d.ts +6 -6
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +5 -5
- package/dist/api/middlewares.d.ts +1 -1
- package/dist/api/reportError.d.ts +1 -1
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +4 -4
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.d.ts +39 -3
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +48 -16
- 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/tsort.d.ts +1 -1
- package/dist/api/routing/tsort.d.ts.map +1 -1
- package/dist/api/routing/utils.d.ts +3 -3
- package/dist/api/routing/utils.d.ts.map +1 -1
- package/dist/api/routing.d.ts +80 -37
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +109 -41
- package/dist/api/setupRequest.d.ts +8 -5
- package/dist/api/setupRequest.d.ts.map +1 -1
- package/dist/api/setupRequest.js +12 -7
- package/dist/api/util.d.ts +1 -1
- package/dist/arbs.d.ts +1 -1
- package/dist/arbs.d.ts.map +1 -1
- package/dist/arbs.js +5 -3
- package/dist/errorReporter.d.ts +4 -4
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +20 -25
- package/dist/errors.d.ts +1 -1
- package/dist/fileUtil.d.ts +1 -1
- package/dist/fileUtil.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/logger/jsonLogger.d.ts +1 -1
- package/dist/logger/logFmtLogger.d.ts +1 -1
- package/dist/logger/shared.d.ts +1 -1
- package/dist/logger/shared.js +2 -2
- 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 +9 -3
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +5 -11
- package/dist/test.d.ts +2 -2
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +1 -1
- package/dist/vitest.d.ts +1 -1
- package/examples/query.ts +42 -38
- package/package.json +46 -37
- package/src/CUPS.ts +9 -11
- package/src/Emailer/Sendgrid.ts +17 -14
- package/src/Emailer/service.ts +9 -3
- package/src/MainFiberSet.ts +5 -6
- package/src/Model/Repository/Registry.ts +33 -0
- package/src/Model/Repository/ext.ts +96 -10
- package/src/Model/Repository/internal/internal.ts +218 -149
- package/src/Model/Repository/makeRepo.ts +12 -10
- package/src/Model/Repository/service.ts +31 -22
- package/src/Model/Repository/validation.ts +4 -4
- package/src/Model/Repository.ts +1 -0
- package/src/Model/dsl.ts +3 -3
- package/src/Model/filter/types/path/eager.ts +1 -2
- package/src/Model/query/dsl.ts +348 -18
- package/src/Model/query/new-kid-interpreter.ts +206 -6
- package/src/Model.ts +1 -0
- package/src/QueueMaker/SQLQueue.ts +144 -152
- package/src/QueueMaker/memQueue.ts +104 -103
- package/src/QueueMaker/sbqueue.ts +70 -86
- package/src/RequestContext.ts +14 -16
- package/src/RequestFiberSet.ts +2 -2
- package/src/Store/ContextMapContainer.ts +41 -2
- package/src/Store/Cosmos/query.ts +140 -43
- package/src/Store/Cosmos.ts +482 -349
- package/src/Store/Disk.ts +102 -65
- package/src/Store/Memory.ts +275 -87
- package/src/Store/SQL/Pg.ts +361 -0
- package/src/Store/SQL/query.ts +539 -0
- package/src/Store/SQL.ts +731 -0
- package/src/Store/codeFilter.ts +3 -1
- package/src/Store/index.ts +17 -2
- package/src/Store/service.ts +41 -10
- package/src/Store/utils.ts +23 -22
- package/src/adapters/SQL/Model.ts +41 -40
- package/src/adapters/ServiceBus.ts +125 -121
- package/src/adapters/cosmos-client.ts +2 -2
- package/src/adapters/index.ts +7 -0
- package/src/adapters/memQueue.ts +2 -2
- package/src/adapters/mongo-client.ts +2 -2
- package/src/adapters/redis-client.ts +2 -2
- package/src/api/ContextProvider.ts +12 -13
- package/src/api/internal/RequestContextMiddleware.ts +15 -5
- package/src/api/internal/auth.ts +246 -44
- package/src/api/internal/events.ts +13 -9
- package/src/api/layerUtils.ts +8 -8
- package/src/api/routing/middleware/RouterMiddleware.ts +4 -4
- package/src/api/routing/middleware/middleware.ts +55 -14
- package/src/api/routing/middleware.ts +0 -2
- package/src/api/routing.ts +296 -131
- package/src/api/setupRequest.ts +28 -8
- package/src/arbs.ts +4 -2
- package/src/errorReporter.ts +62 -74
- package/src/logger/shared.ts +1 -1
- package/src/otel.ts +152 -0
- package/src/rateLimit.ts +30 -22
- package/src/test.ts +1 -1
- package/test/auth.test.ts +101 -0
- package/test/contextProvider.test.ts +11 -11
- package/test/controller.test.ts +21 -30
- 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 +26 -12
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +12 -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 +11 -9
- package/test/query.test.ts +813 -38
- package/test/rawQuery.test.ts +301 -20
- package/test/repository-ext.test.ts +60 -0
- package/test/requires.test.ts +6 -6
- package/test/router-generator.test.ts +183 -0
- package/test/routing-interruptibility.test.ts +63 -0
- package/test/rpc-e2e-invalidation.test.ts +251 -0
- package/test/rpc-multi-middleware.test.ts +78 -9
- package/test/rpc-stream-fullstack.test.ts +300 -0
- package/test/sql-store.test.ts +1592 -0
- package/test/validateSample.test.ts +15 -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/dist/vitest.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from "@effect/vitest";
|
|
2
2
|
export * from "./test.js";
|
|
3
|
-
//# sourceMappingURL=
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidml0ZXN0LmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdml0ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsZ0JBQWdCLENBQUE7QUFDOUIsY0FBYyxXQUFXLENBQUEifQ==
|
package/examples/query.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { expectTypeOf } from "@effect/vitest"
|
|
2
|
+
import { Effect, Layer, ManagedRuntime, S, Struct } from "effect-app"
|
|
2
3
|
import { makeRepo } from "../src/Model.js"
|
|
3
|
-
import { and, make, one, or, order, page, project, QueryWhere, where } from "../src/Model/query.js"
|
|
4
|
+
import { and, make, one, or, order, page, project, type QueryWhere, where } from "../src/Model/query.js"
|
|
4
5
|
import { MemoryStoreLive } from "../src/Store/Memory.js"
|
|
5
|
-
import { expectTypeOf } from "@effect/vitest"
|
|
6
6
|
|
|
7
7
|
const str = S.Struct({ _tag: S.Literal("string"), value: S.String })
|
|
8
|
-
const num = S.Struct({ _tag: S.Literal("number"), value: S.
|
|
8
|
+
const num = S.Struct({ _tag: S.Literal("number"), value: S.Finite })
|
|
9
9
|
const someUnion = S.Union(str, num)
|
|
10
10
|
|
|
11
|
-
export class Something extends S.
|
|
12
|
-
id: S.StringId.
|
|
11
|
+
export class Something extends S.Opaque<Something>()(S.TaggedStruct("Something", {
|
|
12
|
+
id: S.StringId.withConstructorDefault,
|
|
13
13
|
displayName: S.NonEmptyString255,
|
|
14
|
-
n: S.Date.
|
|
15
|
-
union: someUnion.pipe(S.
|
|
16
|
-
}) {}
|
|
14
|
+
n: S.Date.withConstructorDefault,
|
|
15
|
+
union: someUnion.pipe(S.withConstructorDefault(Effect.succeed({ _tag: "string" as const, value: "hi" })))
|
|
16
|
+
})) {}
|
|
17
17
|
|
|
18
|
-
export class SomethingElse extends S.
|
|
19
|
-
id: S.StringId.
|
|
18
|
+
export class SomethingElse extends S.Opaque<SomethingElse>()(S.TaggedStruct("SomethingElse", {
|
|
19
|
+
id: S.StringId.withConstructorDefault,
|
|
20
20
|
banana: S.NonEmptyString255
|
|
21
|
-
}) {}
|
|
21
|
+
})) {}
|
|
22
22
|
|
|
23
23
|
const Union = S.Union(Something, SomethingElse)
|
|
24
24
|
|
|
@@ -38,15 +38,15 @@ export declare namespace SomethingElse {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const items = [
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
Something.make({ displayName: S.NonEmptyString255("Verona"), n: new Date("2020-01-01T00:00:00Z") }),
|
|
42
|
+
Something.make({ displayName: S.NonEmptyString255("Riley") }),
|
|
43
|
+
Something.make({
|
|
44
44
|
displayName: S.NonEmptyString255("Riley"),
|
|
45
45
|
n: new Date("2020-01-01T00:00:00Z"),
|
|
46
46
|
union: { _tag: "number", value: 1 }
|
|
47
47
|
}),
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
SomethingElse.make({ banana: S.NonEmptyString255("Banana") }),
|
|
49
|
+
SomethingElse.make({ banana: S.NonEmptyString255("Banana2") })
|
|
50
50
|
]
|
|
51
51
|
|
|
52
52
|
class SomethingRepo extends Effect.Service<SomethingRepo>()("SomethingRepo", {
|
|
@@ -78,7 +78,7 @@ const program = Effect.gen(function*() {
|
|
|
78
78
|
order("displayName"),
|
|
79
79
|
page({ take: 1 }),
|
|
80
80
|
one,
|
|
81
|
-
project(
|
|
81
|
+
project(Something.mapFields(Struct.pick(["id", "displayName"])))
|
|
82
82
|
)
|
|
83
83
|
|
|
84
84
|
const r2 = yield* somethingRepo.query(
|
|
@@ -100,31 +100,35 @@ const rt = ManagedRuntime.make(SomethingRepo.Test)
|
|
|
100
100
|
rt.runFork(program)
|
|
101
101
|
|
|
102
102
|
const test1 = make<Union.Encoded>().pipe(
|
|
103
|
-
where("union._tag", "string")
|
|
103
|
+
where("union._tag", "string")
|
|
104
104
|
)
|
|
105
105
|
|
|
106
|
-
expectTypeOf(test1).toEqualTypeOf<
|
|
107
|
-
|
|
108
|
-
readonly
|
|
109
|
-
readonly
|
|
110
|
-
readonly
|
|
106
|
+
expectTypeOf(test1).toEqualTypeOf<
|
|
107
|
+
QueryWhere<Union.Encoded, {
|
|
108
|
+
readonly _tag: "Something"
|
|
109
|
+
readonly id: string
|
|
110
|
+
readonly displayName: string
|
|
111
|
+
readonly n: string
|
|
111
112
|
readonly union: {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
}
|
|
113
|
+
readonly _tag: "string"
|
|
114
|
+
readonly value: string
|
|
115
|
+
}
|
|
116
|
+
}>
|
|
117
|
+
>()
|
|
116
118
|
|
|
117
119
|
const testneq1 = make<Union.Encoded>().pipe(
|
|
118
|
-
where("union._tag", "neq", "string")
|
|
120
|
+
where("union._tag", "neq", "string")
|
|
119
121
|
)
|
|
120
122
|
|
|
121
|
-
expectTypeOf(testneq1).toEqualTypeOf<
|
|
122
|
-
|
|
123
|
-
readonly
|
|
124
|
-
readonly
|
|
125
|
-
readonly
|
|
123
|
+
expectTypeOf(testneq1).toEqualTypeOf<
|
|
124
|
+
QueryWhere<Union.Encoded, {
|
|
125
|
+
readonly _tag: "Something"
|
|
126
|
+
readonly id: string
|
|
127
|
+
readonly displayName: string
|
|
128
|
+
readonly n: string
|
|
126
129
|
readonly union: {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
}
|
|
130
|
+
readonly _tag: "number"
|
|
131
|
+
readonly value: number
|
|
132
|
+
}
|
|
133
|
+
}>
|
|
134
|
+
>()
|
package/package.json
CHANGED
|
@@ -1,54 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/infra",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.220",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@faker-js/faker": "^8.4.1",
|
|
8
8
|
"change-case": "^5.4.4",
|
|
9
9
|
"cross-fetch": "^4.1.0",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"fast-check": "~4.7.0",
|
|
11
|
+
"jose": "^6.2.3",
|
|
12
12
|
"path-parser": "^6.1.0",
|
|
13
13
|
"proper-lockfile": "^4.1.2",
|
|
14
|
-
"pure-rand": "
|
|
14
|
+
"pure-rand": "8.4.0",
|
|
15
15
|
"query-string": "^9.3.1",
|
|
16
|
-
"effect-app": "4.0.0-beta.
|
|
16
|
+
"effect-app": "4.0.0-beta.220"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@azure/cosmos": "^4.9.
|
|
19
|
+
"@azure/cosmos": "^4.9.3",
|
|
20
20
|
"@azure/service-bus": "^7.9.5",
|
|
21
|
-
"@
|
|
22
|
-
"@sentry/
|
|
23
|
-
"@
|
|
24
|
-
"@types/
|
|
21
|
+
"@effect/sql-sqlite-node": "4.0.0-beta.62",
|
|
22
|
+
"@sentry/node": "10.51.0",
|
|
23
|
+
"@sentry/opentelemetry": "10.51.0",
|
|
24
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
25
|
+
"@types/node": "25.6.0",
|
|
25
26
|
"@types/proper-lockfile": "^4.1.4",
|
|
26
27
|
"@types/redis": "^2.8.32",
|
|
27
28
|
"@types/redlock": "^4.0.8",
|
|
28
|
-
"
|
|
29
|
-
"jwks-rsa": "2.1.4",
|
|
29
|
+
"better-sqlite3": "^12.9.0",
|
|
30
30
|
"jwt-decode": "^4.0.0",
|
|
31
|
-
"mongodb": "7.
|
|
31
|
+
"mongodb": "7.2.0",
|
|
32
32
|
"redis": "^3.1.2",
|
|
33
33
|
"redlock": "^4.2.0",
|
|
34
34
|
"strip-ansi": "^7.2.0",
|
|
35
|
-
"typescript": "~
|
|
36
|
-
"vitest": "^4.
|
|
37
|
-
"@effect-app/eslint-shared-config": "0.5.7-beta.2"
|
|
35
|
+
"typescript": "~6.0.3",
|
|
36
|
+
"vitest": "^4.1.5"
|
|
38
37
|
},
|
|
39
38
|
"peerDependencies": {
|
|
40
|
-
"@azure/cosmos": "^4.9.
|
|
39
|
+
"@azure/cosmos": "^4.9.3",
|
|
41
40
|
"@azure/service-bus": "^7.9.5",
|
|
42
|
-
"@effect/vitest": "^4.0.0-beta.
|
|
41
|
+
"@effect/vitest": "^4.0.0-beta.62",
|
|
43
42
|
"@sendgrid/helpers": "^8.0.0",
|
|
44
43
|
"@sendgrid/mail": "^8.1.6",
|
|
45
|
-
"@sentry/node": "10.
|
|
46
|
-
"@sentry/opentelemetry": "10.
|
|
44
|
+
"@sentry/node": "10.51.0",
|
|
45
|
+
"@sentry/opentelemetry": "10.51.0",
|
|
46
|
+
"effect": "^4.0.0-beta.62",
|
|
47
47
|
"jwt-decode": "^4.0.0",
|
|
48
48
|
"redis": "^3.1.2",
|
|
49
|
-
"redlock": "^4.2.0"
|
|
50
|
-
"effect": "^4.0.0-beta.36",
|
|
51
|
-
"express": "^5.2.1"
|
|
49
|
+
"redlock": "^4.2.0"
|
|
52
50
|
},
|
|
53
51
|
"typesVersions": {
|
|
54
52
|
"*": {
|
|
@@ -94,6 +92,10 @@
|
|
|
94
92
|
"types": "./dist/Model/Repository.d.ts",
|
|
95
93
|
"default": "./dist/Model/Repository.js"
|
|
96
94
|
},
|
|
95
|
+
"./Model/Repository/Registry": {
|
|
96
|
+
"types": "./dist/Model/Repository/Registry.d.ts",
|
|
97
|
+
"default": "./dist/Model/Repository/Registry.js"
|
|
98
|
+
},
|
|
97
99
|
"./Model/Repository/ext": {
|
|
98
100
|
"types": "./dist/Model/Repository/ext.d.ts",
|
|
99
101
|
"default": "./dist/Model/Repository/ext.js"
|
|
@@ -166,14 +168,6 @@
|
|
|
166
168
|
"types": "./dist/Model/query/new-kid-interpreter.d.ts",
|
|
167
169
|
"default": "./dist/Model/query/new-kid-interpreter.js"
|
|
168
170
|
},
|
|
169
|
-
"./Operations": {
|
|
170
|
-
"types": "./dist/Operations.d.ts",
|
|
171
|
-
"default": "./dist/Operations.js"
|
|
172
|
-
},
|
|
173
|
-
"./OperationsRepo": {
|
|
174
|
-
"types": "./dist/OperationsRepo.d.ts",
|
|
175
|
-
"default": "./dist/OperationsRepo.js"
|
|
176
|
-
},
|
|
177
171
|
"./QueueMaker/SQLQueue": {
|
|
178
172
|
"types": "./dist/QueueMaker/SQLQueue.d.ts",
|
|
179
173
|
"default": "./dist/QueueMaker/SQLQueue.js"
|
|
@@ -226,6 +220,18 @@
|
|
|
226
220
|
"types": "./dist/Store/Memory.d.ts",
|
|
227
221
|
"default": "./dist/Store/Memory.js"
|
|
228
222
|
},
|
|
223
|
+
"./Store/SQL": {
|
|
224
|
+
"types": "./dist/Store/SQL.d.ts",
|
|
225
|
+
"default": "./dist/Store/SQL.js"
|
|
226
|
+
},
|
|
227
|
+
"./Store/SQL/Pg": {
|
|
228
|
+
"types": "./dist/Store/SQL/Pg.d.ts",
|
|
229
|
+
"default": "./dist/Store/SQL/Pg.js"
|
|
230
|
+
},
|
|
231
|
+
"./Store/SQL/query": {
|
|
232
|
+
"types": "./dist/Store/SQL/query.d.ts",
|
|
233
|
+
"default": "./dist/Store/SQL/query.js"
|
|
234
|
+
},
|
|
229
235
|
"./Store/codeFilter": {
|
|
230
236
|
"types": "./dist/Store/codeFilter.d.ts",
|
|
231
237
|
"default": "./dist/Store/codeFilter.js"
|
|
@@ -366,6 +372,10 @@
|
|
|
366
372
|
"types": "./dist/logger/shared.d.ts",
|
|
367
373
|
"default": "./dist/logger/shared.js"
|
|
368
374
|
},
|
|
375
|
+
"./otel": {
|
|
376
|
+
"types": "./dist/otel.d.ts",
|
|
377
|
+
"default": "./dist/otel.js"
|
|
378
|
+
},
|
|
369
379
|
"./rateLimit": {
|
|
370
380
|
"types": "./dist/rateLimit.d.ts",
|
|
371
381
|
"default": "./dist/rateLimit.js"
|
|
@@ -384,18 +394,17 @@
|
|
|
384
394
|
"scripts": {
|
|
385
395
|
"watch": "pnpm build:tsc -w",
|
|
386
396
|
"build:tsc": "pnpm clean-dist && effect-app-cli packagejson pnpm check",
|
|
387
|
-
"check": "
|
|
397
|
+
"check": "tsgo --build",
|
|
388
398
|
"build": "pnpm build:tsc",
|
|
389
|
-
"watch2": "pnpm clean-dist && NODE_OPTIONS=--max-old-space-size=6144
|
|
399
|
+
"watch2": "pnpm clean-dist && NODE_OPTIONS=--max-old-space-size=6144 tsgo -w",
|
|
390
400
|
"clean": "rm -rf dist",
|
|
391
401
|
"clean-dist": "sh ../../scripts/clean-dist.sh",
|
|
392
402
|
"circular": "pnpm circular:src && pnpm circular:dist",
|
|
393
403
|
"circular:src": "madge --circular --ts-config ./tsconfig.json --extensions ts ./src",
|
|
394
404
|
"circular:dist": "madge --circular --extensions js ./dist",
|
|
395
|
-
"compile": "NODE_OPTIONS=--max-old-space-size=6144
|
|
396
|
-
"lint": "
|
|
397
|
-
"lint
|
|
398
|
-
"lint-fix": "pnpm lint --fix",
|
|
405
|
+
"compile": "NODE_OPTIONS=--max-old-space-size=6144 tsgo --noEmit",
|
|
406
|
+
"lint": "oxlint --quiet --type-aware ./src && pnpm exec dprint check --config ../../dprint.jsonc .",
|
|
407
|
+
"lint-fix": "oxlint --quiet --type-aware --fix ./src && pnpm exec dprint fmt --config ../../dprint.jsonc .",
|
|
399
408
|
"test": "vitest",
|
|
400
409
|
"test:run": "pnpm run test run --passWithNoTests",
|
|
401
410
|
"testsuite": "pnpm lint && pnpm circular && pnpm run test:run",
|
package/src/CUPS.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type FileOptions, tempFile } from "@effect-app/infra/fileUtil"
|
|
2
2
|
import cp from "child_process"
|
|
3
|
-
import { Config, Effect, Layer, Option, Predicate, S
|
|
3
|
+
import { Config, Context, Effect, Layer, Option, Predicate, S } from "effect-app"
|
|
4
4
|
import { pretty } from "effect-app/utils"
|
|
5
5
|
import fs from "fs"
|
|
6
6
|
import os from "os"
|
|
@@ -74,15 +74,13 @@ function printBuffer(printer: PrinterConfig, options: string[]) {
|
|
|
74
74
|
)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
})
|
|
85
|
-
}
|
|
77
|
+
const getAvailablePrinters = Effect.fnUntraced(function*(host?: string) {
|
|
78
|
+
const { stdout } = yield* exec(["lpstat", ...buildListArgs({ host }), "-s"].join(" "))
|
|
79
|
+
return [...stdout.matchAll(/device for (\w+):/g)]
|
|
80
|
+
.map((_) => _[1])
|
|
81
|
+
.filter(Predicate.isNotNullish)
|
|
82
|
+
.map((_) => S.NonEmptyString255(_))
|
|
83
|
+
})
|
|
86
84
|
|
|
87
85
|
function* buildListArgs(config?: { host?: string | undefined }) {
|
|
88
86
|
if (config?.host) {
|
|
@@ -100,7 +98,7 @@ export const CUPSConfig = Config.all({
|
|
|
100
98
|
)
|
|
101
99
|
})
|
|
102
100
|
|
|
103
|
-
export class CUPS extends
|
|
101
|
+
export class CUPS extends Context.Service<CUPS>()("effect-app/CUPS", {
|
|
104
102
|
make: Effect.gen(function*() {
|
|
105
103
|
const config = yield* CUPSConfig
|
|
106
104
|
const serverUrl = Option.getOrUndefined(config.server)
|
package/src/Emailer/Sendgrid.ts
CHANGED
|
@@ -7,7 +7,9 @@ import { inspect } from "util"
|
|
|
7
7
|
import { InfraLogger } from "../logger.js"
|
|
8
8
|
import { Emailer, type EmailMsg, type EmailMsgOptionalFrom, type SendgridConfig, SendMailError } from "./service.js"
|
|
9
9
|
|
|
10
|
-
const makeSendgrid = (
|
|
10
|
+
const makeSendgrid = (
|
|
11
|
+
{ apiKey, defaultFrom, defaultReplyTo, fakeMailAddress, realMail, subjectPrefix }: SendgridConfig
|
|
12
|
+
) =>
|
|
11
13
|
Effect.sync(() => {
|
|
12
14
|
sgMail.setApiKey(Redacted.value(apiKey))
|
|
13
15
|
|
|
@@ -18,7 +20,7 @@ const makeSendgrid = ({ apiKey, defaultFrom, defaultReplyTo, realMail, subjectPr
|
|
|
18
20
|
from: msg_.from ?? defaultFrom,
|
|
19
21
|
replyTo: msg_.replyTo ?? (msg_.from ? undefined : defaultReplyTo)
|
|
20
22
|
})
|
|
21
|
-
const render = renderMessage(!realMail)
|
|
23
|
+
const render = renderMessage(!realMail, fakeMailAddress)
|
|
22
24
|
|
|
23
25
|
const renderedMsg_ = render(msg)
|
|
24
26
|
const renderedMsg = {
|
|
@@ -68,23 +70,24 @@ export function Sendgrid(config: SendgridConfig) {
|
|
|
68
70
|
/**
|
|
69
71
|
* @hidden
|
|
70
72
|
*/
|
|
71
|
-
export function renderMessage(forceFake: boolean) {
|
|
73
|
+
export function renderMessage(forceFake: boolean, fakeMailAddress: string) {
|
|
72
74
|
let i = 0
|
|
73
75
|
const makeId = () => i++
|
|
76
|
+
const makeFakeEmail = () => fakeMailAddress.replace("{i}", String(makeId()))
|
|
74
77
|
return forceFake
|
|
75
78
|
? (msg: EmailMsg) =>
|
|
76
79
|
dropUndefinedT({
|
|
77
80
|
...msg,
|
|
78
|
-
to: msg.to && renderFake(msg.to,
|
|
79
|
-
cc: msg.cc && renderFake(msg.cc,
|
|
80
|
-
bcc: msg.bcc && renderFake(msg.bcc,
|
|
81
|
+
to: msg.to && renderFake(msg.to, makeFakeEmail),
|
|
82
|
+
cc: msg.cc && renderFake(msg.cc, makeFakeEmail),
|
|
83
|
+
bcc: msg.bcc && renderFake(msg.bcc, makeFakeEmail)
|
|
81
84
|
})
|
|
82
85
|
: (msg: EmailMsg) =>
|
|
83
86
|
dropUndefinedT({
|
|
84
87
|
...msg,
|
|
85
|
-
to: msg.to && renderFakeIfTest(msg.to,
|
|
86
|
-
cc: msg.cc && renderFakeIfTest(msg.cc,
|
|
87
|
-
bcc: msg.bcc && renderFakeIfTest(msg.bcc,
|
|
88
|
+
to: msg.to && renderFakeIfTest(msg.to, makeFakeEmail),
|
|
89
|
+
cc: msg.cc && renderFakeIfTest(msg.cc, makeFakeEmail),
|
|
90
|
+
bcc: msg.bcc && renderFakeIfTest(msg.bcc, makeFakeEmail)
|
|
88
91
|
})
|
|
89
92
|
}
|
|
90
93
|
|
|
@@ -100,10 +103,10 @@ export function isTestAddress(to: EmailData) {
|
|
|
100
103
|
)
|
|
101
104
|
}
|
|
102
105
|
|
|
103
|
-
function renderFake(addr: EmailData | readonly EmailData[],
|
|
106
|
+
function renderFake(addr: EmailData | readonly EmailData[], makeEmail: () => string) {
|
|
104
107
|
return {
|
|
105
108
|
name: renderMailData(addr),
|
|
106
|
-
email:
|
|
109
|
+
email: makeEmail()
|
|
107
110
|
}
|
|
108
111
|
}
|
|
109
112
|
const eq = Equivalence.mapInput(
|
|
@@ -117,14 +120,14 @@ function isEmailDataArray(md: EmailData | readonly EmailData[]): md is readonly
|
|
|
117
120
|
|
|
118
121
|
// TODO: should just not add any already added email address
|
|
119
122
|
// https://stackoverflow.com/a/53603076/11595834
|
|
120
|
-
function renderFakeIfTest(addr: EmailData | readonly EmailData[],
|
|
123
|
+
function renderFakeIfTest(addr: EmailData | readonly EmailData[], makeEmail: () => string) {
|
|
121
124
|
if (isEmailDataArray(addr)) {
|
|
122
125
|
return Array.dedupeWith(
|
|
123
|
-
addr.map((x) => (isTestAddress(x) ? renderFake(x,
|
|
126
|
+
addr.map((x) => (isTestAddress(x) ? renderFake(x, makeEmail) : x)),
|
|
124
127
|
eq
|
|
125
128
|
)
|
|
126
129
|
}
|
|
127
|
-
return isTestAddress(addr) ? renderFake(addr,
|
|
130
|
+
return isTestAddress(addr) ? renderFake(addr, makeEmail) : addr
|
|
128
131
|
}
|
|
129
132
|
|
|
130
133
|
function renderMailData(md: EmailData | readonly EmailData[]): string {
|
package/src/Emailer/service.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { MailContent, MailData } from "@sendgrid/helpers/classes/mail.js"
|
|
2
2
|
import type { ResponseError } from "@sendgrid/mail"
|
|
3
|
-
import { Data, type Effect, type NonEmptyReadonlyArray, type Redacted
|
|
3
|
+
import { Context, Data, type Effect, type NonEmptyReadonlyArray, type Redacted } from "effect-app"
|
|
4
4
|
import type { Email } from "effect-app/Schema"
|
|
5
5
|
|
|
6
6
|
export class SendMailError extends Data.TaggedError("SendMailError")<{
|
|
7
7
|
readonly raw: Error | ResponseError
|
|
8
8
|
}> {}
|
|
9
9
|
|
|
10
|
-
export class Emailer extends
|
|
10
|
+
export class Emailer extends Context.Opaque<Emailer, {
|
|
11
11
|
sendMail: (msg: EmailMsgOptionalFrom) => Effect.Effect<void, SendMailError>
|
|
12
12
|
}>()("effect-app/Emailer") {}
|
|
13
13
|
|
|
@@ -21,7 +21,13 @@ export interface SendgridConfig {
|
|
|
21
21
|
subjectPrefix: string
|
|
22
22
|
realMail: boolean
|
|
23
23
|
defaultFrom: EmailData
|
|
24
|
-
apiKey: Redacted.Redacted
|
|
24
|
+
apiKey: Redacted.Redacted
|
|
25
|
+
/**
|
|
26
|
+
* Email address used for fake/test recipients. Use `{i}` as a placeholder for an auto-incrementing index to ensure uniqueness.
|
|
27
|
+
*
|
|
28
|
+
* @example "test+{i}@example.com"
|
|
29
|
+
*/
|
|
30
|
+
fakeMailAddress: string
|
|
25
31
|
}
|
|
26
32
|
export type EmailTemplateMsg = MailData & { templateId: string }
|
|
27
33
|
|
package/src/MainFiberSet.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { Effect, Fiber, FiberSet, Layer
|
|
2
|
-
|
|
1
|
+
import { Context, Effect, Fiber, FiberSet, Layer } from "effect-app"
|
|
2
|
+
|
|
3
3
|
import { InfraLogger } from "./logger.js"
|
|
4
4
|
import { reportNonInterruptedFailureCause } from "./QueueMaker/errors.js"
|
|
5
5
|
import { setRootParentSpan } from "./RequestFiberSet.js"
|
|
6
6
|
|
|
7
7
|
const make = Effect.gen(function*() {
|
|
8
8
|
const set = yield* FiberSet.make<unknown, never>()
|
|
9
|
-
const add = (...fibers: Fiber.Fiber<never
|
|
10
|
-
|
|
11
|
-
const addAll = (fibers: readonly Fiber.Fiber<never, never>[]) =>
|
|
9
|
+
const add = (...fibers: Fiber.Fiber<never>[]) => Effect.sync(() => fibers.forEach((_) => FiberSet.addUnsafe(set, _)))
|
|
10
|
+
const addAll = (fibers: readonly Fiber.Fiber<never>[]) =>
|
|
12
11
|
Effect.sync(() => fibers.forEach((_) => FiberSet.addUnsafe(set, _)))
|
|
13
12
|
const join = FiberSet.size(set).pipe(
|
|
14
13
|
Effect.andThen((count) => InfraLogger.logDebug(`Joining ${count} current fibers on the MainFiberSet`)),
|
|
@@ -62,7 +61,7 @@ const make = Effect.gen(function*() {
|
|
|
62
61
|
* you should register these long running fibers in a FiberSet, and join them at the end of your main program.
|
|
63
62
|
* This way any errors will blow up the main program instead of fibers dying unknowingly.
|
|
64
63
|
*/
|
|
65
|
-
export class MainFiberSet extends
|
|
64
|
+
export class MainFiberSet extends Context.Service<MainFiberSet>()("MainFiberSet", { make }) {
|
|
66
65
|
static readonly Live = Layer.effect(this, this.make)
|
|
67
66
|
static readonly JoinLive = this.asEffect().pipe(
|
|
68
67
|
Effect.andThen((_) => _.join),
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Context, Effect } from "effect-app"
|
|
2
|
+
|
|
3
|
+
export interface RegisteredRepository {
|
|
4
|
+
readonly seedNamespace: (namespace: string) => Effect.Effect<void>
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const make = Effect.sync(() => {
|
|
8
|
+
const repos = new Map<string, RegisteredRepository>()
|
|
9
|
+
return {
|
|
10
|
+
register(modelName: string, repo: RegisteredRepository) {
|
|
11
|
+
repos.set(modelName, repo)
|
|
12
|
+
},
|
|
13
|
+
seedNamespace: (namespace: string) =>
|
|
14
|
+
Effect.suspend(() =>
|
|
15
|
+
Effect.forEach(
|
|
16
|
+
repos.values(),
|
|
17
|
+
(r) => r.seedNamespace(namespace),
|
|
18
|
+
{ concurrency: "unbounded", discard: true }
|
|
19
|
+
)
|
|
20
|
+
),
|
|
21
|
+
get entries(): ReadonlyMap<string, RegisteredRepository> {
|
|
22
|
+
return repos
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
export class RepositoryRegistry extends Context.Opaque<RepositoryRegistry, {
|
|
28
|
+
readonly register: (modelName: string, repo: RegisteredRepository) => void
|
|
29
|
+
readonly seedNamespace: (namespace: string) => Effect.Effect<void>
|
|
30
|
+
readonly entries: ReadonlyMap<string, RegisteredRepository>
|
|
31
|
+
}>()("effect-app/RepositoryRegistry", { make }) {}
|
|
32
|
+
|
|
33
|
+
export const RepositoryRegistryLive = RepositoryRegistry.toLayer(RepositoryRegistry.make)
|
|
@@ -9,6 +9,22 @@ import type { Query, QueryEnd, QueryWhere } from "../query.js"
|
|
|
9
9
|
import * as Q from "../query.js"
|
|
10
10
|
import type { Repository } from "./service.js"
|
|
11
11
|
|
|
12
|
+
interface BatchOptions {
|
|
13
|
+
readonly batch?: true | number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const asReadonlyArray = <T>(itemOrItems: T | ReadonlyArray<T>): ReadonlyArray<T> =>
|
|
17
|
+
globalThis.Array.isArray(itemOrItems)
|
|
18
|
+
? itemOrItems as ReadonlyArray<T>
|
|
19
|
+
: [itemOrItems as T]
|
|
20
|
+
|
|
21
|
+
const getBatchSize = (batch?: true | number) =>
|
|
22
|
+
batch === true
|
|
23
|
+
? 100
|
|
24
|
+
: typeof batch === "number" && Number.isFinite(batch) && batch > 0
|
|
25
|
+
? Math.floor(batch)
|
|
26
|
+
: undefined
|
|
27
|
+
|
|
12
28
|
export const extendRepo = <
|
|
13
29
|
T,
|
|
14
30
|
Encoded extends FieldValues,
|
|
@@ -16,9 +32,10 @@ export const extendRepo = <
|
|
|
16
32
|
ItemType extends string,
|
|
17
33
|
IdKey extends keyof T & keyof Encoded,
|
|
18
34
|
RSchema,
|
|
19
|
-
RPublish
|
|
35
|
+
RPublish,
|
|
36
|
+
RProvided = never
|
|
20
37
|
>(
|
|
21
|
-
repo: Repository<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish>
|
|
38
|
+
repo: Repository<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish, RProvided>
|
|
22
39
|
) => {
|
|
23
40
|
const get = (id: T[IdKey]) =>
|
|
24
41
|
repo.find(id).pipe(
|
|
@@ -109,7 +126,7 @@ export const extendRepo = <
|
|
|
109
126
|
) =>
|
|
110
127
|
| Query<Encoded>
|
|
111
128
|
| QueryWhere<Encoded>
|
|
112
|
-
| QueryEnd<Encoded
|
|
129
|
+
| QueryEnd<Encoded>,
|
|
113
130
|
pure: Effect.Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>
|
|
114
131
|
): Effect.Effect<
|
|
115
132
|
A,
|
|
@@ -126,7 +143,7 @@ export const extendRepo = <
|
|
|
126
143
|
) =>
|
|
127
144
|
| Query<Encoded>
|
|
128
145
|
| QueryWhere<Encoded>
|
|
129
|
-
| QueryEnd<Encoded
|
|
146
|
+
| QueryEnd<Encoded>,
|
|
130
147
|
pure: Effect.Effect<A, E2, FixEnv<R2, Evt, readonly T[], readonly T2[]>>,
|
|
131
148
|
batch: "batched" | number
|
|
132
149
|
): Effect.Effect<
|
|
@@ -214,8 +231,7 @@ export const extendRepo = <
|
|
|
214
231
|
_key: unknown
|
|
215
232
|
) =>
|
|
216
233
|
(repo.query(Q.where(repo.idKey as any, "in" as any, entries.map((_) => _.request.id)) as any) as Effect.Effect<
|
|
217
|
-
readonly T[]
|
|
218
|
-
never
|
|
234
|
+
readonly T[]
|
|
219
235
|
>)
|
|
220
236
|
// TODO
|
|
221
237
|
.pipe(
|
|
@@ -244,8 +260,77 @@ export const extendRepo = <
|
|
|
244
260
|
request: (id: T[IdKey]) => Effect.request(_request({ id }), requestResolver),
|
|
245
261
|
get,
|
|
246
262
|
log: (evt: Evt) => AnyPureDSL.log(evt),
|
|
247
|
-
|
|
263
|
+
/**
|
|
264
|
+
* Enables chunked writes for large batches via `options.batch`.
|
|
265
|
+
* Note: batching breaks transactional properties because chunks are saved independently.
|
|
266
|
+
*/
|
|
267
|
+
save: ((itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
|
|
268
|
+
const items = asReadonlyArray(itemOrItems)
|
|
269
|
+
if (!Array.isReadonlyArrayNonEmpty(items)) {
|
|
270
|
+
return Effect.void
|
|
271
|
+
}
|
|
272
|
+
const batchSize = getBatchSize(options?.batch)
|
|
273
|
+
if (batchSize === undefined) {
|
|
274
|
+
return repo.saveAndPublish(items)
|
|
275
|
+
}
|
|
276
|
+
return Effect.forEach(
|
|
277
|
+
Array.chunksOf(items, batchSize),
|
|
278
|
+
(batch) => repo.saveAndPublish(batch),
|
|
279
|
+
{ discard: true }
|
|
280
|
+
)
|
|
281
|
+
}) as (
|
|
282
|
+
itemOrItems: T | ReadonlyArray<T>,
|
|
283
|
+
options?: BatchOptions
|
|
284
|
+
) => Effect.Effect<
|
|
285
|
+
void,
|
|
286
|
+
InvalidStateError | OptimisticConcurrencyException,
|
|
287
|
+
RSchema | RPublish
|
|
288
|
+
>,
|
|
248
289
|
saveWithEvents: (events: Iterable<Evt>) => (...items: NonEmptyArray<T>) => repo.saveAndPublish(items, events),
|
|
290
|
+
/**
|
|
291
|
+
* Enables chunked deletes for large batches via `options.batch`.
|
|
292
|
+
* Note: batching breaks transactional properties because chunks are removed independently.
|
|
293
|
+
*/
|
|
294
|
+
remove: ((itemOrItems: T | ReadonlyArray<T>, options?: BatchOptions) => {
|
|
295
|
+
const items = asReadonlyArray(itemOrItems)
|
|
296
|
+
if (!Array.isReadonlyArrayNonEmpty(items)) {
|
|
297
|
+
return Effect.void
|
|
298
|
+
}
|
|
299
|
+
const batchSize = getBatchSize(options?.batch)
|
|
300
|
+
if (batchSize === undefined) {
|
|
301
|
+
return repo.removeAndPublish(items)
|
|
302
|
+
}
|
|
303
|
+
return Effect.forEach(
|
|
304
|
+
Array.chunksOf(items, batchSize),
|
|
305
|
+
(batch) => repo.removeAndPublish(batch),
|
|
306
|
+
{ discard: true }
|
|
307
|
+
)
|
|
308
|
+
}) as (
|
|
309
|
+
itemOrItems: T | ReadonlyArray<T>,
|
|
310
|
+
options?: BatchOptions
|
|
311
|
+
) => Effect.Effect<void, never, RSchema | RPublish>,
|
|
312
|
+
/**
|
|
313
|
+
* Enables chunked deletes for large batches via `options.batch`.
|
|
314
|
+
* Note: batching breaks transactional properties because chunks are removed independently.
|
|
315
|
+
*/
|
|
316
|
+
removeById: ((idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>, options?: BatchOptions) => {
|
|
317
|
+
const ids = asReadonlyArray(idOrIds)
|
|
318
|
+
if (!Array.isReadonlyArrayNonEmpty(ids)) {
|
|
319
|
+
return Effect.void
|
|
320
|
+
}
|
|
321
|
+
const batchSize = getBatchSize(options?.batch)
|
|
322
|
+
if (batchSize === undefined) {
|
|
323
|
+
return repo.removeById(ids)
|
|
324
|
+
}
|
|
325
|
+
return Effect.forEach(
|
|
326
|
+
Array.chunksOf(ids, batchSize),
|
|
327
|
+
(batch) => repo.removeById(batch),
|
|
328
|
+
{ discard: true }
|
|
329
|
+
)
|
|
330
|
+
}) as (
|
|
331
|
+
idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>,
|
|
332
|
+
options?: BatchOptions
|
|
333
|
+
) => Effect.Effect<void, never, RSchema>,
|
|
249
334
|
queryAndSavePure,
|
|
250
335
|
saveManyWithPure,
|
|
251
336
|
byIdAndSaveWithPure,
|
|
@@ -268,7 +353,7 @@ export const extendRepo = <
|
|
|
268
353
|
return {
|
|
269
354
|
...repo,
|
|
270
355
|
...exts
|
|
271
|
-
} as Repository<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish> & typeof exts
|
|
356
|
+
} as Repository<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish, RProvided> & typeof exts
|
|
272
357
|
}
|
|
273
358
|
|
|
274
359
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
@@ -279,5 +364,6 @@ export interface ExtendedRepository<
|
|
|
279
364
|
ItemType extends string,
|
|
280
365
|
IdKey extends keyof T & keyof Encoded,
|
|
281
366
|
RSchema,
|
|
282
|
-
RPublish
|
|
283
|
-
|
|
367
|
+
RPublish,
|
|
368
|
+
RProvided = never
|
|
369
|
+
> extends ReturnType<typeof extendRepo<T, Encoded, Evt, ItemType, IdKey, RSchema, RPublish, RProvided>> {}
|