@effect-app/infra 0.170.5 → 0.171.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 +23 -0
- package/_cjs/api/routing/base.cjs.map +1 -1
- package/_cjs/api/routing/makeRequestHandler.cjs.map +1 -1
- package/_cjs/services/QueueMaker/errors.cjs.map +1 -1
- package/_cjs/services/Repository/dsl.cjs +70 -0
- package/_cjs/services/Repository/dsl.cjs.map +1 -0
- package/_cjs/services/Repository/ext.cjs +202 -0
- package/_cjs/services/Repository/ext.cjs.map +1 -0
- package/_cjs/services/Repository/service.cjs +6 -0
- package/_cjs/services/Repository/service.cjs.map +1 -0
- package/_cjs/services/Repository.cjs +32 -252
- package/_cjs/services/Repository.cjs.map +1 -1
- package/_cjs/services/RepositoryBase.cjs +173 -48
- package/_cjs/services/RepositoryBase.cjs.map +1 -1
- package/_cjs/services/RequestContextContainer.cjs +6 -7
- package/_cjs/services/RequestContextContainer.cjs.map +1 -1
- package/_cjs/services/Store/ContextMapContainer.cjs +6 -7
- package/_cjs/services/Store/ContextMapContainer.cjs.map +1 -1
- package/_cjs/services/Store/Memory.cjs.map +1 -1
- package/_cjs/services/Store/utils.cjs.map +1 -1
- package/_src/api/routing/base.ts +5 -3
- package/_src/api/routing/makeRequestHandler.ts +20 -12
- package/_src/rateLimit.ts +2 -2
- package/_src/services/Emailer/Sendgrid.ts +2 -2
- package/_src/services/QueueMaker/errors.ts +6 -3
- package/_src/services/QueueMaker/memQueue.ts +2 -2
- package/_src/services/QueueMaker/sbqueue.ts +2 -2
- package/_src/services/Repository/dsl.ts +137 -0
- package/_src/services/Repository/ext.ts +669 -0
- package/_src/services/Repository/service.ts +12 -0
- package/_src/services/Repository.ts +3 -791
- package/_src/services/RepositoryBase.ts +640 -13
- package/_src/services/RequestContextContainer.ts +14 -16
- package/_src/services/Store/ContextMapContainer.ts +6 -9
- package/_src/services/Store/Cosmos.ts +2 -2
- package/_src/services/Store/Disk.ts +2 -2
- package/_src/services/Store/Memory.ts +2 -1
- package/_src/services/Store/Redis.ts +2 -2
- package/_src/services/Store/utils.ts +4 -5
- package/_src/services/simpledb/cosmosdb.ts +1 -1
- package/_src/services/simpledb/diskdb.ts +1 -1
- package/_src/services/simpledb/memdb.ts +1 -1
- package/_src/services/simpledb/mongodb.ts +1 -1
- package/_src/services/simpledb/redisdb.ts +2 -2
- package/dist/api/routing/base.d.ts +1 -2
- package/dist/api/routing/base.d.ts.map +1 -1
- package/dist/api/routing/base.js +1 -1
- package/dist/api/routing/makeRequestHandler.d.ts.map +1 -1
- package/dist/api/routing/makeRequestHandler.js +15 -11
- package/dist/rateLimit.js +1 -1
- package/dist/services/Emailer/Sendgrid.js +1 -1
- package/dist/services/QueueMaker/errors.d.ts.map +1 -1
- package/dist/services/QueueMaker/errors.js +5 -2
- package/dist/services/QueueMaker/memQueue.js +1 -1
- package/dist/services/QueueMaker/sbqueue.js +1 -1
- package/dist/services/QueueMaker/service.d.ts +2 -2
- package/dist/services/Repository/dsl.d.ts +51 -0
- package/dist/services/Repository/dsl.d.ts.map +1 -0
- package/dist/services/Repository/dsl.js +55 -0
- package/dist/services/Repository/ext.d.ts +310 -0
- package/dist/services/Repository/ext.d.ts.map +1 -0
- package/dist/services/Repository/ext.js +166 -0
- package/dist/services/Repository/service.d.ts +10 -0
- package/dist/services/Repository/service.d.ts.map +1 -0
- package/dist/services/Repository/service.js +2 -0
- package/dist/services/Repository.d.ts +3 -363
- package/dist/services/Repository.d.ts.map +1 -1
- package/dist/services/Repository.js +4 -217
- package/dist/services/RepositoryBase.d.ts +241 -6
- package/dist/services/RepositoryBase.d.ts.map +1 -1
- package/dist/services/RepositoryBase.js +176 -52
- package/dist/services/RequestContextContainer.d.ts +3 -5
- package/dist/services/RequestContextContainer.d.ts.map +1 -1
- package/dist/services/RequestContextContainer.js +17 -16
- package/dist/services/Store/ContextMapContainer.d.ts +2 -5
- package/dist/services/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/services/Store/ContextMapContainer.js +7 -8
- package/dist/services/Store/Cosmos.js +1 -1
- package/dist/services/Store/Disk.js +1 -1
- package/dist/services/Store/Memory.d.ts.map +1 -1
- package/dist/services/Store/Memory.js +1 -1
- package/dist/services/Store/Redis.js +1 -1
- package/dist/services/Store/utils.d.ts.map +1 -1
- package/dist/services/Store/utils.js +1 -1
- package/dist/services/simpledb/cosmosdb.js +1 -1
- package/dist/services/simpledb/diskdb.js +1 -1
- package/dist/services/simpledb/memdb.js +1 -1
- package/dist/services/simpledb/mongodb.js +1 -1
- package/dist/services/simpledb/redisdb.js +1 -1
- package/package.json +37 -7
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
// Update = Must return updated items
|
|
3
|
+
// Modify = Must `set` updated items, and can return anything.
|
|
4
|
+
import type { FixEnv } from "@effect-app/prelude/Pure"
|
|
5
|
+
import type { InvalidStateError, OptimisticConcurrencyException } from "../../errors.js"
|
|
6
|
+
import { NotFoundError } from "../../errors.js"
|
|
7
|
+
import type { Filter, PersistenceModelType } from "../../services/Store.js"
|
|
8
|
+
import type { RepositoryBaseC } from "../RepositoryBase.js"
|
|
9
|
+
import type { QueryBuilder } from "../Store/filterApi/query.js"
|
|
10
|
+
import { AnyPureDSL } from "./dsl.js"
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @tsplus fluent Repository get
|
|
14
|
+
*/
|
|
15
|
+
export function get<
|
|
16
|
+
T extends { id: unknown },
|
|
17
|
+
PM extends PersistenceModelType<string>,
|
|
18
|
+
Evt,
|
|
19
|
+
ItemType extends string
|
|
20
|
+
>(
|
|
21
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
22
|
+
id: T["id"]
|
|
23
|
+
) {
|
|
24
|
+
return self
|
|
25
|
+
.find(id)
|
|
26
|
+
.flatMap((_) => _.encaseInEffect(() => new NotFoundError<ItemType>({ type: self.itemType, id })))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @tsplus getter Repository log
|
|
31
|
+
*/
|
|
32
|
+
export function log<
|
|
33
|
+
T extends { id: unknown },
|
|
34
|
+
PM extends PersistenceModelType<string>,
|
|
35
|
+
Evt,
|
|
36
|
+
ItemType extends string
|
|
37
|
+
>(_: RepositoryBaseC<T, PM, Evt, ItemType>) {
|
|
38
|
+
return (evt: Evt) => AnyPureDSL.log(evt)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* TODO: project inside the db.
|
|
43
|
+
* @tsplus fluent Repository projectEffect
|
|
44
|
+
*/
|
|
45
|
+
export function projectEffect<
|
|
46
|
+
T extends { id: unknown },
|
|
47
|
+
PM extends PersistenceModelType<string>,
|
|
48
|
+
Evt,
|
|
49
|
+
ItemType extends string,
|
|
50
|
+
R,
|
|
51
|
+
E,
|
|
52
|
+
S = PM
|
|
53
|
+
>(
|
|
54
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
55
|
+
map: Effect<
|
|
56
|
+
{
|
|
57
|
+
filter?: Filter<PM> | undefined
|
|
58
|
+
collect?: ((t: PM) => Option<S>) | undefined
|
|
59
|
+
limit?: number | undefined
|
|
60
|
+
skip?: number | undefined
|
|
61
|
+
},
|
|
62
|
+
E,
|
|
63
|
+
R
|
|
64
|
+
>
|
|
65
|
+
): Effect<S[], E, R>
|
|
66
|
+
export function projectEffect<
|
|
67
|
+
T extends { id: unknown },
|
|
68
|
+
PM extends PersistenceModelType<string>,
|
|
69
|
+
Evt,
|
|
70
|
+
ItemType extends string,
|
|
71
|
+
R,
|
|
72
|
+
E,
|
|
73
|
+
U extends keyof PM,
|
|
74
|
+
S = PM
|
|
75
|
+
>(
|
|
76
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
77
|
+
map: Effect<
|
|
78
|
+
{
|
|
79
|
+
filter?: QueryBuilder<PM> | undefined
|
|
80
|
+
collect?: ((t: PM) => Option<S>) | undefined
|
|
81
|
+
limit?: number | undefined
|
|
82
|
+
skip?: number | undefined
|
|
83
|
+
},
|
|
84
|
+
E,
|
|
85
|
+
R
|
|
86
|
+
>
|
|
87
|
+
): Effect<Pick<PM, U>[], E, R>
|
|
88
|
+
export function projectEffect<
|
|
89
|
+
T extends { id: unknown },
|
|
90
|
+
PM extends PersistenceModelType<string>,
|
|
91
|
+
Evt,
|
|
92
|
+
ItemType extends string,
|
|
93
|
+
R,
|
|
94
|
+
E,
|
|
95
|
+
U extends keyof PM,
|
|
96
|
+
S = Pick<PM, U>
|
|
97
|
+
>(
|
|
98
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
99
|
+
map: Effect<
|
|
100
|
+
{
|
|
101
|
+
filter?: Filter<PM> | undefined
|
|
102
|
+
select?: NonEmptyReadonlyArray<U> | undefined
|
|
103
|
+
collect?: ((t: PM) => Option<S>) | undefined
|
|
104
|
+
limit?: number | undefined
|
|
105
|
+
skip?: number | undefined
|
|
106
|
+
},
|
|
107
|
+
E,
|
|
108
|
+
R
|
|
109
|
+
>
|
|
110
|
+
): Effect<S[], E, R> {
|
|
111
|
+
// TODO: a projection that gets sent to the db instead.
|
|
112
|
+
return map.flatMap((f) =>
|
|
113
|
+
self
|
|
114
|
+
.utils
|
|
115
|
+
.filter(f)
|
|
116
|
+
.map((_) => f.collect ? _.filterMap(f.collect) : _ as unknown as S[])
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* TODO: project inside the db.
|
|
122
|
+
* @tsplus fluent Repository project
|
|
123
|
+
*/
|
|
124
|
+
export function project<
|
|
125
|
+
T extends { id: unknown },
|
|
126
|
+
PM extends PersistenceModelType<string>,
|
|
127
|
+
Evt,
|
|
128
|
+
ItemType extends string,
|
|
129
|
+
S = PM
|
|
130
|
+
>(
|
|
131
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
132
|
+
map: {
|
|
133
|
+
filter?: Filter<PM>
|
|
134
|
+
collect?: (t: PM) => Option<S>
|
|
135
|
+
limit?: number
|
|
136
|
+
skip?: number
|
|
137
|
+
}
|
|
138
|
+
): Effect<S[]>
|
|
139
|
+
export function project<
|
|
140
|
+
T extends { id: unknown },
|
|
141
|
+
PM extends PersistenceModelType<string>,
|
|
142
|
+
Evt,
|
|
143
|
+
ItemType extends string,
|
|
144
|
+
U extends keyof PM
|
|
145
|
+
>(
|
|
146
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
147
|
+
map: {
|
|
148
|
+
filter?: QueryBuilder<PM>
|
|
149
|
+
select: NonEmptyReadonlyArray<U>
|
|
150
|
+
limit?: number
|
|
151
|
+
skip?: number
|
|
152
|
+
}
|
|
153
|
+
): Effect<Pick<PM, U>[]>
|
|
154
|
+
export function project<
|
|
155
|
+
T extends { id: unknown },
|
|
156
|
+
PM extends PersistenceModelType<string>,
|
|
157
|
+
Evt,
|
|
158
|
+
ItemType extends string,
|
|
159
|
+
U extends keyof PM,
|
|
160
|
+
S = Pick<PM, U>
|
|
161
|
+
>(
|
|
162
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
163
|
+
map: {
|
|
164
|
+
filter?: Filter<PM>
|
|
165
|
+
select?: NonEmptyReadonlyArray<U>
|
|
166
|
+
collect?: (t: Pick<PM, U>) => Option<S>
|
|
167
|
+
limit?: number
|
|
168
|
+
skip?: number
|
|
169
|
+
}
|
|
170
|
+
): Effect<S[]> {
|
|
171
|
+
return self.projectEffect(Effect.sync(() => map))
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* TODO: count inside the db.
|
|
176
|
+
* @tsplus fluent Repository project
|
|
177
|
+
*/
|
|
178
|
+
export function count<
|
|
179
|
+
T extends { id: unknown },
|
|
180
|
+
PM extends PersistenceModelType<string>,
|
|
181
|
+
Evt,
|
|
182
|
+
ItemType extends string
|
|
183
|
+
>(
|
|
184
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
185
|
+
filter?: Filter<PM>
|
|
186
|
+
) {
|
|
187
|
+
return self
|
|
188
|
+
.projectEffect(Effect.sync(() => ({ filter })))
|
|
189
|
+
.map((_) => NonNegativeInt(_.length))
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* @tsplus fluent Repository queryEffect
|
|
194
|
+
*/
|
|
195
|
+
export function queryEffect<
|
|
196
|
+
T extends { id: unknown },
|
|
197
|
+
PM extends PersistenceModelType<string>,
|
|
198
|
+
Evt,
|
|
199
|
+
ItemType extends string,
|
|
200
|
+
R,
|
|
201
|
+
E,
|
|
202
|
+
S = T
|
|
203
|
+
>(
|
|
204
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
205
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
206
|
+
map: Effect<{ filter?: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>
|
|
207
|
+
) {
|
|
208
|
+
return map.flatMap((f) =>
|
|
209
|
+
(f.filter ? self.utils.filter(f) : self.utils.all)
|
|
210
|
+
.flatMap((_) => self.utils.parseMany(_))
|
|
211
|
+
.map((_) => f.collect ? _.filterMap(f.collect) : _ as any as S[])
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @tsplus fluent Repository queryOneEffect
|
|
217
|
+
*/
|
|
218
|
+
export function queryOneEffect<
|
|
219
|
+
T extends { id: unknown },
|
|
220
|
+
PM extends PersistenceModelType<string>,
|
|
221
|
+
Evt,
|
|
222
|
+
ItemType extends string,
|
|
223
|
+
R,
|
|
224
|
+
E
|
|
225
|
+
>(
|
|
226
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
227
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
228
|
+
map: Effect<{ filter?: Filter<PM> }, E, R>
|
|
229
|
+
): Effect<T, E | NotFoundError<ItemType>, R>
|
|
230
|
+
export function queryOneEffect<
|
|
231
|
+
T extends { id: unknown },
|
|
232
|
+
PM extends PersistenceModelType<string>,
|
|
233
|
+
Evt,
|
|
234
|
+
ItemType extends string,
|
|
235
|
+
R,
|
|
236
|
+
E,
|
|
237
|
+
S = T
|
|
238
|
+
>(
|
|
239
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
240
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
241
|
+
map: Effect<{ filter?: Filter<PM>; collect: (t: T) => Option<S> }, E, R>
|
|
242
|
+
): Effect<S, E | NotFoundError<ItemType>, R>
|
|
243
|
+
export function queryOneEffect<
|
|
244
|
+
T extends { id: unknown },
|
|
245
|
+
PM extends PersistenceModelType<string>,
|
|
246
|
+
Evt,
|
|
247
|
+
ItemType extends string,
|
|
248
|
+
R,
|
|
249
|
+
E,
|
|
250
|
+
S = T
|
|
251
|
+
>(
|
|
252
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
253
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
254
|
+
map: Effect<{ filter?: Filter<PM>; collect?: (t: T) => Option<S> }, E, R>
|
|
255
|
+
): Effect<S, E | NotFoundError<ItemType>, R> {
|
|
256
|
+
return map.flatMap((f) =>
|
|
257
|
+
(f.filter ? self.utils.filter({ filter: f.filter, limit: 1 }) : self.utils.all)
|
|
258
|
+
.flatMap((_) => self.utils.parseMany(_))
|
|
259
|
+
.flatMap((_) =>
|
|
260
|
+
(f.collect ? _.filterMap(f.collect) : _ as any as S[])
|
|
261
|
+
.toNonEmpty
|
|
262
|
+
.encaseInEffect(() => new NotFoundError<ItemType>({ type: self.itemType, id: f.filter }))
|
|
263
|
+
.map((_) => _[0])
|
|
264
|
+
)
|
|
265
|
+
)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* @tsplus fluent Repository query
|
|
270
|
+
*/
|
|
271
|
+
export function query<
|
|
272
|
+
T extends { id: unknown },
|
|
273
|
+
PM extends PersistenceModelType<string>,
|
|
274
|
+
Evt,
|
|
275
|
+
ItemType extends string,
|
|
276
|
+
S = T
|
|
277
|
+
>(
|
|
278
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
279
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
280
|
+
map: { filter?: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }
|
|
281
|
+
) {
|
|
282
|
+
return self.queryEffect(Effect.sync(() => map))
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @tsplus fluent Repository queryOne
|
|
287
|
+
*/
|
|
288
|
+
export function queryOne<
|
|
289
|
+
T extends { id: unknown },
|
|
290
|
+
PM extends PersistenceModelType<string>,
|
|
291
|
+
Evt,
|
|
292
|
+
ItemType extends string,
|
|
293
|
+
S = T
|
|
294
|
+
>(
|
|
295
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
296
|
+
map: { filter?: Filter<PM>; collect: (t: T) => Option<S> }
|
|
297
|
+
): Effect<S, NotFoundError<ItemType>>
|
|
298
|
+
export function queryOne<
|
|
299
|
+
T extends { id: unknown },
|
|
300
|
+
PM extends PersistenceModelType<string>,
|
|
301
|
+
Evt,
|
|
302
|
+
ItemType extends string
|
|
303
|
+
>(
|
|
304
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
305
|
+
map: { filter?: Filter<PM> }
|
|
306
|
+
): Effect<T, NotFoundError<ItemType>>
|
|
307
|
+
export function queryOne<
|
|
308
|
+
T extends { id: unknown },
|
|
309
|
+
PM extends PersistenceModelType<string>,
|
|
310
|
+
Evt,
|
|
311
|
+
ItemType extends string,
|
|
312
|
+
S = T
|
|
313
|
+
>(
|
|
314
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
315
|
+
map: { filter?: Filter<PM>; collect?: (t: T) => Option<S> }
|
|
316
|
+
) {
|
|
317
|
+
return self.queryOneEffect(Effect.sync(() => map))
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* @tsplus fluent Repository queryAndSaveOnePureEffect
|
|
322
|
+
*/
|
|
323
|
+
export function queryAndSaveOnePureEffect<
|
|
324
|
+
T extends { id: unknown },
|
|
325
|
+
PM extends PersistenceModelType<string>,
|
|
326
|
+
Evt,
|
|
327
|
+
ItemType extends string,
|
|
328
|
+
R,
|
|
329
|
+
E,
|
|
330
|
+
S extends T = T
|
|
331
|
+
>(
|
|
332
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
333
|
+
map: Effect<{ filter: Filter<PM>; collect: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>
|
|
334
|
+
): <R2, A, E2, S2 extends T>(
|
|
335
|
+
pure: Effect<A, E2, FixEnv<R2, Evt, S, S2>>
|
|
336
|
+
) => Effect<
|
|
337
|
+
A,
|
|
338
|
+
InvalidStateError | OptimisticConcurrencyException | E | E2 | NotFoundError<ItemType>,
|
|
339
|
+
| R
|
|
340
|
+
| Exclude<R2, {
|
|
341
|
+
env: PureEnv<Evt, S, S2>
|
|
342
|
+
}>
|
|
343
|
+
>
|
|
344
|
+
export function queryAndSaveOnePureEffect<
|
|
345
|
+
T extends { id: unknown },
|
|
346
|
+
PM extends PersistenceModelType<string>,
|
|
347
|
+
Evt,
|
|
348
|
+
ItemType extends string,
|
|
349
|
+
R,
|
|
350
|
+
E
|
|
351
|
+
>(
|
|
352
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
353
|
+
map: Effect<{ filter: Filter<PM> }, E, R>
|
|
354
|
+
): <R2, A, E2, T2 extends T>(
|
|
355
|
+
pure: Effect<A, E2, FixEnv<R2, Evt, T, T2>>
|
|
356
|
+
) => Effect<
|
|
357
|
+
A,
|
|
358
|
+
InvalidStateError | OptimisticConcurrencyException | E | E2 | NotFoundError<ItemType>,
|
|
359
|
+
| R
|
|
360
|
+
| Exclude<R2, {
|
|
361
|
+
env: PureEnv<Evt, T, T2>
|
|
362
|
+
}>
|
|
363
|
+
>
|
|
364
|
+
export function queryAndSaveOnePureEffect(
|
|
365
|
+
self: any,
|
|
366
|
+
map: any
|
|
367
|
+
) {
|
|
368
|
+
return (pure: any) =>
|
|
369
|
+
queryOneEffect(self, map)
|
|
370
|
+
.flatMap((_) => saveWithPure_(self, _, pure))
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* @tsplus fluent Repository queryAndSaveOnePure
|
|
375
|
+
*/
|
|
376
|
+
export function queryAndSaveOnePure<
|
|
377
|
+
T extends { id: unknown },
|
|
378
|
+
PM extends PersistenceModelType<string>,
|
|
379
|
+
Evt,
|
|
380
|
+
ItemType extends string,
|
|
381
|
+
S extends T = T
|
|
382
|
+
>(
|
|
383
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
384
|
+
map: { filter: Filter<PM>; collect: (t: T) => Option<S>; limit?: number; skip?: number }
|
|
385
|
+
): <R2, A, E2, S2>(pure: Effect<A, E2, FixEnv<R2, Evt, S, S2>>) => Effect<
|
|
386
|
+
A,
|
|
387
|
+
InvalidStateError | OptimisticConcurrencyException | E2 | NotFoundError<ItemType>,
|
|
388
|
+
Exclude<R2, {
|
|
389
|
+
env: PureEnv<Evt, S, S2>
|
|
390
|
+
}>
|
|
391
|
+
>
|
|
392
|
+
export function queryAndSaveOnePure<
|
|
393
|
+
T extends { id: unknown },
|
|
394
|
+
PM extends PersistenceModelType<string>,
|
|
395
|
+
Evt,
|
|
396
|
+
ItemType extends string
|
|
397
|
+
>(
|
|
398
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
399
|
+
map: { filter: Filter<PM> }
|
|
400
|
+
): <R2, A, E2, T2>(pure: Effect<A, E2, FixEnv<R2, Evt, T, T2>>) => Effect<
|
|
401
|
+
A,
|
|
402
|
+
InvalidStateError | OptimisticConcurrencyException | E2 | NotFoundError<ItemType>,
|
|
403
|
+
Exclude<R2, {
|
|
404
|
+
env: PureEnv<Evt, T, T2>
|
|
405
|
+
}>
|
|
406
|
+
>
|
|
407
|
+
export function queryAndSaveOnePure(
|
|
408
|
+
self: any,
|
|
409
|
+
map: { filter: Filter<any>; collect?: any }
|
|
410
|
+
) {
|
|
411
|
+
return queryAndSaveOnePureEffect(self, Effect.sync(() => map))
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* @tsplus fluent Repository queryAndSavePureEffect
|
|
416
|
+
*/
|
|
417
|
+
export function queryAndSavePureEffect<
|
|
418
|
+
T extends { id: unknown },
|
|
419
|
+
PM extends PersistenceModelType<string>,
|
|
420
|
+
Evt,
|
|
421
|
+
ItemType extends string,
|
|
422
|
+
R,
|
|
423
|
+
E,
|
|
424
|
+
S extends T = T
|
|
425
|
+
>(
|
|
426
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
427
|
+
map: Effect<{ filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>
|
|
428
|
+
) {
|
|
429
|
+
return <R2, A, E2, S2 extends T>(pure: Effect<A, E2, FixEnv<R2, Evt, S[], S2[]>>) =>
|
|
430
|
+
queryEffect(self, map)
|
|
431
|
+
.flatMap((_) => self.saveManyWithPure_(_, pure))
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* @tsplus fluent Repository queryAndSavePure
|
|
436
|
+
*/
|
|
437
|
+
export function queryAndSavePure<
|
|
438
|
+
T extends { id: unknown },
|
|
439
|
+
PM extends PersistenceModelType<string>,
|
|
440
|
+
Evt,
|
|
441
|
+
ItemType extends string,
|
|
442
|
+
S extends T = T
|
|
443
|
+
>(
|
|
444
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
445
|
+
map: { filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }
|
|
446
|
+
) {
|
|
447
|
+
return self.queryAndSavePureEffect(Effect.sync(() => map))
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* @tsplus getter Repository saveManyWithPure
|
|
452
|
+
*/
|
|
453
|
+
export function saveManyWithPure<
|
|
454
|
+
T extends { id: unknown },
|
|
455
|
+
PM extends PersistenceModelType<string>,
|
|
456
|
+
Evt,
|
|
457
|
+
ItemType extends string
|
|
458
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>) {
|
|
459
|
+
return <R, A, E, S1 extends T, S2 extends T>(pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>) =>
|
|
460
|
+
(items: Iterable<S1>) => saveManyWithPure_(self, items, pure)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* @tsplus fluent Repository byIdAndSaveWithPure
|
|
465
|
+
*/
|
|
466
|
+
export function byIdAndSaveWithPure<
|
|
467
|
+
T extends { id: unknown },
|
|
468
|
+
PM extends PersistenceModelType<string>,
|
|
469
|
+
Evt,
|
|
470
|
+
ItemType extends string
|
|
471
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>, id: T["id"]) {
|
|
472
|
+
return <R, A, E, S2 extends T>(pure: Effect<A, E, FixEnv<R, Evt, T, S2>>) =>
|
|
473
|
+
get(self, id).flatMap((item) => saveWithPure_(self, item, pure))
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* NOTE: it's not as composable, only useful when the request is simple, and only this part needs request args.
|
|
478
|
+
* @tsplus getter Repository handleByIdAndSaveWithPure
|
|
479
|
+
*/
|
|
480
|
+
export function handleByIdAndSaveWithPure<
|
|
481
|
+
T extends { id: unknown },
|
|
482
|
+
PM extends PersistenceModelType<string>,
|
|
483
|
+
Evt,
|
|
484
|
+
ItemType extends string
|
|
485
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>) {
|
|
486
|
+
return <Req extends { id: T["id"] }, Context, R, A, E, S2 extends T>(
|
|
487
|
+
pure: (req: Req, ctx: Context) => Effect<A, E, FixEnv<R, Evt, T, S2>>
|
|
488
|
+
) =>
|
|
489
|
+
(req: Req, ctx: Context) => byIdAndSaveWithPure(self, req.id)(pure(req, ctx))
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* @tsplus fluent Repository saveManyWithPure_
|
|
494
|
+
*/
|
|
495
|
+
export function saveManyWithPure_<
|
|
496
|
+
R,
|
|
497
|
+
T extends { id: unknown },
|
|
498
|
+
PM extends PersistenceModelType<string>,
|
|
499
|
+
A,
|
|
500
|
+
E,
|
|
501
|
+
Evt,
|
|
502
|
+
S1 extends T,
|
|
503
|
+
S2 extends T,
|
|
504
|
+
ItemType extends string
|
|
505
|
+
>(
|
|
506
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
507
|
+
items: Iterable<S1>,
|
|
508
|
+
pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>
|
|
509
|
+
) {
|
|
510
|
+
return saveAllWithEffectInt(
|
|
511
|
+
self,
|
|
512
|
+
pure.runTerm([...items])
|
|
513
|
+
)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* @tsplus fluent Repository saveWithPure_
|
|
518
|
+
*/
|
|
519
|
+
export function saveWithPure_<
|
|
520
|
+
R,
|
|
521
|
+
T extends { id: unknown },
|
|
522
|
+
PM extends PersistenceModelType<string>,
|
|
523
|
+
A,
|
|
524
|
+
E,
|
|
525
|
+
Evt,
|
|
526
|
+
S1 extends T,
|
|
527
|
+
S2 extends T,
|
|
528
|
+
ItemType extends string
|
|
529
|
+
>(
|
|
530
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
531
|
+
item: S1,
|
|
532
|
+
pure: Effect<A, E, FixEnv<R, Evt, S1, S2>>
|
|
533
|
+
) {
|
|
534
|
+
return saveAllWithEffectInt(
|
|
535
|
+
self,
|
|
536
|
+
pure
|
|
537
|
+
.runTerm(item)
|
|
538
|
+
.map(([item, events, a]) => [[item], events, a])
|
|
539
|
+
)
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export function saveAllWithEffectInt<
|
|
543
|
+
T extends { id: unknown },
|
|
544
|
+
PM extends PersistenceModelType<string>,
|
|
545
|
+
P extends T,
|
|
546
|
+
Evt,
|
|
547
|
+
ItemType extends string,
|
|
548
|
+
R,
|
|
549
|
+
E,
|
|
550
|
+
A
|
|
551
|
+
>(
|
|
552
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
553
|
+
gen: Effect<readonly [Iterable<P>, Iterable<Evt>, A], E, R>
|
|
554
|
+
) {
|
|
555
|
+
return gen
|
|
556
|
+
.flatMap(
|
|
557
|
+
([items, events, a]) => self.saveAndPublish(items, events).map(() => a)
|
|
558
|
+
)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* @tsplus fluent Repository queryAndSavePureEffectBatched
|
|
563
|
+
*/
|
|
564
|
+
export function queryAndSavePureEffectBatched<
|
|
565
|
+
T extends { id: unknown },
|
|
566
|
+
PM extends PersistenceModelType<string>,
|
|
567
|
+
Evt,
|
|
568
|
+
ItemType extends string,
|
|
569
|
+
R,
|
|
570
|
+
E,
|
|
571
|
+
S extends T = T
|
|
572
|
+
>(
|
|
573
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
574
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
575
|
+
map: Effect<{ filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>,
|
|
576
|
+
batchSize = 100
|
|
577
|
+
) {
|
|
578
|
+
return <R2, A, E2, S2 extends T>(pure: Effect<A, E2, FixEnv<R2, Evt, S[], S2[]>>) =>
|
|
579
|
+
queryEffect(self, map)
|
|
580
|
+
.flatMap((_) => self.saveManyWithPureBatched_(_, pure, batchSize))
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* @tsplus fluent Repository queryAndSavePureBatched
|
|
585
|
+
*/
|
|
586
|
+
export function queryAndSavePureBatched<
|
|
587
|
+
T extends { id: unknown },
|
|
588
|
+
PM extends PersistenceModelType<string>,
|
|
589
|
+
Evt,
|
|
590
|
+
ItemType extends string,
|
|
591
|
+
S extends T = T
|
|
592
|
+
>(
|
|
593
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
594
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
595
|
+
map: { filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number },
|
|
596
|
+
batchSize = 100
|
|
597
|
+
) {
|
|
598
|
+
return self.queryAndSavePureEffectBatched(Effect.sync(() => map), batchSize)
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* @tsplus fluent Repository saveManyWithPureBatched
|
|
603
|
+
*/
|
|
604
|
+
export function saveManyWithPureBatched<
|
|
605
|
+
T extends { id: unknown },
|
|
606
|
+
PM extends PersistenceModelType<string>,
|
|
607
|
+
Evt,
|
|
608
|
+
ItemType extends string
|
|
609
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>, batchSize = 100) {
|
|
610
|
+
return <R, A, E, S1 extends T, S2 extends T>(pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>) =>
|
|
611
|
+
(items: Iterable<S1>) => saveManyWithPureBatched_(self, items, pure, batchSize)
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* @tsplus fluent Repository saveManyWithPureBatched_
|
|
616
|
+
*/
|
|
617
|
+
export function saveManyWithPureBatched_<
|
|
618
|
+
R,
|
|
619
|
+
T extends { id: unknown },
|
|
620
|
+
PM extends PersistenceModelType<string>,
|
|
621
|
+
A,
|
|
622
|
+
E,
|
|
623
|
+
Evt,
|
|
624
|
+
S1 extends T,
|
|
625
|
+
S2 extends T,
|
|
626
|
+
ItemType extends string
|
|
627
|
+
>(
|
|
628
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
629
|
+
items: Iterable<S1>,
|
|
630
|
+
pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>,
|
|
631
|
+
batchSize = 100
|
|
632
|
+
) {
|
|
633
|
+
return items
|
|
634
|
+
.chunk(batchSize)
|
|
635
|
+
.forEachEffect((batch) =>
|
|
636
|
+
saveAllWithEffectInt(
|
|
637
|
+
self,
|
|
638
|
+
pure.runTerm(batch)
|
|
639
|
+
)
|
|
640
|
+
)
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* @tsplus getter Repository save
|
|
645
|
+
*/
|
|
646
|
+
export function save<
|
|
647
|
+
T extends { id: unknown },
|
|
648
|
+
PM extends PersistenceModelType<string>,
|
|
649
|
+
Evt,
|
|
650
|
+
ItemType extends string
|
|
651
|
+
>(
|
|
652
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>
|
|
653
|
+
) {
|
|
654
|
+
return (...items: NonEmptyArray<T>) => self.saveAndPublish(items)
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* @tsplus getter Repository saveWithEvents
|
|
659
|
+
*/
|
|
660
|
+
export function saveWithEvents<
|
|
661
|
+
T extends { id: unknown },
|
|
662
|
+
PM extends PersistenceModelType<string>,
|
|
663
|
+
Evt,
|
|
664
|
+
ItemType extends string
|
|
665
|
+
>(
|
|
666
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>
|
|
667
|
+
) {
|
|
668
|
+
return (events: Iterable<Evt>) => (...items: NonEmptyArray<T>) => self.saveAndPublish(items, events)
|
|
669
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { RepositoryBaseC } from "../RepositoryBase.js"
|
|
2
|
+
import type { PersistenceModelType } from "../Store.js"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @tsplus type Repository
|
|
6
|
+
*/
|
|
7
|
+
export interface Repository<
|
|
8
|
+
T extends { id: unknown },
|
|
9
|
+
PM extends PersistenceModelType<string>,
|
|
10
|
+
Evt,
|
|
11
|
+
ItemType extends string
|
|
12
|
+
> extends RepositoryBaseC<T, PM, Evt, ItemType> {}
|