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