@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.
Files changed (38) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/_cjs/services/Repository/dsl.cjs +70 -0
  3. package/_cjs/services/Repository/dsl.cjs.map +1 -0
  4. package/_cjs/services/Repository/ext.cjs +202 -0
  5. package/_cjs/services/Repository/ext.cjs.map +1 -0
  6. package/_cjs/services/Repository/service.cjs +6 -0
  7. package/_cjs/services/Repository/service.cjs.map +1 -0
  8. package/_cjs/services/Repository.cjs +32 -252
  9. package/_cjs/services/Repository.cjs.map +1 -1
  10. package/_cjs/services/RepositoryBase.cjs +173 -48
  11. package/_cjs/services/RepositoryBase.cjs.map +1 -1
  12. package/_src/services/Repository/dsl.ts +137 -0
  13. package/_src/services/Repository/ext.ts +669 -0
  14. package/_src/services/Repository/service.ts +12 -0
  15. package/_src/services/Repository.ts +3 -815
  16. package/_src/services/RepositoryBase.ts +621 -4
  17. package/dist/services/Repository/dsl.d.ts +51 -0
  18. package/dist/services/Repository/dsl.d.ts.map +1 -0
  19. package/dist/services/Repository/dsl.js +55 -0
  20. package/dist/services/Repository/ext.d.ts +310 -0
  21. package/dist/services/Repository/ext.d.ts.map +1 -0
  22. package/dist/services/Repository/ext.js +166 -0
  23. package/dist/services/Repository/service.d.ts +10 -0
  24. package/dist/services/Repository/service.d.ts.map +1 -0
  25. package/dist/services/Repository/service.js +2 -0
  26. package/dist/services/Repository.d.ts +3 -363
  27. package/dist/services/Repository.d.ts.map +1 -1
  28. package/dist/services/Repository.js +4 -217
  29. package/dist/services/RepositoryBase.d.ts +241 -6
  30. package/dist/services/RepositoryBase.d.ts.map +1 -1
  31. package/dist/services/RepositoryBase.js +164 -48
  32. package/dist/services/simpledb/cosmosdb.d.ts +2 -2
  33. package/dist/services/simpledb/diskdb.d.ts +1 -1
  34. package/dist/services/simpledb/memdb.d.ts +1 -1
  35. package/dist/services/simpledb/redisdb.d.ts +8 -8
  36. package/dist/services/simpledb/shared.d.ts +10 -10
  37. package/dist/services/simpledb/simpledb.d.ts +2 -2
  38. 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 type { Repository } from "./Repository.js"
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 { InvalidStateError, OptimisticConcurrencyException } from "../errors.js"
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
- ) => RepositoryBaseC2<T, PM, Evt, ItemType>)
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 RepositoryBaseC2<T, PM, Evt, ItemType> {
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