@effect-app/infra 0.170.6 → 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 +17 -0
- 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/_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 -815
- package/_src/services/RepositoryBase.ts +621 -4
- 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 +164 -48
- package/dist/services/simpledb/cosmosdb.d.ts +2 -2
- package/dist/services/simpledb/diskdb.d.ts +1 -1
- package/dist/services/simpledb/memdb.d.ts +1 -1
- package/dist/services/simpledb/redisdb.d.ts +8 -8
- package/dist/services/simpledb/shared.d.ts +10 -10
- package/dist/services/simpledb/simpledb.d.ts +2 -2
- 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
|
) {
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Pure, PureEnvEnv } from "@effect-app/prelude/Pure";
|
|
2
|
+
import { Effect } from "effect/Effect";
|
|
3
|
+
import { NonEmptyReadonlyArray } from "effect/ReadonlyArray";
|
|
4
|
+
import type { FixEnv, PureLogT } from "@effect-app/prelude/Pure";
|
|
5
|
+
export interface PureDSL<S, S2, W> {
|
|
6
|
+
get: ReturnType<typeof Pure.get<S>>;
|
|
7
|
+
set: typeof Pure.set<S2>;
|
|
8
|
+
log: (...w: W[]) => PureLogT<W>;
|
|
9
|
+
}
|
|
10
|
+
export declare const AnyPureDSL: PureDSL<any, any, any>;
|
|
11
|
+
export type AllDSL<T, Evt> = (<R, A, E, S1 extends T, S2 extends T>(pure: (dsl: PureDSL<S1[], S2[], Evt>) => Effect<A, E, R>) => Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>) & AllDSLExt<T, Evt>;
|
|
12
|
+
/**
|
|
13
|
+
* @tsplus type DSLExt
|
|
14
|
+
*/
|
|
15
|
+
export interface AllDSLExt<T, Evt> {
|
|
16
|
+
modify: <R, E, A, S1 extends T, S2 extends T>(pure: (items: S1[], dsl: PureDSL<S1[], S2[], Evt>) => Effect<A, E, R>) => Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>;
|
|
17
|
+
update: <R, E, S1 extends T, S2 extends T>(pure: (items: S1[], log: (...evt: Evt[]) => PureLogT<Evt>) => Effect<S2[], E, R>) => Effect<S2[], E, FixEnv<R, Evt, S1[], S2[]>>;
|
|
18
|
+
}
|
|
19
|
+
export declare function makeAllDSL<T, Evt>(): AllDSL<T, Evt>;
|
|
20
|
+
export type OneDSL<T, Evt> = (<R, A, E, S1 extends T, S2 extends T>(pure: (dsl: PureDSL<S1, S2, Evt>) => Effect<A, E, FixEnv<R, Evt, S1, S2>>) => Effect<A, E, FixEnv<R, Evt, S1, S2>>) & OneDSLExt<T, Evt>;
|
|
21
|
+
/**
|
|
22
|
+
* @tsplus type DSLExt
|
|
23
|
+
*/
|
|
24
|
+
export interface OneDSLExt<T, Evt> {
|
|
25
|
+
modify: <R, E, A, S1 extends T, S2 extends T>(pure: (items: S1, dsl: PureDSL<S1, S2, Evt>) => Effect<A, E, FixEnv<R, Evt, S1, S2>>) => Effect<A, E, FixEnv<R, Evt, S1, S2> | PureEnvEnv<Evt, S1, S1>>;
|
|
26
|
+
update: <R, E, S1 extends T, S2 extends T>(pure: (items: S1, log: (...evt: Evt[]) => PureLogT<Evt>) => Effect<S2, E, FixEnv<R, Evt, S1, S2>>) => Effect<S2, E, FixEnv<R, Evt, S1, S2>>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @tsplus fluent DSLExt updateWith
|
|
30
|
+
* @tsplus location "@effect-app/infra/services/Repository/dsl"
|
|
31
|
+
*/
|
|
32
|
+
export declare function updateWithOne<T, Evt, S1 extends T, S2 extends T>(self: OneDSL<T, Evt>, upd: (item: S1) => S2): import("effect/Effect").Effect<S2, never, import("@effect-app/prelude/Pure").PureEnvEnv<Evt, S1, S2>>;
|
|
33
|
+
/**
|
|
34
|
+
* @tsplus fluent DSLExt updateWith
|
|
35
|
+
* @tsplus location "@effect-app/infra/services/Repository/dsl"
|
|
36
|
+
*/
|
|
37
|
+
export declare function updateWith<T, Evt, S1 extends T, S2 extends T>(self: AllDSL<T, Evt>, upd: (item: S1[]) => S2[]): import("effect/Effect").Effect<S2[], never, import("@effect-app/prelude/Pure").PureEnvEnv<Evt, S1[], S2[]>>;
|
|
38
|
+
export declare function makeOneDSL<T, Evt>(): OneDSL<T, Evt>;
|
|
39
|
+
export declare function makeDSL<S1, S2, Evt>(): (<R, A, E>(pure: (dsl: PureDSL<S1, S2, Evt>) => Effect<A, E, R>) => Effect<A, E, FixEnv<R, Evt, S1, S2>>) & {
|
|
40
|
+
modify: <R_1, E_1, A_1>(pure: (items: S1, dsl: PureDSL<S1, S2, Evt>) => import("effect/Effect").Effect<A_1, E_1, R_1>) => import("effect/Effect").Effect<A_1, E_1, FixEnv<R_1, Evt, S1, S2>>;
|
|
41
|
+
update: <R_2, E_2>(pure: (items: S1, log: (...evt: Evt[]) => PureLogT<Evt>) => import("effect/Effect").Effect<S2, E_2, R_2>) => import("effect/Effect").Effect<S2, E_2, FixEnv<R_2, Evt, S1, S2>>;
|
|
42
|
+
};
|
|
43
|
+
export interface DSLExt<S1, S2, Evt> extends ReturnType<typeof makeDSL<S1, S2, Evt>> {
|
|
44
|
+
}
|
|
45
|
+
export declare function ifAny<T, R, E, A>(fn: (items: NonEmptyReadonlyArray<T>) => Effect<A, E, R>): (items: Iterable<T>) => import("effect/Effect").Effect<import("effect/Option").Option<A>, E, R>;
|
|
46
|
+
/**
|
|
47
|
+
* @tsplus fluent Iterable ifAny
|
|
48
|
+
* @tsplus location "@effect-app/infra/services/Repository/dsl"
|
|
49
|
+
*/
|
|
50
|
+
export declare function ifAny_<T, R, E, A>(items: Iterable<T>, fn: (items: NonEmptyReadonlyArray<T>) => Effect<A, E, R>): import("effect/Effect").Effect<import("effect/Option").Option<A>, E, R>;
|
|
51
|
+
//# sourceMappingURL=dsl.d.ts.map
|