@effect-app/infra 3.9.0 → 4.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/_check.sh +3 -0
- package/dist/CUPS.d.ts +22 -12
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/CUPS.js +28 -29
- package/dist/Emailer/Sendgrid.js +13 -12
- package/dist/Emailer/service.d.ts +3 -13
- package/dist/Emailer/service.d.ts.map +1 -1
- package/dist/Emailer/service.js +3 -3
- package/dist/MainFiberSet.d.ts +18 -41
- package/dist/MainFiberSet.d.ts.map +1 -1
- package/dist/MainFiberSet.js +10 -10
- package/dist/Model/Repository/ext.d.ts.map +1 -1
- package/dist/Model/Repository/ext.js +13 -10
- package/dist/Model/Repository/internal/internal.d.ts +5 -5
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +52 -42
- package/dist/Model/Repository/legacy.d.ts +9 -9
- package/dist/Model/Repository/legacy.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.d.ts +4 -4
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.js +1 -1
- package/dist/Model/Repository/service.d.ts +11 -11
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/Model/Repository/validation.d.ts +17 -47
- package/dist/Model/Repository/validation.d.ts.map +1 -1
- package/dist/Model/Repository/validation.js +2 -2
- package/dist/Model/query/dsl.d.ts +22 -22
- package/dist/Model/query/dsl.d.ts.map +1 -1
- package/dist/Model/query/dsl.js +1 -1
- package/dist/Model/query/new-kid-interpreter.d.ts +1 -1
- package/dist/Model/query/new-kid-interpreter.js +7 -7
- package/dist/Operations.d.ts +22 -63
- package/dist/Operations.d.ts.map +1 -1
- package/dist/Operations.js +14 -14
- package/dist/OperationsRepo.d.ts +23 -7
- package/dist/OperationsRepo.d.ts.map +1 -1
- package/dist/OperationsRepo.js +4 -5
- package/dist/QueueMaker/SQLQueue.d.ts +6 -8
- package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
- package/dist/QueueMaker/SQLQueue.js +20 -24
- package/dist/QueueMaker/errors.js +1 -1
- package/dist/QueueMaker/memQueue.d.ts +2 -5
- package/dist/QueueMaker/memQueue.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.js +22 -26
- package/dist/QueueMaker/sbqueue.d.ts +2 -5
- package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/QueueMaker/sbqueue.js +24 -28
- package/dist/RequestContext.d.ts +28 -41
- package/dist/RequestContext.d.ts.map +1 -1
- package/dist/RequestContext.js +4 -4
- package/dist/RequestFiberSet.d.ts +23 -50
- package/dist/RequestFiberSet.d.ts.map +1 -1
- package/dist/RequestFiberSet.js +14 -14
- package/dist/Store/ContextMapContainer.d.ts +4 -4
- package/dist/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/Store/ContextMapContainer.js +5 -5
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +21 -28
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +12 -16
- package/dist/Store/Memory.d.ts +2 -2
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +25 -33
- package/dist/Store/index.js +2 -2
- package/dist/Store/service.d.ts +9 -34
- package/dist/Store/service.d.ts.map +1 -1
- package/dist/Store/service.js +4 -4
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +10 -2
- package/dist/adapters/SQL/Model.d.ts +106 -162
- package/dist/adapters/SQL/Model.d.ts.map +1 -1
- package/dist/adapters/SQL/Model.js +92 -130
- package/dist/adapters/ServiceBus.d.ts +13 -44
- package/dist/adapters/ServiceBus.d.ts.map +1 -1
- package/dist/adapters/ServiceBus.js +13 -15
- package/dist/adapters/cosmos-client.d.ts +7 -3
- package/dist/adapters/cosmos-client.d.ts.map +1 -1
- package/dist/adapters/cosmos-client.js +5 -4
- package/dist/adapters/logger.d.ts +1 -1
- package/dist/adapters/logger.d.ts.map +1 -1
- package/dist/adapters/memQueue.d.ts +8 -21
- package/dist/adapters/memQueue.d.ts.map +1 -1
- package/dist/adapters/memQueue.js +4 -4
- package/dist/adapters/mongo-client.d.ts +6 -6
- package/dist/adapters/mongo-client.d.ts.map +1 -1
- package/dist/adapters/mongo-client.js +5 -4
- package/dist/adapters/redis-client.d.ts +14 -4
- package/dist/adapters/redis-client.d.ts.map +1 -1
- package/dist/adapters/redis-client.js +19 -18
- package/dist/api/ContextProvider.d.ts +10 -15
- package/dist/api/ContextProvider.d.ts.map +1 -1
- package/dist/api/ContextProvider.js +8 -8
- package/dist/api/codec.d.ts +1 -1
- package/dist/api/codec.d.ts.map +1 -1
- package/dist/api/codec.js +1 -1
- package/dist/api/internal/RequestContextMiddleware.d.ts +1 -1
- package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
- package/dist/api/internal/auth.d.ts +3 -3
- package/dist/api/internal/auth.d.ts.map +1 -1
- package/dist/api/internal/auth.js +8 -8
- package/dist/api/internal/events.d.ts +2 -2
- package/dist/api/internal/events.d.ts.map +1 -1
- package/dist/api/internal/events.js +9 -9
- package/dist/api/internal/health.d.ts +1 -1
- package/dist/api/internal/health.d.ts.map +1 -1
- package/dist/api/internal/health.js +2 -2
- package/dist/api/layerUtils.d.ts +14 -14
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +5 -5
- package/dist/api/middlewares.d.ts +0 -75
- package/dist/api/middlewares.d.ts.map +1 -1
- package/dist/api/middlewares.js +6 -51
- package/dist/api/reportError.js +4 -4
- 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 +6 -7
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +9 -13
- 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 +5 -4
- package/dist/api/routing/utils.d.ts +2 -2
- package/dist/api/routing/utils.d.ts.map +1 -1
- package/dist/api/routing/utils.js +10 -8
- package/dist/api/routing.d.ts +39 -37
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +17 -21
- package/dist/api/setupRequest.d.ts +4 -6
- package/dist/api/setupRequest.d.ts.map +1 -1
- package/dist/api/setupRequest.js +10 -9
- package/dist/arbs.d.ts +3 -3
- package/dist/arbs.d.ts.map +1 -1
- package/dist/arbs.js +2 -2
- package/dist/errorReporter.d.ts +1 -1
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +12 -12
- package/dist/fileUtil.d.ts +6 -6
- package/dist/fileUtil.d.ts.map +1 -1
- package/dist/logger/jsonLogger.d.ts.map +1 -1
- package/dist/logger/jsonLogger.js +19 -18
- package/dist/logger/logFmtLogger.d.ts.map +1 -1
- package/dist/logger/logFmtLogger.js +11 -13
- package/dist/logger/shared.d.ts +2 -2
- package/dist/logger/shared.d.ts.map +1 -1
- package/dist/logger/shared.js +7 -9
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/rateLimit.d.ts +2 -2
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +5 -5
- package/dist/test.d.ts +2 -2
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +6 -24
- package/package.json +24 -27
- package/src/CUPS.ts +15 -14
- package/src/Emailer/Sendgrid.ts +15 -13
- package/src/Emailer/service.ts +3 -3
- package/src/MainFiberSet.ts +16 -12
- package/src/Model/Repository/ext.ts +18 -16
- package/src/Model/Repository/internal/internal.ts +80 -69
- package/src/Model/Repository/legacy.ts +9 -9
- package/src/Model/Repository/makeRepo.ts +5 -5
- package/src/Model/Repository/service.ts +12 -12
- package/src/Model/Repository/validation.ts +1 -1
- package/src/Model/query/dsl.ts +13 -13
- package/src/Model/query/new-kid-interpreter.ts +8 -8
- package/src/Operations.ts +17 -14
- package/src/OperationsRepo.ts +3 -4
- package/src/QueueMaker/SQLQueue.ts +86 -89
- package/src/QueueMaker/errors.ts +1 -1
- package/src/QueueMaker/memQueue.ts +90 -91
- package/src/QueueMaker/sbqueue.ts +90 -92
- package/src/RequestContext.ts +3 -3
- package/src/RequestFiberSet.ts +17 -15
- package/src/Store/ContextMapContainer.ts +4 -4
- package/src/Store/Cosmos.ts +20 -27
- package/src/Store/Disk.ts +13 -17
- package/src/Store/Memory.ts +28 -34
- package/src/Store/index.ts +1 -1
- package/src/Store/service.ts +4 -4
- package/src/Store/utils.ts +9 -5
- package/src/adapters/SQL/Model.ts +255 -268
- package/src/adapters/ServiceBus.ts +17 -20
- package/src/adapters/cosmos-client.ts +5 -5
- package/src/adapters/memQueue.ts +3 -3
- package/src/adapters/mongo-client.ts +5 -5
- package/src/adapters/redis-client.ts +25 -19
- package/src/api/ContextProvider.ts +24 -34
- package/src/api/codec.ts +1 -1
- package/src/api/internal/auth.ts +11 -13
- package/src/api/internal/events.ts +11 -11
- package/src/api/internal/health.ts +1 -1
- package/src/api/layerUtils.ts +20 -20
- package/src/api/middlewares.ts +0 -97
- package/src/api/reportError.ts +3 -3
- package/src/api/routing/middleware/RouterMiddleware.ts +5 -6
- package/src/api/routing/middleware/middleware.ts +13 -25
- package/src/api/routing/schema/jwt.ts +9 -7
- package/src/api/routing/utils.ts +12 -10
- package/src/api/routing.ts +77 -79
- package/src/api/setupRequest.ts +9 -8
- package/src/arbs.ts +3 -3
- package/src/errorReporter.ts +12 -12
- package/src/logger/jsonLogger.ts +18 -17
- package/src/logger/logFmtLogger.ts +10 -12
- package/src/logger/shared.ts +6 -8
- package/src/rateLimit.ts +7 -7
- package/src/test.ts +7 -29
- package/test/contextProvider.test.ts +77 -70
- package/test/controller.test.ts +51 -39
- package/test/dist/contextProvider.test.d.ts.map +1 -1
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/fixtures.d.ts +33 -81
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +9 -8
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/dist/rawQuery.test.d.ts.map +1 -1
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
- package/test/fixtures.ts +9 -7
- package/test/query.test.ts +49 -41
- package/test/rawQuery.test.ts +44 -40
- package/test/requires.test.ts +40 -31
- package/test/rpc-multi-middleware.test.ts +13 -14
- package/test/validateSample.test.ts +2 -2
- package/tsconfig.json +1 -25
- package/dist/api/internal/middlewares.d.ts +0 -15
- package/dist/api/internal/middlewares.d.ts.map +0 -1
- package/dist/api/internal/middlewares.js +0 -168
- package/src/api/internal/middlewares.ts +0 -279
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import type {} from "effect/Equal"
|
|
3
3
|
import type {} from "effect/Hash"
|
|
4
|
-
import { Array, Chunk,
|
|
4
|
+
import { Array, Chunk, Effect, Equivalence, flow, type NonEmptyReadonlyArray, Option, pipe, Pipeable, PubSub, Result, S, SchemaAST, ServiceMap, Unify } from "effect-app"
|
|
5
5
|
import { toNonEmptyArray } from "effect-app/Array"
|
|
6
6
|
import { NotFoundError } from "effect-app/client/errors"
|
|
7
7
|
import { flatMapOption } from "effect-app/Effect"
|
|
8
|
-
import {
|
|
8
|
+
import { type Codec, NonNegativeInt } from "effect-app/Schema"
|
|
9
9
|
import { setupRequestContextFromCurrent } from "../../../api/setupRequest.js"
|
|
10
10
|
import { type FilterArgs, type PersistenceModelType, type StoreConfig, StoreMaker } from "../../../Store.js"
|
|
11
11
|
import { getContextMap } from "../../../Store/ContextMapContainer.js"
|
|
@@ -14,7 +14,7 @@ import * as Q from "../../query.js"
|
|
|
14
14
|
import type { Repository } from "../service.js"
|
|
15
15
|
import { ValidationError, ValidationResult } from "../validation.js"
|
|
16
16
|
|
|
17
|
-
const dedupe = Array.dedupeWith(Equivalence.
|
|
17
|
+
const dedupe = Array.dedupeWith(Equivalence.String)
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* A base implementation to create a repository.
|
|
@@ -30,7 +30,7 @@ export function makeRepoInternal<
|
|
|
30
30
|
IdKey extends keyof T & keyof Encoded
|
|
31
31
|
>(
|
|
32
32
|
name: ItemType,
|
|
33
|
-
schema: S.
|
|
33
|
+
schema: S.Codec<T, Encoded, R>,
|
|
34
34
|
mapFrom: (pm: Encoded) => Encoded,
|
|
35
35
|
mapTo: (e: Encoded, etag: string | undefined) => PersistenceModelType<Encoded>,
|
|
36
36
|
idKey: IdKey
|
|
@@ -55,14 +55,14 @@ export function makeRepoInternal<
|
|
|
55
55
|
|
|
56
56
|
function make<RInitial = never, E = never, RPublish = never, RCtx = never>(
|
|
57
57
|
args: [Evt] extends [never] ? {
|
|
58
|
-
schemaContext?:
|
|
58
|
+
schemaContext?: ServiceMap.ServiceMap<RCtx>
|
|
59
59
|
makeInitial?: Effect.Effect<readonly T[], E, RInitial> | undefined
|
|
60
60
|
config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
|
|
61
61
|
partitionValue?: (e?: Encoded) => string
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
: {
|
|
65
|
-
schemaContext?:
|
|
65
|
+
schemaContext?: ServiceMap.ServiceMap<RCtx>
|
|
66
66
|
publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect.Effect<void, never, RPublish>
|
|
67
67
|
makeInitial?: Effect.Effect<readonly T[], E, RInitial> | undefined
|
|
68
68
|
config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
|
|
@@ -72,21 +72,21 @@ export function makeRepoInternal<
|
|
|
72
72
|
) {
|
|
73
73
|
return Effect
|
|
74
74
|
.gen(function*() {
|
|
75
|
-
const rctx:
|
|
75
|
+
const rctx: ServiceMap.ServiceMap<RCtx> = args.schemaContext ?? ServiceMap.empty() as any
|
|
76
76
|
const provideRctx = Effect.provide(rctx)
|
|
77
77
|
const encodeMany = flow(
|
|
78
|
-
S.
|
|
78
|
+
S.encodeEffect(S.Array(schema)),
|
|
79
79
|
provideRctx,
|
|
80
|
-
Effect.withSpan("encodeMany", { captureStackTrace: false })
|
|
80
|
+
Effect.withSpan("encodeMany", {}, { captureStackTrace: false })
|
|
81
81
|
)
|
|
82
|
-
const decode = flow(S.
|
|
82
|
+
const decode = flow(S.decodeEffect(schema), provideRctx)
|
|
83
83
|
const decodeMany = flow(
|
|
84
|
-
S.
|
|
84
|
+
S.decodeEffect(S.Array(schema)),
|
|
85
85
|
provideRctx
|
|
86
86
|
)
|
|
87
87
|
|
|
88
88
|
const store = yield* mkStore(args.makeInitial, args.config)
|
|
89
|
-
const cms = Effect.
|
|
89
|
+
const cms = Effect.map(getContextMap.pipe(Effect.orDie), (_) => ({
|
|
90
90
|
get: (id: string) => _.get(`${name}.${id}`),
|
|
91
91
|
set: (id: string, etag: string | undefined) => _.set(`${name}.${id}`, etag)
|
|
92
92
|
}))
|
|
@@ -113,20 +113,30 @@ export function makeRepoInternal<
|
|
|
113
113
|
let ast = _.ast
|
|
114
114
|
if (ast._tag === "Declaration") ast = ast.typeParameters[0]!
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
// In v4, to get the encoded (from) side of a schema, use SchemaAST.toEncoded
|
|
117
|
+
const pickIdFromAst = (a: SchemaAST.AST) => {
|
|
118
|
+
const encoded = SchemaAST.toEncoded(a)
|
|
119
|
+
if (SchemaAST.isObjects(encoded)) {
|
|
120
|
+
const field = encoded.propertySignatures.find((_) => _.name === idKey)
|
|
121
|
+
if (field) {
|
|
122
|
+
return S.Struct({ [idKey]: S.make(field.type) }) as unknown as Codec<T, Encoded>
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return S.make(a) as unknown as Codec<T, Encoded>
|
|
126
|
+
}
|
|
117
127
|
|
|
118
128
|
return ast._tag === "Union"
|
|
119
|
-
// we need to get the TypeLiteral,
|
|
129
|
+
// we need to get the Objects (TypeLiteral), in case of class it has encoding chain...
|
|
120
130
|
? S.Union(
|
|
121
|
-
|
|
122
|
-
(S.make(_._tag === "Transformation" ? _.from : _) as unknown as Schema<T, Encoded>)
|
|
123
|
-
.pipe(S.pick(idKey as any))
|
|
124
|
-
)
|
|
131
|
+
ast.types.map((_) => pickIdFromAst(_))
|
|
125
132
|
)
|
|
126
|
-
:
|
|
133
|
+
: pickIdFromAst(ast)
|
|
127
134
|
})
|
|
128
|
-
const encodeId = flow(S.
|
|
129
|
-
const encodeIdOnly = (id: string) =>
|
|
135
|
+
const encodeId = flow(S.encodeEffect(i), provideRctx)
|
|
136
|
+
const encodeIdOnly = (id: string) =>
|
|
137
|
+
encodeId({ [idKey]: id } as any).pipe(
|
|
138
|
+
Effect.map((_: Record<string, unknown>) => _[idKey as string] as Encoded[IdKey])
|
|
139
|
+
)
|
|
130
140
|
const findEId = Effect.fnUntraced(function*(id: Encoded[IdKey]) {
|
|
131
141
|
yield* Effect.annotateCurrentSpan({ itemId: id })
|
|
132
142
|
|
|
@@ -154,22 +164,21 @@ export function makeRepoInternal<
|
|
|
154
164
|
const find = Effect.fn("find")(function*(id: T[IdKey]) {
|
|
155
165
|
yield* Effect.annotateCurrentSpan({ itemId: id })
|
|
156
166
|
|
|
157
|
-
return yield*
|
|
167
|
+
return yield* flatMapOption(findE(id), (_) => Effect.orDie(decode(_)))
|
|
158
168
|
})
|
|
159
169
|
|
|
160
170
|
const saveAllE = (a: Iterable<Encoded>) =>
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
)
|
|
171
|
+
flatMapOption(
|
|
172
|
+
Effect
|
|
173
|
+
.sync(() => toNonEmptyArray([...a])),
|
|
174
|
+
(a) =>
|
|
175
|
+
Effect.gen(function*() {
|
|
176
|
+
const { get, set } = yield* cms
|
|
177
|
+
const items = a.map((_) => mapToPersistenceModel(_, get))
|
|
178
|
+
const ret = yield* store.batchSet(items)
|
|
179
|
+
ret.forEach((_) => set(_[idKey], _._etag))
|
|
180
|
+
})
|
|
181
|
+
)
|
|
173
182
|
.pipe(Effect.asVoid)
|
|
174
183
|
|
|
175
184
|
const saveAll = (a: Iterable<T>) =>
|
|
@@ -187,8 +196,8 @@ export function makeRepoInternal<
|
|
|
187
196
|
.pipe(
|
|
188
197
|
Effect.andThen(Effect.sync(() => toNonEmptyArray(evts))),
|
|
189
198
|
// TODO: for full consistency the events should be stored within the same database transaction, and then picked up.
|
|
190
|
-
(_) =>
|
|
191
|
-
Effect.andThen(
|
|
199
|
+
(_) => flatMapOption(_, pub),
|
|
200
|
+
Effect.andThen(PubSub.publish(changeFeed, [Chunk.toArray(it), "save"] as [T[], "save" | "remove"])),
|
|
192
201
|
Effect.asVoid
|
|
193
202
|
)
|
|
194
203
|
})
|
|
@@ -199,7 +208,7 @@ export function makeRepoInternal<
|
|
|
199
208
|
const evts = [...events]
|
|
200
209
|
yield* Effect.annotateCurrentSpan({ itemIds: it.map((_) => _[idKey]), eventCount: evts.length })
|
|
201
210
|
const items = yield* encodeMany(it).pipe(Effect.orDie)
|
|
202
|
-
if (Array.
|
|
211
|
+
if (Array.isReadonlyArrayNonEmpty(items)) {
|
|
203
212
|
yield* store.batchRemove(
|
|
204
213
|
items.map((_) => (_[idKey])),
|
|
205
214
|
args.config?.partitionValue?.(items[0])
|
|
@@ -210,14 +219,14 @@ export function makeRepoInternal<
|
|
|
210
219
|
yield* Effect
|
|
211
220
|
.sync(() => toNonEmptyArray(evts))
|
|
212
221
|
// TODO: for full consistency the events should be stored within the same database transaction, and then picked up.
|
|
213
|
-
.pipe((_) =>
|
|
222
|
+
.pipe((_) => flatMapOption(_, pub))
|
|
214
223
|
|
|
215
|
-
yield*
|
|
224
|
+
yield* PubSub.publish(changeFeed, [it, "remove"] as [T[], "save" | "remove"])
|
|
216
225
|
}
|
|
217
226
|
})
|
|
218
227
|
|
|
219
228
|
const removeById = Effect.fn("removeById")(function*(...ids: readonly T[IdKey][]) {
|
|
220
|
-
if (!Array.
|
|
229
|
+
if (!Array.isReadonlyArrayNonEmpty(ids)) {
|
|
221
230
|
return
|
|
222
231
|
}
|
|
223
232
|
const { set } = yield* cms
|
|
@@ -227,25 +236,25 @@ export function makeRepoInternal<
|
|
|
227
236
|
for (const id of eids) {
|
|
228
237
|
set(id, undefined)
|
|
229
238
|
}
|
|
230
|
-
yield*
|
|
239
|
+
yield* PubSub.publish(changeFeed, [[], "remove"] as [T[], "save" | "remove"])
|
|
231
240
|
})
|
|
232
241
|
|
|
233
242
|
const parseMany = (items: readonly PM[]) =>
|
|
234
243
|
Effect
|
|
235
244
|
.flatMap(cms, (cm) =>
|
|
236
245
|
decodeMany(items.map((_) => mapReverse(_, cm.set)))
|
|
237
|
-
.pipe(Effect.orDie, Effect.withSpan("parseMany", { captureStackTrace: false })))
|
|
246
|
+
.pipe(Effect.orDie, Effect.withSpan("parseMany", {}, { captureStackTrace: false })))
|
|
238
247
|
const parseMany2 = <A, R>(
|
|
239
248
|
items: readonly PM[],
|
|
240
|
-
schema: S.
|
|
249
|
+
schema: S.Codec<A, Encoded, R>
|
|
241
250
|
) =>
|
|
242
251
|
Effect
|
|
243
252
|
.flatMap(cms, (cm) =>
|
|
244
253
|
S
|
|
245
|
-
.
|
|
254
|
+
.decodeEffect(S.Array(schema))(
|
|
246
255
|
items.map((_) => mapReverse(_, cm.set))
|
|
247
256
|
)
|
|
248
|
-
.pipe(Effect.orDie, Effect.withSpan("parseMany2", { captureStackTrace: false })))
|
|
257
|
+
.pipe(Effect.orDie, Effect.withSpan("parseMany2", {}, { captureStackTrace: false })))
|
|
249
258
|
const filter = <U extends keyof Encoded = keyof Encoded>(args: FilterArgs<Encoded, U>) =>
|
|
250
259
|
store
|
|
251
260
|
.filter(
|
|
@@ -267,7 +276,7 @@ export function makeRepoInternal<
|
|
|
267
276
|
const query: {
|
|
268
277
|
<A, R, From extends FieldValues>(
|
|
269
278
|
q: Q.QueryProjection<Encoded extends From ? From : never, A, R>
|
|
270
|
-
): Effect.Effect<readonly A[], S.
|
|
279
|
+
): Effect.Effect<readonly A[], S.SchemaError, R>
|
|
271
280
|
<A, R, EncodedRefined extends Encoded = Encoded>(
|
|
272
281
|
q: Q.QAll<NoInfer<Encoded>, NoInfer<EncodedRefined>, A, R>
|
|
273
282
|
): Effect.Effect<readonly A[], never, R>
|
|
@@ -277,14 +286,14 @@ export function makeRepoInternal<
|
|
|
277
286
|
? filter(a)
|
|
278
287
|
// TODO: mapFrom but need to support per field and dependencies
|
|
279
288
|
.pipe(
|
|
280
|
-
Effect.andThen(flow(S.
|
|
289
|
+
Effect.andThen(flow(S.decodeEffect(S.Array(a.schema ?? schema)), provideRctx))
|
|
281
290
|
)
|
|
282
291
|
: a.mode === "collect"
|
|
283
292
|
? filter(a)
|
|
284
293
|
// TODO: mapFrom but need to support per field and dependencies
|
|
285
294
|
.pipe(
|
|
286
295
|
Effect.flatMap(flow(
|
|
287
|
-
S.
|
|
296
|
+
S.decodeEffect(S.Array(a.schema)),
|
|
288
297
|
Effect.map(Array.getSomes),
|
|
289
298
|
provideRctx
|
|
290
299
|
))
|
|
@@ -301,25 +310,27 @@ export function makeRepoInternal<
|
|
|
301
310
|
)
|
|
302
311
|
return pipe(
|
|
303
312
|
a.ttype === "one"
|
|
304
|
-
? Effect.
|
|
313
|
+
? Effect.flatMap(
|
|
305
314
|
eff,
|
|
306
315
|
flow(
|
|
307
316
|
Array.head,
|
|
308
|
-
|
|
317
|
+
Option.match({
|
|
318
|
+
onNone: () => Effect.fail(new NotFoundError({ id: "query", /* TODO */ type: name })),
|
|
319
|
+
onSome: Effect.succeed
|
|
320
|
+
})
|
|
309
321
|
)
|
|
310
322
|
)
|
|
311
323
|
: a.ttype === "count"
|
|
312
324
|
? Effect
|
|
313
|
-
.
|
|
314
|
-
.pipe(Effect.catchTag("
|
|
325
|
+
.map(eff, (_) => NonNegativeInt(_.length))
|
|
326
|
+
.pipe(Effect.catchTag("SchemaError", (e) => Effect.die(e)))
|
|
315
327
|
: eff,
|
|
316
328
|
Effect.withSpan("Repository.query [effect-app/infra]", {
|
|
317
|
-
captureStackTrace: false,
|
|
318
329
|
attributes: {
|
|
319
330
|
"repository.model_name": name,
|
|
320
331
|
query: { ...a, schema: a.schema ? "__SCHEMA__" : a.schema, filter: a.filter }
|
|
321
332
|
}
|
|
322
|
-
})
|
|
333
|
+
}, { captureStackTrace: false })
|
|
323
334
|
)
|
|
324
335
|
}) as any
|
|
325
336
|
|
|
@@ -356,18 +367,18 @@ export function makeRepoInternal<
|
|
|
356
367
|
const rawData = rawResult.value as Encoded
|
|
357
368
|
const jitMResult = mapFrom(rawData) // apply jitM
|
|
358
369
|
|
|
359
|
-
const decodeResult = yield* S.
|
|
360
|
-
Effect.
|
|
370
|
+
const decodeResult = yield* S.decodeEffect(schema)(jitMResult).pipe(
|
|
371
|
+
Effect.result,
|
|
361
372
|
provideRctx
|
|
362
373
|
)
|
|
363
374
|
|
|
364
|
-
if (
|
|
375
|
+
if (Result.isFailure(decodeResult)) {
|
|
365
376
|
errors.push(
|
|
366
377
|
new ValidationError({
|
|
367
378
|
id,
|
|
368
379
|
rawData,
|
|
369
380
|
jitMResult,
|
|
370
|
-
error: decodeResult.
|
|
381
|
+
error: decodeResult.failure
|
|
371
382
|
})
|
|
372
383
|
)
|
|
373
384
|
}
|
|
@@ -381,7 +392,7 @@ export function makeRepoInternal<
|
|
|
381
392
|
})
|
|
382
393
|
})
|
|
383
394
|
|
|
384
|
-
const r
|
|
395
|
+
const r = {
|
|
385
396
|
changeFeed,
|
|
386
397
|
itemType: name,
|
|
387
398
|
idKey,
|
|
@@ -391,8 +402,8 @@ export function makeRepoInternal<
|
|
|
391
402
|
removeAndPublish,
|
|
392
403
|
removeById,
|
|
393
404
|
validateSample,
|
|
394
|
-
queryRaw(schema, q) {
|
|
395
|
-
const dec = S.
|
|
405
|
+
queryRaw<A, Out, QR>(schema: S.Codec<A, Out, QR>, q: Q.RawQuery<Encoded, Out>) {
|
|
406
|
+
const dec = S.decodeEffect(S.Array(schema))
|
|
396
407
|
return store.queryRaw(q).pipe(Effect.flatMap(dec))
|
|
397
408
|
},
|
|
398
409
|
query(q: any) {
|
|
@@ -402,10 +413,10 @@ export function makeRepoInternal<
|
|
|
402
413
|
/**
|
|
403
414
|
* @internal
|
|
404
415
|
*/
|
|
405
|
-
mapped: <A, R>(schema: S.
|
|
406
|
-
const dec = S.
|
|
407
|
-
const encMany = S.
|
|
408
|
-
const decMany = S.
|
|
416
|
+
mapped: <A, R>(schema: S.Codec<A, any, R>) => {
|
|
417
|
+
const dec = S.decodeEffect(schema)
|
|
418
|
+
const encMany = S.encodeEffect(S.Array(schema))
|
|
419
|
+
const decMany = S.decodeEffect(S.Array(schema))
|
|
409
420
|
return {
|
|
410
421
|
all: allE.pipe(
|
|
411
422
|
Effect.flatMap(decMany),
|
|
@@ -430,12 +441,12 @@ export function makeRepoInternal<
|
|
|
430
441
|
// },
|
|
431
442
|
save: (...xes: any[]) =>
|
|
432
443
|
Effect.flatMap(encMany(xes), (_) => saveAllE(_)).pipe(
|
|
433
|
-
Effect.withSpan("mapped.save", { captureStackTrace: false })
|
|
444
|
+
Effect.withSpan("mapped.save", {}, { captureStackTrace: false })
|
|
434
445
|
)
|
|
435
446
|
}
|
|
436
447
|
}
|
|
437
448
|
}
|
|
438
|
-
return r
|
|
449
|
+
return r as Repository<T, Encoded, Evt, ItemType, IdKey, Exclude<R, RCtx>, RPublish>
|
|
439
450
|
})
|
|
440
451
|
.pipe(Effect
|
|
441
452
|
// .withSpan("Repository.make [effect-app/infra]", { attributes: { "repository.model_name": name } })
|
|
@@ -465,7 +476,7 @@ export function makeStore<Encoded extends FieldValues>() {
|
|
|
465
476
|
IdKey extends keyof Encoded
|
|
466
477
|
>(
|
|
467
478
|
name: ItemType,
|
|
468
|
-
schema: S.
|
|
479
|
+
schema: S.Codec<T, E, R>,
|
|
469
480
|
mapTo: (e: E, etag: string | undefined) => Encoded,
|
|
470
481
|
idKey: IdKey
|
|
471
482
|
) => {
|
|
@@ -478,7 +489,7 @@ export function makeStore<Encoded extends FieldValues>() {
|
|
|
478
489
|
function encodeToEncoded() {
|
|
479
490
|
const getEtag = () => undefined
|
|
480
491
|
return (t: T) =>
|
|
481
|
-
S.
|
|
492
|
+
S.encodeEffect(schema)(t).pipe(
|
|
482
493
|
Effect.orDie,
|
|
483
494
|
Effect.map((_) => mapToPersistenceModel(_, getEtag))
|
|
484
495
|
)
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
3
|
-
import type { Effect, Option,
|
|
3
|
+
import type { Effect, Option, S } from "effect-app"
|
|
4
4
|
import type { OptimisticConcurrencyException } from "effect-app/client/errors"
|
|
5
5
|
|
|
6
6
|
export interface Mapped1<A, IdKey extends keyof A, R> {
|
|
7
|
-
all: Effect.Effect<A[],
|
|
8
|
-
save: (...xes: readonly A[]) => Effect.Effect<void, OptimisticConcurrencyException |
|
|
9
|
-
find: (id: A[IdKey]) => Effect.Effect<Option.Option<A>,
|
|
7
|
+
all: Effect.Effect<A[], S.SchemaError, R>
|
|
8
|
+
save: (...xes: readonly A[]) => Effect.Effect<void, OptimisticConcurrencyException | S.SchemaError, R>
|
|
9
|
+
find: (id: A[IdKey]) => Effect.Effect<Option.Option<A>, S.SchemaError, R>
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
// TODO: auto use project, and select fields from the From side of schema only
|
|
13
13
|
export interface Mapped2<A, R> {
|
|
14
|
-
all: Effect.Effect<A[],
|
|
14
|
+
all: Effect.Effect<A[], S.SchemaError, R>
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export interface Mapped<Encoded> {
|
|
18
|
-
<A, R, IdKey extends keyof A>(schema: S.
|
|
18
|
+
<A, R, IdKey extends keyof A>(schema: S.Codec<A, Encoded, R>): Mapped1<A, IdKey, R>
|
|
19
19
|
// TODO: constrain on Encoded2 having to contain only fields that fit Encoded
|
|
20
|
-
<A, Encoded2, R>(schema: S.
|
|
20
|
+
<A, Encoded2, R>(schema: S.Codec<A, Encoded2, R>): Mapped2<A, R>
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export interface MM<Repo, Encoded> {
|
|
24
|
-
<A, R, IdKey extends keyof A>(schema: S.
|
|
24
|
+
<A, R, IdKey extends keyof A>(schema: S.Codec<A, Encoded, R>): Effect.Effect<Mapped1<A, IdKey, R>, never, Repo>
|
|
25
25
|
// TODO: constrain on Encoded2 having to contain only fields that fit Encoded
|
|
26
|
-
<A, Encoded2, R>(schema: S.
|
|
26
|
+
<A, Encoded2, R>(schema: S.Codec<A, Encoded2, R>): Effect.Effect<Mapped2<A, R>, never, Repo>
|
|
27
27
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// import type { ParserEnv } from "effect-app/Schema/custom/Parser"
|
|
8
8
|
import type {} from "effect/Equal"
|
|
9
9
|
import type {} from "effect/Hash"
|
|
10
|
-
import {
|
|
10
|
+
import { Effect, type NonEmptyReadonlyArray, type S, type ServiceMap } from "effect-app"
|
|
11
11
|
import type { StoreConfig, StoreMaker } from "../../Store.js"
|
|
12
12
|
import type { FieldValues } from "../filter/types.js"
|
|
13
13
|
import { type ExtendedRepository, extendRepo } from "./ext.js"
|
|
@@ -52,7 +52,7 @@ export interface RepositoryOptions<
|
|
|
52
52
|
* Optional context to be provided to Schema decode/encode.
|
|
53
53
|
* Useful for effectful transformations like XWithItems, where items is a transformation retrieving elements from another database table or other source.
|
|
54
54
|
*/
|
|
55
|
-
schemaContext?:
|
|
55
|
+
schemaContext?: ServiceMap.ServiceMap<RCtx>
|
|
56
56
|
|
|
57
57
|
overrides?: (
|
|
58
58
|
repo: Repository<T, Encoded, Evt, ItemType, IdKey, Exclude<RSchema, RCtx>, RPublish>
|
|
@@ -80,7 +80,7 @@ export const makeRepo: {
|
|
|
80
80
|
RCtx = never
|
|
81
81
|
>(
|
|
82
82
|
itemType: ItemType,
|
|
83
|
-
schema: S.
|
|
83
|
+
schema: S.Codec<T, Encoded, RSchema>,
|
|
84
84
|
options: RepositoryOptions<IdKey, Encoded, T, ItemType, Evt, RPublish, E, RInitial, RCtx, RSchema>
|
|
85
85
|
): Effect.Effect<
|
|
86
86
|
ExtendedRepository<T, Encoded, Evt, ItemType, IdKey, Exclude<RSchema, RCtx>, RPublish>,
|
|
@@ -99,7 +99,7 @@ export const makeRepo: {
|
|
|
99
99
|
RCtx = never
|
|
100
100
|
>(
|
|
101
101
|
itemType: ItemType,
|
|
102
|
-
schema: S.
|
|
102
|
+
schema: S.Codec<T, Encoded, RSchema>,
|
|
103
103
|
options: Omit<RepositoryOptions<"id", Encoded, T, ItemType, Evt, RPublish, E, RInitial, RCtx, RSchema>, "idKey">
|
|
104
104
|
): Effect.Effect<
|
|
105
105
|
ExtendedRepository<T, Encoded, Evt, ItemType, "id", Exclude<RSchema, RCtx>, RPublish>,
|
|
@@ -119,7 +119,7 @@ export const makeRepo: {
|
|
|
119
119
|
RCtx = never
|
|
120
120
|
>(
|
|
121
121
|
itemType: ItemType,
|
|
122
|
-
schema: S.
|
|
122
|
+
schema: S.Codec<T, Encoded, RSchema>,
|
|
123
123
|
options: Omit<RepositoryOptions<IdKey, Encoded, T, ItemType, Evt, RPublish, E, RInitial, RCtx, RSchema>, "idKey"> & {
|
|
124
124
|
idKey?: IdKey
|
|
125
125
|
}
|
|
@@ -33,9 +33,9 @@ export interface Repository<
|
|
|
33
33
|
readonly removeById: (...id: readonly T[IdKey][]) => Effect.Effect<void, never, RSchema>
|
|
34
34
|
|
|
35
35
|
readonly queryRaw: <T, Out, R>(
|
|
36
|
-
schema: S.
|
|
36
|
+
schema: S.Codec<T, Out, R>,
|
|
37
37
|
raw: RawQuery<Encoded, Out>
|
|
38
|
-
) => Effect.Effect<readonly T[], S.
|
|
38
|
+
) => Effect.Effect<readonly T[], S.SchemaError, R>
|
|
39
39
|
|
|
40
40
|
readonly query: {
|
|
41
41
|
// ending with projection
|
|
@@ -52,7 +52,7 @@ export interface Repository<
|
|
|
52
52
|
): Effect.Effect<
|
|
53
53
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
54
54
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
55
|
-
| (TType extends "count" ? never : S.
|
|
55
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
56
56
|
R | RSchema
|
|
57
57
|
>
|
|
58
58
|
<
|
|
@@ -72,7 +72,7 @@ export interface Repository<
|
|
|
72
72
|
): Effect.Effect<
|
|
73
73
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
74
74
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
75
|
-
| (TType extends "count" ? never : S.
|
|
75
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
76
76
|
R | RSchema
|
|
77
77
|
>
|
|
78
78
|
<
|
|
@@ -94,7 +94,7 @@ export interface Repository<
|
|
|
94
94
|
): Effect.Effect<
|
|
95
95
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
96
96
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
97
|
-
| (TType extends "count" ? never : S.
|
|
97
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
98
98
|
R | RSchema
|
|
99
99
|
>
|
|
100
100
|
<
|
|
@@ -118,7 +118,7 @@ export interface Repository<
|
|
|
118
118
|
): Effect.Effect<
|
|
119
119
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
120
120
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
121
|
-
| (TType extends "count" ? never : S.
|
|
121
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
122
122
|
R | RSchema
|
|
123
123
|
>
|
|
124
124
|
<
|
|
@@ -144,7 +144,7 @@ export interface Repository<
|
|
|
144
144
|
): Effect.Effect<
|
|
145
145
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
146
146
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
147
|
-
| (TType extends "count" ? never : S.
|
|
147
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
148
148
|
R | RSchema
|
|
149
149
|
>
|
|
150
150
|
<
|
|
@@ -170,7 +170,7 @@ export interface Repository<
|
|
|
170
170
|
): Effect.Effect<
|
|
171
171
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
172
172
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
173
|
-
| (TType extends "count" ? never : S.
|
|
173
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
174
174
|
R | RSchema
|
|
175
175
|
>
|
|
176
176
|
<
|
|
@@ -198,7 +198,7 @@ export interface Repository<
|
|
|
198
198
|
): Effect.Effect<
|
|
199
199
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
200
200
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
201
|
-
| (TType extends "count" ? never : S.
|
|
201
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
202
202
|
R | RSchema
|
|
203
203
|
>
|
|
204
204
|
<
|
|
@@ -228,7 +228,7 @@ export interface Repository<
|
|
|
228
228
|
): Effect.Effect<
|
|
229
229
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
230
230
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
231
|
-
| (TType extends "count" ? never : S.
|
|
231
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
232
232
|
R | RSchema
|
|
233
233
|
>
|
|
234
234
|
<
|
|
@@ -260,7 +260,7 @@ export interface Repository<
|
|
|
260
260
|
): Effect.Effect<
|
|
261
261
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
262
262
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
263
|
-
| (TType extends "count" ? never : S.
|
|
263
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
264
264
|
R | RSchema
|
|
265
265
|
>
|
|
266
266
|
<
|
|
@@ -294,7 +294,7 @@ export interface Repository<
|
|
|
294
294
|
): Effect.Effect<
|
|
295
295
|
TType extends "many" ? readonly A[] : TType extends "count" ? NonNegativeInt : A,
|
|
296
296
|
| (TType extends "many" ? never : NotFoundError<ItemType>)
|
|
297
|
-
| (TType extends "count" ? never : S.
|
|
297
|
+
| (TType extends "count" ? never : S.SchemaError),
|
|
298
298
|
R | RSchema
|
|
299
299
|
>
|
|
300
300
|
|
|
@@ -12,7 +12,7 @@ export class ValidationError extends S.Class<ValidationError>("@effect-app/infra
|
|
|
12
12
|
rawData: S.Unknown,
|
|
13
13
|
/** the data after applying jitM transformation */
|
|
14
14
|
jitMResult: S.Unknown,
|
|
15
|
-
/** the
|
|
15
|
+
/** the S.SchemaError from schema decode */
|
|
16
16
|
error: S.Unknown
|
|
17
17
|
}) {}
|
|
18
18
|
|