@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
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
2
|
+
|
|
3
|
+
import * as Array from "effect-app/Array"
|
|
4
|
+
import type { NonEmptyReadonlyArray } from "effect-app/Array"
|
|
5
5
|
import { toNonEmptyArray } from "effect-app/Array"
|
|
6
|
+
import * as Chunk from "effect-app/Chunk"
|
|
6
7
|
import { NotFoundError } from "effect-app/client/errors"
|
|
8
|
+
import * as Context from "effect-app/Context"
|
|
9
|
+
import * as Effect from "effect-app/Effect"
|
|
7
10
|
import { flatMapOption } from "effect-app/Effect"
|
|
11
|
+
import * as Option from "effect-app/Option"
|
|
12
|
+
import * as S from "effect-app/Schema"
|
|
8
13
|
import { type Codec, NonNegativeInt } from "effect-app/Schema"
|
|
14
|
+
import * as Equivalence from "effect/Equivalence"
|
|
15
|
+
import { flow, pipe } from "effect/Function"
|
|
16
|
+
import * as Pipeable from "effect/Pipeable"
|
|
17
|
+
import * as PubSub from "effect/PubSub"
|
|
18
|
+
import * as Result from "effect/Result"
|
|
19
|
+
import * as SchemaAST from "effect/SchemaAST"
|
|
20
|
+
import * as Unify from "effect/Unify"
|
|
9
21
|
import { setupRequestContextFromCurrent } from "../../../api/setupRequest.js"
|
|
10
22
|
import { type FilterArgs, type PersistenceModelType, type StoreConfig, StoreMaker } from "../../../Store.js"
|
|
11
23
|
import { getContextMap } from "../../../Store/ContextMapContainer.js"
|
|
@@ -55,14 +67,14 @@ export function makeRepoInternal<
|
|
|
55
67
|
|
|
56
68
|
function make<RInitial = never, E = never, RPublish = never, RCtx = never>(
|
|
57
69
|
args: [Evt] extends [never] ? {
|
|
58
|
-
schemaContext?:
|
|
70
|
+
schemaContext?: Context.Context<RCtx>
|
|
59
71
|
makeInitial?: Effect.Effect<readonly T[], E, RInitial> | undefined
|
|
60
72
|
config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
|
|
61
73
|
partitionValue?: (e?: Encoded) => string
|
|
62
74
|
}
|
|
63
75
|
}
|
|
64
76
|
: {
|
|
65
|
-
schemaContext?:
|
|
77
|
+
schemaContext?: Context.Context<RCtx>
|
|
66
78
|
publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect.Effect<void, never, RPublish>
|
|
67
79
|
makeInitial?: Effect.Effect<readonly T[], E, RInitial> | undefined
|
|
68
80
|
config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
|
|
@@ -72,16 +84,16 @@ export function makeRepoInternal<
|
|
|
72
84
|
) {
|
|
73
85
|
return Effect
|
|
74
86
|
.gen(function*() {
|
|
75
|
-
const rctx:
|
|
87
|
+
const rctx: Context.Context<RCtx> = args.schemaContext ?? Context.empty() as any
|
|
76
88
|
const provideRctx = Effect.provide(rctx)
|
|
77
89
|
const encodeMany = flow(
|
|
78
90
|
S.encodeEffect(S.Array(schema)),
|
|
79
91
|
provideRctx,
|
|
80
|
-
Effect.withSpan("encodeMany", {}, { captureStackTrace: false })
|
|
92
|
+
Effect.withSpan("encodeMany", { attributes: { "app.entity": name } }, { captureStackTrace: false })
|
|
81
93
|
)
|
|
82
|
-
const decode = flow(S.
|
|
94
|
+
const decode = flow(S.decodeEffectConcurrently(schema), provideRctx)
|
|
83
95
|
const decodeMany = flow(
|
|
84
|
-
S.
|
|
96
|
+
S.decodeEffectConcurrently(S.Array(schema)),
|
|
85
97
|
provideRctx
|
|
86
98
|
)
|
|
87
99
|
|
|
@@ -104,7 +116,13 @@ export function makeRepoInternal<
|
|
|
104
116
|
allE,
|
|
105
117
|
(_) => decodeMany(_).pipe(Effect.orDie)
|
|
106
118
|
)
|
|
107
|
-
.pipe(
|
|
119
|
+
.pipe(
|
|
120
|
+
Effect.map((_) => _ as T[]),
|
|
121
|
+
Effect.withSpan("Repository.all", {
|
|
122
|
+
kind: "client",
|
|
123
|
+
attributes: { "app.entity": name }
|
|
124
|
+
}, { captureStackTrace: false })
|
|
125
|
+
)
|
|
108
126
|
|
|
109
127
|
const fieldsSchema = schema as unknown as { fields: any }
|
|
110
128
|
// assumes the id field never needs a service...
|
|
@@ -113,11 +131,14 @@ export function makeRepoInternal<
|
|
|
113
131
|
let ast = _.ast
|
|
114
132
|
if (ast._tag === "Declaration") ast = ast.typeParameters[0]!
|
|
115
133
|
|
|
116
|
-
// In v4, to get the encoded (from) side of a schema, use SchemaAST.toEncoded
|
|
117
134
|
const pickIdFromAst = (a: SchemaAST.AST) => {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
135
|
+
// Unwrap Declaration (e.g. TaggedClass) to get the underlying Objects AST
|
|
136
|
+
let inner = a
|
|
137
|
+
if (inner._tag === "Declaration") inner = inner.typeParameters[0]!
|
|
138
|
+
// Pick from the original AST to preserve the full encoding chain (e.g. decodeTo transformations).
|
|
139
|
+
// Using toEncoded would lose transformation info needed to encode Type -> Encoded.
|
|
140
|
+
if (SchemaAST.isObjects(inner)) {
|
|
141
|
+
const field = inner.propertySignatures.find((_) => _.name === idKey)
|
|
121
142
|
if (field) {
|
|
122
143
|
return S.Struct({ [idKey]: S.make(field.type) }) as unknown as Codec<T, Encoded>
|
|
123
144
|
}
|
|
@@ -138,7 +159,7 @@ export function makeRepoInternal<
|
|
|
138
159
|
Effect.map((_: Record<string, unknown>) => _[idKey as string] as Encoded[IdKey])
|
|
139
160
|
)
|
|
140
161
|
const findEId = Effect.fnUntraced(function*(id: Encoded[IdKey]) {
|
|
141
|
-
yield* Effect.annotateCurrentSpan({
|
|
162
|
+
yield* Effect.annotateCurrentSpan({ "app.entity.id": id })
|
|
142
163
|
|
|
143
164
|
return yield* Effect.flatMap(
|
|
144
165
|
store.find(id),
|
|
@@ -151,7 +172,7 @@ export function makeRepoInternal<
|
|
|
151
172
|
})
|
|
152
173
|
// TODO: select the particular field, instead of as struct
|
|
153
174
|
const findE = Effect.fnUntraced(function*(id: T[IdKey]) {
|
|
154
|
-
yield* Effect.annotateCurrentSpan({
|
|
175
|
+
yield* Effect.annotateCurrentSpan({ "app.entity.id": id })
|
|
155
176
|
|
|
156
177
|
return yield* pipe(
|
|
157
178
|
encodeId({ [idKey]: id } as any),
|
|
@@ -161,9 +182,11 @@ export function makeRepoInternal<
|
|
|
161
182
|
)
|
|
162
183
|
})
|
|
163
184
|
|
|
164
|
-
const find = Effect.fn("find"
|
|
165
|
-
|
|
166
|
-
|
|
185
|
+
const find = Effect.fn("Repository.find", {
|
|
186
|
+
kind: "client",
|
|
187
|
+
attributes: { "app.entity": name }
|
|
188
|
+
})(function*(id: T[IdKey]) {
|
|
189
|
+
yield* Effect.annotateCurrentSpan({ "app.entity.id": id })
|
|
167
190
|
return yield* flatMapOption(findE(id), (_) => Effect.orDie(decode(_)))
|
|
168
191
|
})
|
|
169
192
|
|
|
@@ -188,73 +211,96 @@ export function makeRepoInternal<
|
|
|
188
211
|
Effect.andThen(saveAllE)
|
|
189
212
|
)
|
|
190
213
|
|
|
191
|
-
const saveAndPublish = Effect.fn("saveAndPublish"
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
214
|
+
const saveAndPublish = Effect.fn("Repository.saveAndPublish", { attributes: { "app.entity": name } })(
|
|
215
|
+
function*(items: Iterable<T>, events: Iterable<Evt> = []) {
|
|
216
|
+
const it = Chunk.fromIterable(items)
|
|
217
|
+
const evts = [...events]
|
|
218
|
+
yield* Effect.annotateCurrentSpan({
|
|
219
|
+
"app.entity.ids": Chunk.map(it, (_) => _[idKey]),
|
|
220
|
+
"app.event.count": evts.length
|
|
221
|
+
})
|
|
222
|
+
return yield* saveAll(it)
|
|
223
|
+
.pipe(
|
|
224
|
+
Effect.andThen(Effect.sync(() => toNonEmptyArray(evts))),
|
|
225
|
+
// TODO: for full consistency the events should be stored within the same database transaction, and then picked up.
|
|
226
|
+
(_) => flatMapOption(_, pub),
|
|
227
|
+
Effect.andThen(PubSub.publish(changeFeed, [Chunk.toArray(it), "save"] as [T[], "save" | "remove"])),
|
|
228
|
+
Effect.asVoid
|
|
229
|
+
)
|
|
230
|
+
}
|
|
231
|
+
)
|
|
204
232
|
|
|
205
|
-
const removeAndPublish = Effect.fn("removeAndPublish"
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
|
|
233
|
+
const removeAndPublish = Effect.fn("Repository.removeAndPublish", { attributes: { "app.entity": name } })(
|
|
234
|
+
function*(a: Iterable<T>, events: Iterable<Evt> = []) {
|
|
235
|
+
const { set } = yield* cms
|
|
236
|
+
const it = [...a]
|
|
237
|
+
const evts = [...events]
|
|
238
|
+
yield* Effect.annotateCurrentSpan({
|
|
239
|
+
"app.entity.ids": it.map((_) => _[idKey]),
|
|
240
|
+
"app.event.count": evts.length
|
|
241
|
+
})
|
|
242
|
+
const items = yield* encodeMany(it).pipe(Effect.orDie)
|
|
243
|
+
if (Array.isReadonlyArrayNonEmpty(items)) {
|
|
244
|
+
yield* store.batchRemove(
|
|
245
|
+
items.map((_) => (_[idKey])),
|
|
246
|
+
args.config?.partitionValue?.(items[0])
|
|
247
|
+
)
|
|
248
|
+
for (const e of items) {
|
|
249
|
+
set(e[idKey], undefined)
|
|
250
|
+
}
|
|
251
|
+
yield* Effect
|
|
252
|
+
.sync(() => toNonEmptyArray(evts))
|
|
253
|
+
// TODO: for full consistency the events should be stored within the same database transaction, and then picked up.
|
|
254
|
+
.pipe((_) => flatMapOption(_, pub))
|
|
255
|
+
|
|
256
|
+
yield* PubSub.publish(changeFeed, [it, "remove"] as [T[], "save" | "remove"])
|
|
218
257
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
// TODO: for full consistency the events should be stored within the same database transaction, and then picked up.
|
|
222
|
-
.pipe((_) => flatMapOption(_, pub))
|
|
258
|
+
}
|
|
259
|
+
)
|
|
223
260
|
|
|
224
|
-
|
|
261
|
+
const removeById = Effect.fn("Repository.removeById", { attributes: { "app.entity": name } })(
|
|
262
|
+
function*(idOrIds: T[IdKey] | ReadonlyArray<T[IdKey]>) {
|
|
263
|
+
const ids = globalThis.Array.isArray(idOrIds)
|
|
264
|
+
? idOrIds as readonly T[IdKey][]
|
|
265
|
+
: [idOrIds as T[IdKey]]
|
|
266
|
+
if (!Array.isReadonlyArrayNonEmpty(ids)) {
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
const { set } = yield* cms
|
|
270
|
+
const eids = yield* Effect.forEach(ids, (_) => encodeIdOnly(_ as any)).pipe(Effect.orDie)
|
|
271
|
+
yield* Effect.annotateCurrentSpan({ "app.entity.ids": eids })
|
|
272
|
+
yield* store.batchRemove(eids)
|
|
273
|
+
for (const id of eids) {
|
|
274
|
+
set(id, undefined)
|
|
275
|
+
}
|
|
276
|
+
yield* PubSub.publish(changeFeed, [[], "remove"] as [T[], "save" | "remove"])
|
|
225
277
|
}
|
|
226
|
-
|
|
278
|
+
)
|
|
227
279
|
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
280
|
+
const parseMany = Effect.fn("parseMany", { attributes: { "app.entity": name } })(
|
|
281
|
+
function*(items: readonly PM[]) {
|
|
282
|
+
const cm = yield* cms
|
|
283
|
+
return yield* decodeMany(items.map((_) => mapReverse(_, cm.set))).pipe(Effect.orDie)
|
|
231
284
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
285
|
+
)
|
|
286
|
+
const decodeManyCache = new WeakMap<
|
|
287
|
+
S.Codec<any, any, any>,
|
|
288
|
+
(i: readonly any[]) => Effect.Effect<any, any, any>
|
|
289
|
+
>()
|
|
290
|
+
const getDecodeMany = (s: S.Codec<any, Encoded, any>) => {
|
|
291
|
+
let dec = decodeManyCache.get(s)
|
|
292
|
+
if (!dec) {
|
|
293
|
+
dec = S.decodeEffectConcurrently(S.Array(s))
|
|
294
|
+
decodeManyCache.set(s, dec)
|
|
238
295
|
}
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
.
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const parseMany2 = <A, R>(
|
|
248
|
-
items: readonly PM[],
|
|
249
|
-
schema: S.Codec<A, Encoded, R>
|
|
250
|
-
) =>
|
|
251
|
-
Effect
|
|
252
|
-
.flatMap(cms, (cm) =>
|
|
253
|
-
S
|
|
254
|
-
.decodeEffect(S.Array(schema))(
|
|
255
|
-
items.map((_) => mapReverse(_, cm.set))
|
|
256
|
-
)
|
|
257
|
-
.pipe(Effect.orDie, Effect.withSpan("parseMany2", {}, { captureStackTrace: false })))
|
|
296
|
+
return dec
|
|
297
|
+
}
|
|
298
|
+
const parseMany2 = Effect.fn("parseMany2", { attributes: { "app.entity": name } })(
|
|
299
|
+
function*<A, R>(items: readonly PM[], schema: S.Codec<A, Encoded, R>) {
|
|
300
|
+
const cm = yield* cms
|
|
301
|
+
return yield* getDecodeMany(schema)(items.map((_) => mapReverse(_, cm.set))).pipe(Effect.orDie)
|
|
302
|
+
}
|
|
303
|
+
)
|
|
258
304
|
const filter = <U extends keyof Encoded = keyof Encoded>(args: FilterArgs<Encoded, U>) =>
|
|
259
305
|
store
|
|
260
306
|
.filter(
|
|
@@ -276,24 +322,28 @@ export function makeRepoInternal<
|
|
|
276
322
|
const query: {
|
|
277
323
|
<A, R, From extends FieldValues>(
|
|
278
324
|
q: Q.QueryProjection<Encoded extends From ? From : never, A, R>
|
|
279
|
-
): Effect.Effect<readonly A[], S.SchemaError, R
|
|
325
|
+
): Effect.Effect<readonly A[], S.SchemaError, Exclude<R, RCtx>>
|
|
280
326
|
<A, R, EncodedRefined extends Encoded = Encoded>(
|
|
281
327
|
q: Q.QAll<NoInfer<Encoded>, NoInfer<EncodedRefined>, A, R>
|
|
282
|
-
): Effect.Effect<readonly A[], never, R
|
|
328
|
+
): Effect.Effect<readonly A[], never, Exclude<R, RCtx>>
|
|
283
329
|
} = (<A, R, EncodedRefined extends Encoded = Encoded>(q: Q.QAll<Encoded, EncodedRefined, A, R>) => {
|
|
284
|
-
const a = Q.toFilter(q)
|
|
330
|
+
const a = Q.toFilter(q, schema)
|
|
331
|
+
// Mode dispatch — see `Q.project` JSDoc for the contract:
|
|
332
|
+
// project : decode raw encoded rows with schema; no PM reverse-mapping; SchemaError surfaces.
|
|
333
|
+
// collect : same as project, but schema yields Option and None rows are dropped.
|
|
334
|
+
// transform: PM reverse-map (re-inject _etag/PM state from cms cache) then decode; orDie.
|
|
285
335
|
const eff = a.mode === "project"
|
|
286
336
|
? filter(a)
|
|
287
337
|
// TODO: mapFrom but need to support per field and dependencies
|
|
288
338
|
.pipe(
|
|
289
|
-
Effect.andThen(flow(S.
|
|
339
|
+
Effect.andThen(flow(S.decodeEffectConcurrently(S.Array(a.schema ?? schema)), provideRctx))
|
|
290
340
|
)
|
|
291
341
|
: a.mode === "collect"
|
|
292
342
|
? filter(a)
|
|
293
343
|
// TODO: mapFrom but need to support per field and dependencies
|
|
294
344
|
.pipe(
|
|
295
345
|
Effect.flatMap(flow(
|
|
296
|
-
S.
|
|
346
|
+
S.decodeEffectConcurrently(S.Array(a.schema)),
|
|
297
347
|
Effect.map(Array.getSomes),
|
|
298
348
|
provideRctx
|
|
299
349
|
))
|
|
@@ -325,72 +375,89 @@ export function makeRepoInternal<
|
|
|
325
375
|
.map(eff, (_) => NonNegativeInt(_.length))
|
|
326
376
|
.pipe(Effect.catchTag("SchemaError", (e) => Effect.die(e)))
|
|
327
377
|
: eff,
|
|
328
|
-
Effect.
|
|
329
|
-
|
|
330
|
-
"
|
|
331
|
-
query
|
|
332
|
-
|
|
378
|
+
Effect.tap((r) =>
|
|
379
|
+
Effect.annotateCurrentSpan({
|
|
380
|
+
"app.query.ttype": a.ttype,
|
|
381
|
+
"app.query.mode": a.mode,
|
|
382
|
+
"db.response.returned_rows": Array.isArray(r) ? r.length : 1
|
|
383
|
+
})
|
|
384
|
+
),
|
|
385
|
+
Effect.withSpan("Repository.query", {
|
|
386
|
+
kind: "client",
|
|
387
|
+
attributes: { "app.entity": name }
|
|
333
388
|
}, { captureStackTrace: false })
|
|
334
389
|
)
|
|
335
390
|
}) as any
|
|
336
391
|
|
|
337
|
-
const validateSample = Effect.fn("validateSample")(
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
392
|
+
const validateSample = Effect.fn("Repository.validateSample", { attributes: { "app.entity": name } })(
|
|
393
|
+
function*(options?: {
|
|
394
|
+
percentage?: number
|
|
395
|
+
maxItems?: number
|
|
396
|
+
}) {
|
|
397
|
+
const percentage = options?.percentage ?? 0.1 // default 10%
|
|
398
|
+
const maxItems = options?.maxItems
|
|
399
|
+
|
|
400
|
+
// 1. get all IDs with projection (bypasses main schema decode)
|
|
401
|
+
const allIds = yield* store
|
|
402
|
+
.filter({
|
|
403
|
+
t: null as unknown as Encoded,
|
|
404
|
+
select: [idKey as keyof Encoded]
|
|
405
|
+
})
|
|
406
|
+
.pipe(Effect.withSpan("Repository.filter", {
|
|
407
|
+
kind: "client",
|
|
408
|
+
attributes: { "app.entity": name }
|
|
409
|
+
}, { captureStackTrace: false }))
|
|
410
|
+
|
|
411
|
+
// 2. random subset
|
|
412
|
+
const shuffled = [...allIds].sort(() => Math.random() - 0.5)
|
|
413
|
+
const sampleSize = Math.min(
|
|
414
|
+
maxItems ?? Infinity,
|
|
415
|
+
Math.ceil(allIds.length * percentage)
|
|
416
|
+
)
|
|
417
|
+
const sample = shuffled.slice(0, sampleSize)
|
|
418
|
+
|
|
419
|
+
// 3. validate each item
|
|
420
|
+
const errors: ValidationError[] = []
|
|
421
|
+
|
|
422
|
+
for (const item of sample) {
|
|
423
|
+
const id = item[idKey]
|
|
424
|
+
const rawResult = yield* store.find(id).pipe(
|
|
425
|
+
Effect.withSpan("Repository.find", {
|
|
426
|
+
kind: "client",
|
|
427
|
+
attributes: { "app.entity": name, "app.entity.id": id }
|
|
428
|
+
}, { captureStackTrace: false })
|
|
429
|
+
)
|
|
366
430
|
|
|
367
|
-
|
|
368
|
-
const jitMResult = mapFrom(rawData) // apply jitM
|
|
431
|
+
if (Option.isNone(rawResult)) continue
|
|
369
432
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
provideRctx
|
|
373
|
-
)
|
|
433
|
+
const rawData = rawResult.value as Encoded
|
|
434
|
+
const jitMResult = mapFrom(rawData) // apply jitM
|
|
374
435
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
id,
|
|
379
|
-
rawData,
|
|
380
|
-
jitMResult,
|
|
381
|
-
error: decodeResult.failure
|
|
382
|
-
})
|
|
436
|
+
const decodeResult = yield* S.decodeEffectConcurrently(schema)(jitMResult).pipe(
|
|
437
|
+
Effect.result,
|
|
438
|
+
provideRctx
|
|
383
439
|
)
|
|
440
|
+
|
|
441
|
+
if (Result.isFailure(decodeResult)) {
|
|
442
|
+
errors.push(
|
|
443
|
+
ValidationError.make({
|
|
444
|
+
id,
|
|
445
|
+
rawData,
|
|
446
|
+
jitMResult,
|
|
447
|
+
error: decodeResult.failure
|
|
448
|
+
})
|
|
449
|
+
)
|
|
450
|
+
}
|
|
384
451
|
}
|
|
385
|
-
}
|
|
386
452
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
453
|
+
return ValidationResult.make({
|
|
454
|
+
total: NonNegativeInt(allIds.length),
|
|
455
|
+
sampled: NonNegativeInt(sample.length),
|
|
456
|
+
valid: NonNegativeInt(sample.length - errors.length),
|
|
457
|
+
errors
|
|
458
|
+
})
|
|
459
|
+
}
|
|
460
|
+
)
|
|
394
461
|
|
|
395
462
|
const r = {
|
|
396
463
|
changeFeed,
|
|
@@ -401,10 +468,17 @@ export function makeRepoInternal<
|
|
|
401
468
|
saveAndPublish,
|
|
402
469
|
removeAndPublish,
|
|
403
470
|
removeById,
|
|
471
|
+
seedNamespace: (namespace: string) => store.seedNamespace(namespace),
|
|
404
472
|
validateSample,
|
|
405
473
|
queryRaw<A, Out, QR>(schema: S.Codec<A, Out, QR>, q: Q.RawQuery<Encoded, Out>) {
|
|
406
|
-
const dec = S.
|
|
407
|
-
return store.queryRaw(q).pipe(
|
|
474
|
+
const dec = S.decodeEffectConcurrently(S.Array(schema))
|
|
475
|
+
return store.queryRaw(q).pipe(
|
|
476
|
+
Effect.flatMap(dec),
|
|
477
|
+
Effect.withSpan("Repository.queryRaw", {
|
|
478
|
+
kind: "client",
|
|
479
|
+
attributes: { "app.entity": name }
|
|
480
|
+
}, { captureStackTrace: false })
|
|
481
|
+
)
|
|
408
482
|
},
|
|
409
483
|
query(q: any) {
|
|
410
484
|
// eslint-disable-next-line prefer-rest-params
|
|
@@ -414,15 +488,23 @@ export function makeRepoInternal<
|
|
|
414
488
|
* @internal
|
|
415
489
|
*/
|
|
416
490
|
mapped: <A, R>(schema: S.Codec<A, any, R>) => {
|
|
417
|
-
const dec = S.
|
|
491
|
+
const dec = S.decodeEffectConcurrently(schema)
|
|
418
492
|
const encMany = S.encodeEffect(S.Array(schema))
|
|
419
|
-
const decMany = S.
|
|
493
|
+
const decMany = S.decodeEffectConcurrently(S.Array(schema))
|
|
494
|
+
const spanAttrs = { kind: "client" as const, attributes: { "app.entity": name } }
|
|
420
495
|
return {
|
|
421
496
|
all: allE.pipe(
|
|
422
497
|
Effect.flatMap(decMany),
|
|
423
|
-
Effect.map((_) => _ as any[])
|
|
498
|
+
Effect.map((_) => _ as any[]),
|
|
499
|
+
Effect.withSpan("Repository.mapped.all", spanAttrs, { captureStackTrace: false })
|
|
424
500
|
),
|
|
425
|
-
find: (id: T[IdKey]) =>
|
|
501
|
+
find: (id: T[IdKey]) =>
|
|
502
|
+
flatMapOption(findE(id), dec).pipe(
|
|
503
|
+
Effect.withSpan("Repository.mapped.find", {
|
|
504
|
+
...spanAttrs,
|
|
505
|
+
attributes: { ...spanAttrs.attributes, "app.entity.id": id }
|
|
506
|
+
}, { captureStackTrace: false })
|
|
507
|
+
),
|
|
426
508
|
// query: (q: any) => {
|
|
427
509
|
// const a = Q.toFilter(q)
|
|
428
510
|
|
|
@@ -441,12 +523,12 @@ export function makeRepoInternal<
|
|
|
441
523
|
// },
|
|
442
524
|
save: (...xes: any[]) =>
|
|
443
525
|
Effect.flatMap(encMany(xes), (_) => saveAllE(_)).pipe(
|
|
444
|
-
Effect.withSpan("mapped.save",
|
|
526
|
+
Effect.withSpan("Repository.mapped.save", spanAttrs, { captureStackTrace: false })
|
|
445
527
|
)
|
|
446
528
|
}
|
|
447
529
|
}
|
|
448
530
|
}
|
|
449
|
-
return r as Repository<T, Encoded, Evt, ItemType, IdKey, Exclude<R, RCtx>, RPublish>
|
|
531
|
+
return r as Repository<T, Encoded, Evt, ItemType, IdKey, Exclude<R, RCtx>, RPublish, RCtx>
|
|
450
532
|
})
|
|
451
533
|
.pipe(Effect
|
|
452
534
|
// .withSpan("Repository.make [effect-app/infra]", { attributes: { "repository.model_name": name } })
|
|
@@ -513,7 +595,7 @@ export function makeStore<Encoded extends FieldValues>() {
|
|
|
513
595
|
.pipe(
|
|
514
596
|
Effect.flatMap(Effect.forEach(encodeToEncoded())),
|
|
515
597
|
setupRequestContextFromCurrent("Repository.makeInitial [effect-app/infra]", {
|
|
516
|
-
attributes: { "
|
|
598
|
+
attributes: { "app.entity": name }
|
|
517
599
|
})
|
|
518
600
|
)
|
|
519
601
|
: undefined,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
|
-
import type { Effect, Option, S } from "effect-app"
|
|
4
3
|
import type { OptimisticConcurrencyException } from "effect-app/client/errors"
|
|
4
|
+
import type * as Effect from "effect-app/Effect"
|
|
5
|
+
import type * as Option from "effect-app/Option"
|
|
6
|
+
import type * as S from "effect-app/Schema"
|
|
5
7
|
|
|
6
8
|
export interface Mapped1<A, IdKey extends keyof A, R> {
|
|
7
9
|
all: Effect.Effect<A[], S.SchemaError, R>
|
|
@@ -5,13 +5,16 @@
|
|
|
5
5
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
6
6
|
|
|
7
7
|
// import type { ParserEnv } from "effect-app/Schema/custom/Parser"
|
|
8
|
-
|
|
9
|
-
import type {} from "effect/
|
|
10
|
-
import
|
|
8
|
+
|
|
9
|
+
import type { NonEmptyReadonlyArray } from "effect-app/Array"
|
|
10
|
+
import type * as Context from "effect-app/Context"
|
|
11
|
+
import * as Effect from "effect-app/Effect"
|
|
12
|
+
import type * as S from "effect-app/Schema"
|
|
11
13
|
import type { StoreConfig, StoreMaker } from "../../Store.js"
|
|
12
14
|
import type { FieldValues } from "../filter/types.js"
|
|
13
15
|
import { type ExtendedRepository, extendRepo } from "./ext.js"
|
|
14
16
|
import { makeRepoInternal } from "./internal/internal.js"
|
|
17
|
+
import { RepositoryRegistry } from "./Registry.js"
|
|
15
18
|
import type { Repository } from "./service.js"
|
|
16
19
|
|
|
17
20
|
export interface RepositoryOptions<
|
|
@@ -52,11 +55,11 @@ export interface RepositoryOptions<
|
|
|
52
55
|
* Optional context to be provided to Schema decode/encode.
|
|
53
56
|
* Useful for effectful transformations like XWithItems, where items is a transformation retrieving elements from another database table or other source.
|
|
54
57
|
*/
|
|
55
|
-
schemaContext?:
|
|
58
|
+
schemaContext?: Context.Context<RCtx>
|
|
56
59
|
|
|
57
60
|
overrides?: (
|
|
58
|
-
repo: Repository<T, Encoded, Evt, ItemType, IdKey, Exclude<RSchema, RCtx>, RPublish>
|
|
59
|
-
) => Repository<T, Encoded, Evt, ItemType, IdKey, Exclude<RSchema, RCtx>, RPublish>
|
|
61
|
+
repo: Repository<T, Encoded, Evt, ItemType, IdKey, Exclude<RSchema, RCtx>, RPublish, RCtx>
|
|
62
|
+
) => Repository<T, Encoded, Evt, ItemType, IdKey, Exclude<RSchema, RCtx>, RPublish, RCtx>
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
/**
|
|
@@ -83,9 +86,9 @@ export const makeRepo: {
|
|
|
83
86
|
schema: S.Codec<T, Encoded, RSchema>,
|
|
84
87
|
options: RepositoryOptions<IdKey, Encoded, T, ItemType, Evt, RPublish, E, RInitial, RCtx, RSchema>
|
|
85
88
|
): Effect.Effect<
|
|
86
|
-
ExtendedRepository<T, Encoded, Evt, ItemType, IdKey, Exclude<RSchema, RCtx>, RPublish>,
|
|
89
|
+
ExtendedRepository<T, Encoded, Evt, ItemType, IdKey, Exclude<RSchema, RCtx>, RPublish, RCtx>,
|
|
87
90
|
E,
|
|
88
|
-
RInitial | StoreMaker
|
|
91
|
+
RInitial | StoreMaker | RepositoryRegistry
|
|
89
92
|
>
|
|
90
93
|
<
|
|
91
94
|
ItemType extends string,
|
|
@@ -102,9 +105,9 @@ export const makeRepo: {
|
|
|
102
105
|
schema: S.Codec<T, Encoded, RSchema>,
|
|
103
106
|
options: Omit<RepositoryOptions<"id", Encoded, T, ItemType, Evt, RPublish, E, RInitial, RCtx, RSchema>, "idKey">
|
|
104
107
|
): Effect.Effect<
|
|
105
|
-
ExtendedRepository<T, Encoded, Evt, ItemType, "id", Exclude<RSchema, RCtx>, RPublish>,
|
|
108
|
+
ExtendedRepository<T, Encoded, Evt, ItemType, "id", Exclude<RSchema, RCtx>, RPublish, RCtx>,
|
|
106
109
|
E,
|
|
107
|
-
RInitial | StoreMaker
|
|
110
|
+
RInitial | StoreMaker | RepositoryRegistry
|
|
108
111
|
>
|
|
109
112
|
} = <
|
|
110
113
|
ItemType extends string,
|
|
@@ -135,5 +138,7 @@ export const makeRepo: {
|
|
|
135
138
|
let r = yield* mkRepo.make<RInitial, E, RPublish, RCtx>(options as any)
|
|
136
139
|
if (options.overrides) r = options.overrides(r)
|
|
137
140
|
const repo = extendRepo(r)
|
|
141
|
+
const registry = yield* RepositoryRegistry
|
|
142
|
+
registry.register(itemType, repo)
|
|
138
143
|
return repo
|
|
139
144
|
})
|