@effect-app/infra 0.211.0 → 0.211.2

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.
@@ -8,7 +8,6 @@ import {
8
8
  AnyPureDSL,
9
9
  byIdAndSaveWithPure,
10
10
  get,
11
- queryEffect,
12
11
  type Repository,
13
12
  saveAllWithEffectInt,
14
13
  saveManyWithPure_,
@@ -16,7 +15,7 @@ import {
16
15
  saveWithPure_
17
16
  } from "./Repository.js"
18
17
  import { StoreMaker } from "./Store.js"
19
- import type { Filter, FilterArgs, FilterFunc, PersistenceModelType, StoreConfig } from "./Store.js"
18
+ import type { FilterArgs, PersistenceModelType, StoreConfig } from "./Store.js"
20
19
  import type {} from "effect/Equal"
21
20
  import type {} from "effect/Hash"
22
21
  import { toNonEmptyArray } from "@effect-app/core/Array"
@@ -35,7 +34,7 @@ import { make as makeQuery } from "./query.js"
35
34
  import type { QAll, Query, QueryEnd, QueryProjection, QueryWhere } from "./query.js"
36
35
  import * as Q from "./query.js"
37
36
  import { ContextMapContainer } from "./Store/ContextMapContainer.js"
38
- import * as QB from "./Store/filterApi/query.js"
37
+ import type * as QB from "./Store/filterApi/query.js"
39
38
 
40
39
  export interface Mapped1<PM extends { id: string }, X, R> {
41
40
  all: Effect<X[], ParseResult.ParseError, R>
@@ -82,24 +81,12 @@ export abstract class RepositoryBaseC<
82
81
  items: Iterable<T>,
83
82
  events?: Iterable<Evt>
84
83
  ) => Effect<void, InvalidStateError | OptimisticConcurrencyException>
85
- abstract readonly utils: {
86
- parseMany: (a: readonly PM[]) => Effect<readonly T[]>
87
- parseMany2: <A, R>(
88
- a: readonly PM[],
89
- schema: S.Schema<A, Omit<PM, "_etag">, R>
90
- ) => Effect<readonly A[], S.ParseResult.ParseError, R>
91
- all: Effect<PM[]>
92
- filter: FilterFunc<PM>
93
- // count: (filter?: Filter<PM>) => Effect<never, never, NonNegativeInt>
94
- }
95
84
  abstract readonly changeFeed: PubSub.PubSub<[T[], "save" | "remove"]>
96
85
  abstract readonly removeAndPublish: (
97
86
  items: Iterable<T>,
98
87
  events?: Iterable<Evt>
99
88
  ) => Effect<void>
100
89
 
101
- /** @deprecated use query */
102
- abstract readonly mapped: Mapped<PM, Omit<PM, "_etag">>
103
90
  abstract readonly query: {
104
91
  <A, R, From extends FieldValues, TType extends "one" | "many" | "count" = "many">(
105
92
  q: (
@@ -119,6 +106,9 @@ export abstract class RepositoryBaseC<
119
106
  // q: QueryProjection<Omit<PM, "_etag"> extends From ? From : never, A, R>
120
107
  // ): Effect.Effect<readonly A[], S.ParseResult.ParseError, R>
121
108
  }
109
+
110
+ /** @deprecated use query */
111
+ abstract readonly mapped: Mapped<PM, Omit<PM, "_etag">>
122
112
  }
123
113
 
124
114
  export abstract class RepositoryBaseC1<
@@ -149,7 +139,6 @@ export class RepositoryBaseC2<
149
139
  this.removeAndPublish = this.impl.removeAndPublish
150
140
  this.find = this.impl.find
151
141
  this.all = this.impl.all
152
- this.utils = this.impl.utils
153
142
  this.changeFeed = this.impl.changeFeed
154
143
  this.mapped = this.impl.mapped
155
144
  this.query = this.impl.query
@@ -159,7 +148,6 @@ export class RepositoryBaseC2<
159
148
  override removeAndPublish
160
149
  override find
161
150
  override all
162
- override utils
163
151
  override changeFeed
164
152
  override mapped
165
153
  override query
@@ -313,31 +301,6 @@ export class RepositoryBaseC3<
313
301
  .pipe(Effect.map(([item, events, a]) => [[item], events, a]))
314
302
  )
315
303
  }
316
-
317
- /** @deprecated use query */
318
- queryLegacy<S = T>(
319
- // TODO: think about collectPM, collectE, and collect(Parsed)
320
- _map: { filter?: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }
321
- ) {
322
- return Effect.flatMap(Effect.sync(() => _map), (f) =>
323
- (f.filter ? this.utils.filter(f) : this.utils.all)
324
- .pipe(
325
- Effect.flatMap((_) => this.utils.parseMany(_)),
326
- Effect.map((_) => f.collect ? ReadonlyArray.filterMap(_, f.collect) : _ as unknown[] as S[])
327
- ))
328
- }
329
-
330
- /** @deprecated use query */
331
- queryAndSavePureBatched<
332
- S extends T = T
333
- >(
334
- // TODO: think about collectPM, collectE, and collect(Parsed)
335
- map: { filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number },
336
- batchSize = 100
337
- ) {
338
- return <R2, A, E2, S2 extends T>(pure: Effect<A, E2, FixEnv<R2, Evt, readonly S[], readonly S2[]>>) =>
339
- Effect.flatMap(queryEffect(this, Effect.succeed(map)), (_) => this.saveManyWithPure(_, pure, batchSize))
340
- }
341
304
  }
342
305
 
343
306
  type Exact<A, B> = [A] extends [B] ? [B] extends [A] ? true : false : false
@@ -415,12 +378,8 @@ export function makeRepo<
415
378
  : () => Effect.unit
416
379
  const changeFeed = yield* $(PubSub.unbounded<[T[], "save" | "remove"]>())
417
380
 
418
- const allE = store.all.pipe(Effect.flatMap((items) =>
419
- Effect.gen(function*($) {
420
- const { set } = yield* $(cms)
421
- return items.map((_) => mapReverse(_, set))
422
- })
423
- ))
381
+ const allE = cms
382
+ .pipe(Effect.flatMap((cm) => Effect.map(store.all, (_) => _.map((_) => mapReverse(_, cm.set)))))
424
383
 
425
384
  const all = Effect
426
385
  .flatMap(
@@ -531,33 +490,30 @@ export function makeRepo<
531
490
  })
532
491
  }
533
492
 
534
- const utils = {
535
- parseMany: (items) =>
536
- Effect
537
- .flatMap(cms, (cm) =>
538
- decodeMany(items.map((_) => mapReverse(_, cm.set)))
539
- .pipe(Effect.orDie, Effect.withSpan("parseMany"))),
540
- parseMany2: (items, schema) =>
541
- Effect
542
- .flatMap(cms, (cm) =>
543
- S
544
- .decode(S.array(schema))(
545
- items.map((_) => mapReverse(_, cm.set) as unknown as Omit<PM, "_etag">)
546
- )
547
- .pipe(Effect.orDie, Effect.withSpan("parseMany2"))),
548
- filter: <U extends keyof PM = keyof PM>(args: FilterArgs<PM, U>) =>
549
- store
550
- .filter(args)
551
- .pipe(Effect.tap((items) =>
552
- args.select
553
- ? Effect.unit
554
- : Effect.map(cms, ({ set }) => items.forEach((_) => set((_ as PM).id, (_ as PM)._etag)))
555
- )),
556
- all: Effect.tap(
557
- store.all,
558
- (items) => Effect.map(cms, ({ set }) => items.forEach((_) => set(_.id, _._etag)))
559
- )
560
- } satisfies Repository<T, PM, Evt, ItemType>["utils"]
493
+ const parseMany = (items: readonly PM[]) =>
494
+ Effect
495
+ .flatMap(cms, (cm) =>
496
+ decodeMany(items.map((_) => mapReverse(_, cm.set)))
497
+ .pipe(Effect.orDie, Effect.withSpan("parseMany")))
498
+ const parseMany2 = <A, R>(
499
+ items: readonly PM[],
500
+ schema: S.Schema<A, Omit<PM, "_etag">, R>
501
+ ) =>
502
+ Effect
503
+ .flatMap(cms, (cm) =>
504
+ S
505
+ .decode(S.array(schema))(
506
+ items.map((_) => mapReverse(_, cm.set) as unknown as Omit<PM, "_etag">)
507
+ )
508
+ .pipe(Effect.orDie, Effect.withSpan("parseMany2")))
509
+ const filter = <U extends keyof PM = keyof PM>(args: FilterArgs<PM, U>) =>
510
+ store
511
+ .filter(args)
512
+ .pipe(Effect.tap((items) =>
513
+ args.select
514
+ ? Effect.unit
515
+ : Effect.map(cms, ({ set }) => items.forEach((_) => set((_ as PM).id, (_ as PM)._etag)))
516
+ ))
561
517
 
562
518
  // TODO: For raw we should use S.from, and drop the R...
563
519
  const query: {
@@ -580,22 +536,20 @@ export function makeRepo<
580
536
  >(q: QAll<PM, A, R>) => {
581
537
  const a = Q.toFilter(q)
582
538
  const eff = a.mode === "raw"
583
- ? r
584
- .utils
585
- .filter(a)
539
+ ? filter(a)
586
540
  // TODO: mapFrom but need to support per field and dependencies
587
541
  .pipe(Effect.andThen(flow(S.decode(S.array(S.from(a.schema ?? schema))), Effect.provide(rctx))))
588
542
  : Effect.flatMap(
589
- utils.filter(a),
543
+ filter(a),
590
544
  (_) =>
591
545
  Unify
592
546
  .unify(
593
547
  a.schema
594
- ? utils.parseMany2(
548
+ ? parseMany2(
595
549
  _,
596
550
  a.schema as any
597
551
  )
598
- : utils.parseMany(_)
552
+ : parseMany(_)
599
553
  )
600
554
  )
601
555
  return pipe(
@@ -623,40 +577,36 @@ export function makeRepo<
623
577
  }) as any
624
578
 
625
579
  const r: Repository<T, PM, Evt, ItemType> = {
580
+ changeFeed,
581
+ itemType: name,
582
+ find,
583
+ all,
584
+ saveAndPublish,
585
+ removeAndPublish,
586
+ query: (q: any) => query(typeof q === "function" ? q(makeQuery()) : q) as any,
587
+
626
588
  /**
627
589
  * @internal
628
590
  */
629
- utils,
630
591
  mapped: <A, R>(schema: S.Schema<A, any, R>) => {
631
592
  const dec = S.decode(schema)
632
593
  const encMany = S.encode(S.array(schema))
633
594
  const decMany = S.decode(S.array(schema))
634
595
  return {
635
- all: cms
636
- .pipe(
637
- Effect.flatMap((cm) => Effect.map(utils.all, (_) => _.map((_) => mapReverse(_, cm.set)))),
638
- Effect.flatMap(decMany),
639
- Effect.map((_) => _ as any[])
640
- ),
596
+ all: allE.pipe(
597
+ Effect.flatMap(decMany),
598
+ Effect.map((_) => _ as any[])
599
+ ),
641
600
  find: (id: PM["id"]) => flatMapOption(findE(id), dec),
642
601
  query: (b: any) =>
643
- r
644
- .utils
645
- .filter({ filter: b })
602
+ filter({ filter: b })
646
603
  .pipe(
647
604
  Effect.flatMap(decMany),
648
605
  Effect.map((_) => _ as any[])
649
606
  ),
650
607
  save: (...xes: any[]) => Effect.flatMap(encMany(xes), (_) => saveAllE(_))
651
608
  }
652
- },
653
- changeFeed,
654
- itemType: name,
655
- find,
656
- all,
657
- saveAndPublish,
658
- removeAndPublish,
659
- query: (q: any) => query(typeof q === "function" ? q(makeQuery()) : q) as any
609
+ }
660
610
  }
661
611
  return r
662
612
  })
@@ -667,28 +617,11 @@ export function makeRepo<
667
617
 
668
618
  return {
669
619
  make,
670
- Query: QB.QueryBuilder.make<PM>(),
671
620
  Q: Q.make<Omit<PM, "_etag">>()
672
621
  }
673
622
  }
674
623
  }
675
624
 
676
- /**
677
- * only use this as a shortcut if you don't have the item already
678
- * @tsplus fluent Repository removeById
679
- */
680
- export function removeById<
681
- T extends { id: unknown },
682
- PM extends PersistenceModelType<string>,
683
- Evt,
684
- ItemType extends string
685
- >(
686
- self: Repository<T, PM, Evt, ItemType>,
687
- id: T["id"]
688
- ) {
689
- return get(self, id).pipe(Effect.flatMap((_) => self.removeAndPublish([_])))
690
- }
691
-
692
625
  const pluralize = (s: string) =>
693
626
  s.endsWith("s")
694
627
  ? s + "es"
@@ -799,8 +732,6 @@ export interface Repos<
799
732
  },
800
733
  f: (r: Repository<T, PM, Evt, ItemType>) => Out
801
734
  ): Effect<Out, E, StoreMaker | ContextMapContainer | R | RInitial | R2>
802
- /** @deprecated use `Q` instead */
803
- readonly Query: ReturnType<typeof QB.QueryBuilder.make<PM>>
804
735
  readonly Q: ReturnType<typeof Q.make<PM>>
805
736
  readonly type: Repository<T, PM, Evt, ItemType>
806
737
  }
@@ -927,14 +858,6 @@ export interface RepoFunctions<T extends { id: unknown }, PM extends { id: strin
927
858
  >
928
859
  }
929
860
 
930
- /** @deprecated use query */
931
- queryLegacy: <S = T>(map: {
932
- filter?: Filter<PM>
933
- collect?: (t: T) => Option<S>
934
- limit?: number
935
- skip?: number
936
- }) => Effect<S[], never, Service>
937
-
938
861
  /** @experimental */
939
862
  mapped: MM<Service, PM, Omit<PM, "_etag">>
940
863
 
@@ -951,7 +874,6 @@ const makeRepoFunctions = (tag: any) => {
951
874
  get,
952
875
  query,
953
876
  queryAndSavePure,
954
- queryLegacy,
955
877
  removeAndPublish,
956
878
  removeById,
957
879
  save,
@@ -971,10 +893,10 @@ const makeRepoFunctions = (tag: any) => {
971
893
  save,
972
894
  get,
973
895
  query,
974
- queryLegacy,
975
896
  mapped,
976
897
  queryAndSavePure,
977
- saveManyWithPure
898
+ saveManyWithPure,
899
+ use: (body: any) => Effect.andThen(tag, body)
978
900
  }
979
901
  }
980
902
 
@@ -1013,7 +935,6 @@ export const RepositoryBaseImpl = <Service>() => {
1013
935
  static readonly make = mkRepo.make
1014
936
  static readonly makeWith = ((a: any, b: any) => Effect.map(mkRepo.make(a), b)) as any
1015
937
 
1016
- static readonly Query = QB.QueryBuilder.make<PM>()
1017
938
  static readonly Q = Q.make<From>()
1018
939
  static readonly type: Repository<T, PM, Evt, ItemType> = undefined as any
1019
940
  }
@@ -1061,7 +982,6 @@ export const RepositoryDefaultImpl = <Service>() => {
1061
982
  static readonly make = mkRepo.make
1062
983
  static readonly makeWith = ((a: any, b: any) => Effect.map(mkRepo.make(a), b)) as any
1063
984
 
1064
- static readonly Query = QB.QueryBuilder.make<PM>()
1065
985
  static readonly Q = Q.make<From>()
1066
986
 
1067
987
  static readonly type: Repository<T, PM, Evt, ItemType> = undefined as any
@@ -53,52 +53,6 @@ export const codeFilterStatement = <E>(p: FilterR, x: E) => {
53
53
  }
54
54
  }
55
55
 
56
- // const or = <E extends { id: string }, NE extends E>(filters: readonly FilterResult[], x: E): Option<NE> =>
57
- // filters
58
- // .some((p) => {
59
- // if (p.t === "and-scope") {
60
- // return and(p.result, x)
61
- // }
62
- // if (p.t === "or-scope") {
63
- // return or(p.result, x)
64
- // }
65
- // if (p.t === "where-scope") {
66
- // return codeFilter2(filters)(x)
67
- // }
68
- // return codeFilterStatement(p, x)
69
- // })
70
- // ? Option.some(x as unknown as NE)
71
- // : Option.none()
72
-
73
- // export const and = <E extends { id: string }, NE extends E>(filters: readonly FilterResult[], x: E): Option<NE> =>
74
- // filters
75
- // .every((p) => {
76
- // if (p.t === "and-scope") {
77
- // return and(p.result, x)
78
- // }
79
- // if (p.t === "or-scope") {
80
- // return or(p.result, x)
81
- // }
82
- // if (p.t === "where-scope") {
83
- // return codeFilter2(filters)(x)
84
- // }
85
- // return codeFilterStatement(p, x)
86
- // })
87
- // ? Option.some(x as unknown as NE)
88
- // : Option.none()
89
-
90
- // // TODO: how to handle and/or outside scopes.
91
- // // TODO: the scopes are not about and every, or some.. they're about logical grouping. It's a logical group + and/or etc.
92
- // // TODO: how to convert this to code? would we compile an actual function body instead?!
93
- // export function codeFilter2<E extends { id: string }, NE extends E>(filters: readonly FilterResult[]) {
94
- // // TODO: handle or, and, or-scope, and-scope, where-scope
95
- // return (x: E) =>
96
- // // AND
97
- // and<E, NE>(filters, x)
98
- // // OR
99
- // // or<E, NE>(filters, x)
100
- // }
101
-
102
56
  export const codeFilter3 = <E>(state: readonly FilterResult[]) => (sut: E) => codeFilter3_(state, sut)
103
57
  export const codeFilter3_ = <E>(state: readonly FilterResult[], sut: E, statements: any[] = []): boolean => {
104
58
  let s = ""