@effect-app/infra 1.44.6 → 1.45.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.
@@ -50,10 +50,10 @@ import type { QAll, Query, QueryEnd, QueryProjection, QueryWhere } from "./query
50
50
  import * as Q from "./query.js"
51
51
  import { ContextMapContainer } from "./Store/ContextMapContainer.js"
52
52
 
53
- export interface Mapped1<A, Encoded extends { id: string }, R> {
53
+ export interface Mapped1<A, IdKey extends keyof A, R> {
54
54
  all: Effect<A[], ParseResult.ParseError, R>
55
55
  save: (...xes: readonly A[]) => Effect<void, OptimisticConcurrencyException | ParseResult.ParseError, R>
56
- find: (id: Encoded["id"]) => Effect<Option<A>, ParseResult.ParseError, R>
56
+ find: (id: A[IdKey]) => Effect<Option<A>, ParseResult.ParseError, R>
57
57
  }
58
58
 
59
59
  // TODO: auto use project, and select fields from the From side of schema only
@@ -62,13 +62,13 @@ export interface Mapped2<A, R> {
62
62
  }
63
63
 
64
64
  export interface Mapped<Encoded extends { id: string }> {
65
- <A, R>(schema: S.Schema<A, Encoded, R>): Mapped1<A, Encoded, R>
65
+ <A, R, IdKey extends keyof A>(schema: S.Schema<A, Encoded, R>): Mapped1<A, IdKey, R>
66
66
  // TODO: constrain on Encoded2 having to contain only fields that fit Encoded
67
67
  <A, Encoded2, R>(schema: S.Schema<A, Encoded2, R>): Mapped2<A, R>
68
68
  }
69
69
 
70
70
  export interface MM<Repo, Encoded extends { id: string }> {
71
- <A, R>(schema: S.Schema<A, Encoded, R>): Effect<Mapped1<A, Encoded, R>, never, Repo>
71
+ <A, R, IdKey extends keyof A>(schema: S.Schema<A, Encoded, R>): Effect<Mapped1<A, IdKey, R>, never, Repo>
72
72
  // TODO: constrain on Encoded2 having to contain only fields that fit Encoded
73
73
  <A, Encoded2, R>(schema: S.Schema<A, Encoded2, R>): Effect<Mapped2<A, R>, never, Repo>
74
74
  }
@@ -77,13 +77,14 @@ export interface MM<Repo, Encoded extends { id: string }> {
77
77
  * @tsplus type Repository
78
78
  */
79
79
  export abstract class RepositoryBaseC<
80
- T extends { id: unknown },
80
+ T,
81
81
  Encoded extends { id: string },
82
82
  Evt,
83
- ItemType extends string
83
+ ItemType extends string,
84
+ IdKey extends keyof T
84
85
  > {
85
86
  abstract readonly itemType: ItemType
86
- abstract readonly find: (id: T["id"]) => Effect<Option<T>>
87
+ abstract readonly find: (id: T[IdKey]) => Effect<Option<T>>
87
88
  abstract readonly all: Effect<T[]>
88
89
  abstract readonly saveAndPublish: (
89
90
  items: Iterable<T>,
@@ -120,11 +121,12 @@ export abstract class RepositoryBaseC<
120
121
  }
121
122
 
122
123
  export abstract class RepositoryBaseC1<
123
- T extends { id: unknown },
124
+ T,
124
125
  Encoded extends { id: string },
125
126
  Evt,
126
- ItemType extends string
127
- > extends RepositoryBaseC<T, Encoded, Evt, ItemType> {
127
+ ItemType extends string,
128
+ IdKey extends keyof T
129
+ > extends RepositoryBaseC<T, Encoded, Evt, ItemType, IdKey> {
128
130
  constructor(
129
131
  public readonly itemType: ItemType
130
132
  ) {
@@ -133,15 +135,16 @@ export abstract class RepositoryBaseC1<
133
135
  }
134
136
 
135
137
  export class RepositoryBaseC2<
136
- T extends { id: unknown },
138
+ T,
137
139
  Encoded extends { id: string },
138
140
  Evt,
139
141
  ItemType extends string,
140
- Ext
141
- > extends RepositoryBaseC1<T, Encoded, Evt, ItemType> {
142
+ Ext,
143
+ IdKey extends keyof T
144
+ > extends RepositoryBaseC1<T, Encoded, Evt, ItemType, IdKey> {
142
145
  constructor(
143
146
  itemType: ItemType,
144
- protected readonly impl: Repository<T, Encoded, Evt, ItemType> & Ext
147
+ protected readonly impl: Repository<T, Encoded, Evt, ItemType, IdKey> & Ext
145
148
  ) {
146
149
  super(itemType)
147
150
  this.saveAndPublish = this.impl.saveAndPublish
@@ -163,13 +166,14 @@ export class RepositoryBaseC2<
163
166
  }
164
167
 
165
168
  export class RepositoryBaseC3<
166
- T extends { id: unknown },
169
+ T,
167
170
  Encoded extends { id: string },
168
171
  Evt,
169
172
  ItemType extends string,
170
- Ext
171
- > extends RepositoryBaseC2<T, Encoded, Evt, ItemType, Ext> {
172
- get(id: T["id"]) {
173
+ Ext,
174
+ IdKey extends keyof T
175
+ > extends RepositoryBaseC2<T, Encoded, Evt, ItemType, Ext, IdKey> {
176
+ get(id: T[IdKey]) {
173
177
  return Effect.andThen(
174
178
  this
175
179
  .find(id),
@@ -179,7 +183,7 @@ export class RepositoryBaseC3<
179
183
 
180
184
  readonly log = (evt: Evt) => AnyPureDSL.log(evt)
181
185
 
182
- removeById(id: T["id"]) {
186
+ removeById(id: T[IdKey]) {
183
187
  return Effect.andThen(this.get(id), (_) => this.removeAndPublish([_]))
184
188
  }
185
189
 
@@ -237,8 +241,8 @@ export class RepositoryBaseC3<
237
241
  Effect.andThen((_) =>
238
242
  Array.isArray(_)
239
243
  ? batch === undefined
240
- ? saveManyWithPure_(this, _, pure as any)
241
- : saveManyWithPureBatched_(this, _, pure as any, batch === "batched" ? 100 : batch)
244
+ ? saveManyWithPure_(this, _ as any, pure as any)
245
+ : saveManyWithPureBatched_(this, _ as any, pure as any, batch === "batched" ? 100 : batch)
242
246
  : saveWithPure_(this, _ as any, pure as any)
243
247
  )
244
248
  ) as any
@@ -246,7 +250,7 @@ export class RepositoryBaseC3<
246
250
  /**
247
251
  * NOTE: it's not as composable, only useful when the request is simple, and only this part needs request args.
248
252
  */
249
- readonly handleByIdAndSaveWithPure = <Req extends { id: T["id"] }, Context, R, A, E, S2 extends T>(
253
+ readonly handleByIdAndSaveWithPure = <Req extends { id: T[IdKey] }, Context, R, A, E, S2 extends T>(
250
254
  pure: (req: Req, ctx: Context) => Effect<A, E, FixEnv<R, Evt, T, S2>>
251
255
  ) =>
252
256
  (req: Req, ctx: Context) => byIdAndSaveWithPure(this, req.id)(pure(req, ctx))
@@ -290,7 +294,7 @@ export class RepositoryBaseC3<
290
294
 
291
295
  byIdAndSaveWithPure: {
292
296
  <R, A, E, S2 extends T>(
293
- id: T["id"],
297
+ id: T[IdKey],
294
298
  pure: Effect<A, E, FixEnv<R, Evt, T, S2>>
295
299
  ): Effect<
296
300
  A,
@@ -331,12 +335,14 @@ export function makeRepo<
331
335
  ItemType extends string,
332
336
  R,
333
337
  Encoded extends { id: string },
334
- T extends { id: unknown }
338
+ T,
339
+ IdKey extends keyof T
335
340
  >(
336
341
  name: ItemType,
337
342
  schema: S.Schema<T, Encoded, R>,
338
343
  mapFrom: (pm: Encoded) => Encoded,
339
- mapTo: (e: Encoded, etag: string | undefined) => PersistenceModelType<Encoded>
344
+ mapTo: (e: Encoded, etag: string | undefined) => PersistenceModelType<Encoded>,
345
+ idKey: IdKey
340
346
  ) => {
341
347
  type PM = PersistenceModelType<Encoded>
342
348
  function mapToPersistenceModel(
@@ -416,7 +422,7 @@ export function makeRepo<
416
422
  // we need to get the TypeLiteral, incase of class it's behind a transform...
417
423
  ? S.Union(..._.ast.types.map((_) =>
418
424
  (S.make(_._tag === "Transformation" ? _.from : _) as unknown as Schema<T, Encoded>)
419
- .pipe(S.pick("id"))
425
+ .pipe(S.pick(idKey as any))
420
426
  ))
421
427
  : _
422
428
  .ast
@@ -428,10 +434,10 @@ export function makeRepo<
428
434
  .from
429
435
  ) as unknown as Schema<T, Encoded>)
430
436
  .pipe(S
431
- .pick("id"))
437
+ .pick(idKey as any))
432
438
  : _
433
439
  .pipe(S
434
- .pick("id"))
440
+ .pick(idKey as any))
435
441
  )
436
442
  const encodeId = flow(S.encode(i), Effect.provide(rctx))
437
443
  function findEId(id: Encoded["id"]) {
@@ -444,16 +450,17 @@ export function makeRepo<
444
450
  })
445
451
  )
446
452
  }
447
- function findE(id: T["id"]) {
453
+ // TODO: deal with idKey <-> "id" in encoded
454
+ function findE(id: T[IdKey]) {
448
455
  return pipe(
449
- encodeId({ id }),
456
+ encodeId({ [idKey]: id } as any),
450
457
  Effect.orDie,
451
- Effect.map((_) => _.id),
458
+ Effect.map((_) => (_ as any).id),
452
459
  Effect.flatMap(findEId)
453
460
  )
454
461
  }
455
462
 
456
- function find(id: T["id"]) {
463
+ function find(id: T[IdKey]) {
457
464
  return Effect.flatMapOption(findE(id), (_) => Effect.orDie(decode(_)))
458
465
  }
459
466
 
@@ -605,7 +612,7 @@ export function makeRepo<
605
612
  )
606
613
  }) as any
607
614
 
608
- const r: Repository<T, Encoded, Evt, ItemType> = {
615
+ const r: Repository<T, Encoded, Evt, ItemType, IdKey> = {
609
616
  changeFeed,
610
617
  itemType: name,
611
618
  find,
@@ -626,7 +633,7 @@ export function makeRepo<
626
633
  Effect.flatMap(decMany),
627
634
  Effect.map((_) => _ as any[])
628
635
  ),
629
- find: (id: Encoded["id"]) => flatMapOption(findE(id), dec),
636
+ find: (id: T[IdKey]) => flatMapOption(findE(id), dec),
630
637
  // query: (q: any) => {
631
638
  // const a = Q.toFilter(q)
632
639
 
@@ -678,7 +685,7 @@ export function makeStore<
678
685
  ItemType extends string,
679
686
  R,
680
687
  E extends { id: string },
681
- T extends { id: unknown }
688
+ T
682
689
  >(
683
690
  name: ItemType,
684
691
  schema: S.Schema<T, E, R>,
@@ -736,11 +743,12 @@ export function makeStore<
736
743
  }
737
744
 
738
745
  export interface Repos<
739
- T extends { id: unknown },
746
+ T,
740
747
  Encoded extends { id: string },
741
748
  R,
742
749
  Evt,
743
- ItemType extends string
750
+ ItemType extends string,
751
+ IdKey extends keyof T
744
752
  > {
745
753
  make<RInitial = never, E = never, R2 = never>(
746
754
  args: [Evt] extends [never] ? {
@@ -756,7 +764,7 @@ export interface Repos<
756
764
  partitionValue?: (a: Encoded) => string
757
765
  }
758
766
  }
759
- ): Effect<Repository<T, Encoded, Evt, ItemType>, E, StoreMaker | ContextMapContainer | R | RInitial | R2>
767
+ ): Effect<Repository<T, Encoded, Evt, ItemType, IdKey>, E, StoreMaker | ContextMapContainer | R | RInitial | R2>
760
768
  makeWith<Out, RInitial = never, E = never, R2 = never>(
761
769
  args: [Evt] extends [never] ? {
762
770
  makeInitial?: Effect<readonly T[], E, RInitial>
@@ -771,20 +779,20 @@ export interface Repos<
771
779
  partitionValue?: (a: Encoded) => string
772
780
  }
773
781
  },
774
- f: (r: Repository<T, Encoded, Evt, ItemType>) => Out
782
+ f: (r: Repository<T, Encoded, Evt, ItemType, IdKey>) => Out
775
783
  ): Effect<Out, E, StoreMaker | ContextMapContainer | R | RInitial | R2>
776
784
  readonly Q: ReturnType<typeof Q.make<Encoded>>
777
- readonly type: Repository<T, Encoded, Evt, ItemType>
785
+ readonly type: Repository<T, Encoded, Evt, ItemType, IdKey>
778
786
  }
779
787
 
780
788
  export type GetRepoType<T> = T extends { type: infer R } ? R : never
781
789
 
782
- export interface RepoFunctions<T extends { id: unknown }, Encoded extends { id: string }, Evt, ItemType, Service> {
790
+ export interface RepoFunctions<T, Encoded extends { id: string }, Evt, ItemType, IdKey extends keyof T, Service> {
783
791
  itemType: ItemType
784
792
  T: T
785
793
  all: Effect<readonly T[], never, Service>
786
- find: (id: T["id"]) => Effect<Option<T>, never, Service>
787
- removeById: (id: T["id"]) => Effect<void, NotFoundError<ItemType>, Service>
794
+ find: (id: T[IdKey]) => Effect<Option<T>, never, Service>
795
+ removeById: (id: T[IdKey]) => Effect<void, NotFoundError<ItemType>, Service>
788
796
  saveAndPublish: (
789
797
  items: Iterable<T>,
790
798
  events?: Iterable<Evt>
@@ -794,7 +802,7 @@ export interface RepoFunctions<T extends { id: unknown }, Encoded extends { id:
794
802
  events?: Iterable<Evt>
795
803
  ) => Effect<void, never, Service>
796
804
  save: (...items: T[]) => Effect<void, InvalidStateError | OptimisticConcurrencyException, Service>
797
- get: (id: T["id"]) => Effect<T, NotFoundError<ItemType>, Service>
805
+ get: (id: T[IdKey]) => Effect<T, NotFoundError<ItemType>, Service>
798
806
 
799
807
  queryAndSavePure: {
800
808
  <A, E2, R2, T2 extends T>(
@@ -871,7 +879,7 @@ export interface RepoFunctions<T extends { id: unknown }, Encoded extends { id:
871
879
 
872
880
  byIdAndSaveWithPure: {
873
881
  <R, A, E, S2 extends T>(
874
- id: T["id"],
882
+ id: T[IdKey],
875
883
  pure: Effect<A, E, FixEnv<R, Evt, T, S2>>
876
884
  ): Effect<
877
885
  A,
@@ -954,29 +962,32 @@ export const RepositoryBaseImpl = <Service>() => {
954
962
  return <
955
963
  Evt = never
956
964
  >() =>
957
- <ItemType extends string, R, Encoded extends { id: string }, T extends { id: unknown }>(
965
+ <ItemType extends string, R, Encoded extends { id: string }, T, IdKey extends keyof T>(
958
966
  itemType: ItemType,
959
967
  schema: S.Schema<T, Encoded, R>,
968
+ idKey: IdKey,
960
969
  jitM?: (pm: Encoded) => Encoded
961
970
  ):
962
- & (abstract new() => RepositoryBaseC1<T, Encoded, Evt, ItemType>)
971
+ & (abstract new() => RepositoryBaseC1<T, Encoded, Evt, ItemType, IdKey>)
963
972
  & Context.Tag<Service, Service>
964
973
  & Repos<
965
974
  T,
966
975
  Encoded,
967
976
  R,
968
977
  Evt,
969
- ItemType
978
+ ItemType,
979
+ IdKey
970
980
  >
971
- & RepoFunctions<T, Encoded, Evt, ItemType, Service> =>
981
+ & RepoFunctions<T, Encoded, Evt, ItemType, IdKey, Service> =>
972
982
  {
973
983
  const mkRepo = makeRepo<Evt>()(
974
984
  itemType,
975
985
  schema,
976
986
  jitM ? (pm) => jitM(pm as unknown as Encoded) : (pm) => pm as any,
977
- (e, _etag) => ({ ...e, _etag })
987
+ (e, _etag) => ({ ...e, _etag }),
988
+ idKey
978
989
  )
979
- abstract class Cls extends RepositoryBaseC1<T, Encoded, Evt, ItemType> {
990
+ abstract class Cls extends RepositoryBaseC1<T, Encoded, Evt, ItemType, IdKey> {
980
991
  constructor() {
981
992
  super(itemType)
982
993
  }
@@ -984,7 +995,7 @@ export const RepositoryBaseImpl = <Service>() => {
984
995
  static readonly makeWith = ((a: any, b: any) => Effect.map(mkRepo.make(a), b)) as any
985
996
 
986
997
  static readonly Q = Q.make<Encoded>()
987
- static readonly type: Repository<T, Encoded, Evt, ItemType> = undefined as any
998
+ static readonly type: Repository<T, Encoded, Evt, ItemType, IdKey> = undefined as any
988
999
  }
989
1000
  const limit = Error.stackTraceLimit
990
1001
  Error.stackTraceLimit = 2
@@ -997,33 +1008,61 @@ export const RepositoryBaseImpl = <Service>() => {
997
1008
  }
998
1009
 
999
1010
  export const RepositoryDefaultImpl = <Service, Evt = never>() => {
1000
- return <ItemType extends string, R, Encoded extends { id: string }, T extends { id: unknown }>(
1011
+ const f: {
1012
+ <ItemType extends string, R, Encoded extends { id: string }, T, const IdKey extends keyof T>(
1013
+ itemType: ItemType,
1014
+ schema: S.Schema<T, Encoded, R>,
1015
+ idKey: IdKey,
1016
+ jitM?: (pm: Encoded) => Encoded
1017
+ ):
1018
+ & (abstract new(
1019
+ impl: Repository<T, Encoded, Evt, ItemType, IdKey>
1020
+ ) => RepositoryBaseC3<T, Encoded, Evt, ItemType, {}, IdKey>)
1021
+ & Context.Tag<Service, Service>
1022
+ & Repos<
1023
+ T,
1024
+ Encoded,
1025
+ R,
1026
+ Evt,
1027
+ ItemType,
1028
+ IdKey
1029
+ >
1030
+ & RepoFunctions<T, Encoded, Evt, ItemType, IdKey, Service>
1031
+ <ItemType extends string, R, Encoded extends { id: string }, T extends { id: unknown }>(
1032
+ itemType: ItemType,
1033
+ schema: S.Schema<T, Encoded, R>,
1034
+ jitM?: (pm: Encoded) => Encoded
1035
+ ):
1036
+ & (abstract new(
1037
+ impl: Repository<T, Encoded, Evt, ItemType, "id">
1038
+ ) => RepositoryBaseC3<T, Encoded, Evt, ItemType, {}, "id">)
1039
+ & Context.Tag<Service, Service>
1040
+ & Repos<
1041
+ T,
1042
+ Encoded,
1043
+ R,
1044
+ Evt,
1045
+ ItemType,
1046
+ "id"
1047
+ >
1048
+ & RepoFunctions<T, Encoded, Evt, ItemType, "id", Service>
1049
+ } = <ItemType extends string, R, Encoded extends { id: string }, T, const IdKey extends keyof T>(
1001
1050
  itemType: ItemType,
1002
1051
  schema: S.Schema<T, Encoded, R>,
1052
+ idKeyOrJitM?: IdKey | ((pm: Encoded) => Encoded),
1003
1053
  jitM?: (pm: Encoded) => Encoded
1004
- ):
1005
- & (abstract new(
1006
- impl: Repository<T, Encoded, Evt, ItemType>
1007
- ) => RepositoryBaseC3<T, Encoded, Evt, ItemType, {}>)
1008
- & Context.Tag<Service, Service>
1009
- & Repos<
1010
- T,
1011
- Encoded,
1012
- R,
1013
- Evt,
1014
- ItemType
1015
- >
1016
- & RepoFunctions<T, Encoded, Evt, ItemType, Service> =>
1017
- {
1054
+ ) => {
1055
+ if (!jitM && idKeyOrJitM !== undefined && typeof idKeyOrJitM === "function") jitM = idKeyOrJitM
1018
1056
  const mkRepo = makeRepo<Evt>()(
1019
1057
  itemType,
1020
1058
  schema,
1021
1059
  jitM ? (pm) => jitM(pm) : (pm) => pm,
1022
- (e, _etag) => ({ ...e, _etag })
1060
+ (e, _etag) => ({ ...e, _etag }),
1061
+ idKeyOrJitM ?? "id" as any
1023
1062
  )
1024
- abstract class Cls extends RepositoryBaseC3<T, Encoded, Evt, ItemType, {}> {
1063
+ abstract class Cls extends RepositoryBaseC3<T, Encoded, Evt, ItemType, {}, IdKey> {
1025
1064
  constructor(
1026
- impl: Repository<T, Encoded, Evt, ItemType>
1065
+ impl: Repository<T, Encoded, Evt, ItemType, IdKey>
1027
1066
  ) {
1028
1067
  super(itemType, impl)
1029
1068
  }
@@ -1032,7 +1071,7 @@ export const RepositoryDefaultImpl = <Service, Evt = never>() => {
1032
1071
 
1033
1072
  static readonly Q = Q.make<Encoded>()
1034
1073
 
1035
- static readonly type: Repository<T, Encoded, Evt, ItemType> = undefined as any
1074
+ static readonly type: Repository<T, Encoded, Evt, ItemType, IdKey> = undefined as any
1036
1075
  }
1037
1076
  const limit = Error.stackTraceLimit
1038
1077
  Error.stackTraceLimit = 2
@@ -1042,14 +1081,172 @@ export const RepositoryDefaultImpl = <Service, Evt = never>() => {
1042
1081
  Object.assign(Cls, makeRepoFunctions(Cls, itemType))
1043
1082
  ) as any // impl is missing, but its marked protected
1044
1083
  }
1084
+ return f
1045
1085
  }
1046
1086
 
1047
1087
  export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
1048
- return <
1088
+ const f: {
1089
+ <
1090
+ ItemType extends string,
1091
+ R,
1092
+ Encoded extends { id: string },
1093
+ T,
1094
+ IdKey extends keyof T,
1095
+ E = never,
1096
+ RInitial = never,
1097
+ R2 = never,
1098
+ Layers extends [Layer.Layer.Any, ...Layer.Layer.Any[]] = [Layer.Layer<never>],
1099
+ E1 = never,
1100
+ R1 = never,
1101
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
1102
+ Ext = {}
1103
+ >(
1104
+ itemType: ItemType,
1105
+ schema: S.Schema<T, Encoded, R>,
1106
+ options: [Evt] extends [never] ? {
1107
+ dependencies?: Layers
1108
+ idKey: IdKey
1109
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
1110
+ partitionValue?: (a: Encoded) => string
1111
+ }
1112
+ jitM?: (pm: Encoded) => Encoded
1113
+ options?: Effect<
1114
+ {
1115
+ makeInitial?: Effect<readonly T[], E, RInitial>
1116
+ ext?: Ext
1117
+ },
1118
+ E1,
1119
+ R1
1120
+ >
1121
+ }
1122
+ : {
1123
+ dependencies?: Layers
1124
+ idKey: IdKey
1125
+ jitM?: (pm: Encoded) => Encoded
1126
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
1127
+ partitionValue?: (a: Encoded) => string
1128
+ }
1129
+ options?: Effect<
1130
+ {
1131
+ publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<void, never, R2>
1132
+ makeInitial?: Effect<readonly T[], E, RInitial>
1133
+ ext?: Ext
1134
+ },
1135
+ E1,
1136
+ R1
1137
+ >
1138
+ }
1139
+ ):
1140
+ & (abstract new(
1141
+ impl: Repository<T, Encoded, Evt, ItemType, IdKey> & Ext
1142
+ ) => RepositoryBaseC3<T, Encoded, Evt, ItemType, Ext, IdKey>)
1143
+ & Context.Tag<Service, Service>
1144
+ & {
1145
+ Default: Layer.Layer<
1146
+ Service,
1147
+ E1 | Layer.Layer.Error<Layers[number]>,
1148
+ Exclude<
1149
+ R1 | R | StoreMaker | ContextMapContainer,
1150
+ { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]
1151
+ >
1152
+ >
1153
+ DefaultWithoutDependencies: Layer.Layer<
1154
+ Service,
1155
+ E1,
1156
+ R1 | R | StoreMaker | ContextMapContainer
1157
+ >
1158
+ }
1159
+ & Repos<
1160
+ T,
1161
+ Encoded,
1162
+ R,
1163
+ Evt,
1164
+ ItemType,
1165
+ IdKey
1166
+ >
1167
+ & RepoFunctions<T, Encoded, Evt, ItemType, IdKey, Service>
1168
+ <
1169
+ ItemType extends string,
1170
+ R,
1171
+ Encoded extends { id: string },
1172
+ T extends { id: unknown },
1173
+ E = never,
1174
+ RInitial = never,
1175
+ R2 = never,
1176
+ Layers extends [Layer.Layer.Any, ...Layer.Layer.Any[]] = [Layer.Layer<never>],
1177
+ E1 = never,
1178
+ R1 = never,
1179
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
1180
+ Ext = {}
1181
+ >(
1182
+ itemType: ItemType,
1183
+ schema: S.Schema<T, Encoded, R>,
1184
+ options: [Evt] extends [never] ? {
1185
+ dependencies?: Layers
1186
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
1187
+ partitionValue?: (a: Encoded) => string
1188
+ }
1189
+ jitM?: (pm: Encoded) => Encoded
1190
+ options?: Effect<
1191
+ {
1192
+ makeInitial?: Effect<readonly T[], E, RInitial>
1193
+ ext?: Ext
1194
+ },
1195
+ E1,
1196
+ R1
1197
+ >
1198
+ }
1199
+ : {
1200
+ dependencies?: Layers
1201
+ jitM?: (pm: Encoded) => Encoded
1202
+ config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
1203
+ partitionValue?: (a: Encoded) => string
1204
+ }
1205
+ options?: Effect<
1206
+ {
1207
+ publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<void, never, R2>
1208
+ makeInitial?: Effect<readonly T[], E, RInitial>
1209
+ ext?: Ext
1210
+ },
1211
+ E1,
1212
+ R1
1213
+ >
1214
+ }
1215
+ ):
1216
+ & (abstract new(
1217
+ impl: Repository<T, Encoded, Evt, ItemType, "id"> & Ext
1218
+ ) => RepositoryBaseC3<T, Encoded, Evt, ItemType, Ext, "id">)
1219
+ & Context.Tag<Service, Service>
1220
+ & {
1221
+ Default: Layer.Layer<
1222
+ Service,
1223
+ E1 | Layer.Layer.Error<Layers[number]>,
1224
+ Exclude<
1225
+ R1 | R | StoreMaker | ContextMapContainer,
1226
+ { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]
1227
+ >
1228
+ >
1229
+ DefaultWithoutDependencies: Layer.Layer<
1230
+ Service,
1231
+ E1,
1232
+ R1 | R | StoreMaker | ContextMapContainer
1233
+ >
1234
+ }
1235
+ & Repos<
1236
+ T,
1237
+ Encoded,
1238
+ R,
1239
+ Evt,
1240
+ ItemType,
1241
+ "id"
1242
+ >
1243
+ & RepoFunctions<T, Encoded, Evt, ItemType, "id", Service>
1244
+ } = <
1049
1245
  ItemType extends string,
1050
1246
  R,
1051
1247
  Encoded extends { id: string },
1052
- T extends { id: unknown },
1248
+ T,
1249
+ IdKey extends keyof T,
1053
1250
  E = never,
1054
1251
  RInitial = never,
1055
1252
  R2 = never,
@@ -1063,6 +1260,7 @@ export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
1063
1260
  schema: S.Schema<T, Encoded, R>,
1064
1261
  options: [Evt] extends [never] ? {
1065
1262
  dependencies?: Layers
1263
+ idKey?: IdKey
1066
1264
  config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
1067
1265
  partitionValue?: (a: Encoded) => string
1068
1266
  }
@@ -1078,6 +1276,7 @@ export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
1078
1276
  }
1079
1277
  : {
1080
1278
  dependencies?: Layers
1279
+ idKey?: IdKey
1081
1280
  jitM?: (pm: Encoded) => Encoded
1082
1281
  config?: Omit<StoreConfig<Encoded>, "partitionValue"> & {
1083
1282
  partitionValue?: (a: Encoded) => string
@@ -1092,40 +1291,19 @@ export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
1092
1291
  R1
1093
1292
  >
1094
1293
  }
1095
- ):
1096
- & (abstract new(
1097
- impl: Repository<T, Encoded, Evt, ItemType> & Ext
1098
- ) => RepositoryBaseC3<T, Encoded, Evt, ItemType, Ext>)
1099
- & Context.Tag<Service, Service>
1100
- & {
1101
- Default: Layer.Layer<
1102
- Service,
1103
- E1 | Layer.Layer.Error<Layers[number]>,
1104
- Exclude<
1105
- R1 | R | StoreMaker | ContextMapContainer,
1106
- { [k in keyof Layers]: Layer.Layer.Success<Layers[k]> }[number]
1107
- >
1108
- >
1109
- DefaultWithoutDependencies: Layer.Layer<
1110
- Service,
1111
- E1,
1112
- R1 | R | StoreMaker | ContextMapContainer
1113
- >
1114
- }
1115
- & Repos<
1294
+ ) => {
1295
+ let layerCache = undefined
1296
+ let layerCache2 = undefined
1297
+ abstract class Cls extends RepositoryBaseC3<
1116
1298
  T,
1117
1299
  Encoded,
1118
- R,
1119
1300
  Evt,
1120
- ItemType
1121
- >
1122
- & RepoFunctions<T, Encoded, Evt, ItemType, Service> =>
1123
- {
1124
- let layerCache = undefined
1125
- let layerCache2 = undefined
1126
- abstract class Cls extends RepositoryBaseC3<T, Encoded, Evt, ItemType, Ext> {
1301
+ ItemType,
1302
+ Ext,
1303
+ IdKey
1304
+ > {
1127
1305
  constructor(
1128
- impl: Repository<T, Encoded, Evt, ItemType> & Ext
1306
+ impl: Repository<T, Encoded, Evt, ItemType, IdKey> & Ext
1129
1307
  ) {
1130
1308
  super(itemType, impl)
1131
1309
  }
@@ -1139,7 +1317,8 @@ export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
1139
1317
  itemType,
1140
1318
  schema,
1141
1319
  options?.jitM ? (pm) => options.jitM!(pm) : (pm) => pm,
1142
- (e, _etag) => ({ ...e, _etag })
1320
+ (e, _etag) => ({ ...e, _etag }),
1321
+ options.idKey ?? "id" as any
1143
1322
  )
1144
1323
  const r = yield* mkRepo.make({ ...options, ...opts } as any)
1145
1324
  return Layer.succeed(self, new self(Object.assign(r, "ext" in opts ? opts.ext : {})))
@@ -1154,7 +1333,7 @@ export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
1154
1333
  .pipe(Layer.provide(options.dependencies as any))
1155
1334
  : self.DefaultWithoutDependencies
1156
1335
  }
1157
- static readonly type: Repository<T, Encoded, Evt, ItemType> = undefined as any
1336
+ static readonly type: Repository<T, Encoded, Evt, ItemType, IdKey> = undefined as any
1158
1337
  }
1159
1338
  const limit = Error.stackTraceLimit
1160
1339
  Error.stackTraceLimit = 2
@@ -1164,19 +1343,22 @@ export const RepositoryDefaultImpl2 = <Service, Evt = never>() => {
1164
1343
  Object.assign(Cls, makeRepoFunctions(Cls, itemType))
1165
1344
  ) as any // impl is missing, but its marked protected
1166
1345
  }
1346
+
1347
+ return f
1167
1348
  }
1168
1349
 
1169
1350
  // TODO: integrate with repo
1170
1351
  export const makeRequest = <
1171
1352
  ItemType extends string,
1172
- T extends { id: unknown },
1353
+ T,
1173
1354
  Encoded extends { id: string } & FieldValues,
1174
1355
  Evt,
1175
- Service
1176
- >(repo: Context.Tag<Service, Service> & RepoFunctions<T, Encoded, Evt, ItemType, Service>) => {
1356
+ Service,
1357
+ IdKey extends keyof T
1358
+ >(repo: Context.Tag<Service, Service> & RepoFunctions<T, Encoded, Evt, ItemType, IdKey, Service>, idKey: IdKey) => {
1177
1359
  type Req =
1178
1360
  & Request.Request<T, NotFoundError<ItemType>>
1179
- & { _tag: `Get${ItemType}`; id: T["id"] }
1361
+ & { _tag: `Get${ItemType}`; id: T[IdKey] }
1180
1362
  const _request = Request.tagged<Req>(`Get${repo.itemType}`)
1181
1363
 
1182
1364
  const requestResolver = RequestResolver
@@ -1189,7 +1371,7 @@ export const makeRequest = <
1189
1371
  Request.complete(
1190
1372
  r,
1191
1373
  Array
1192
- .findFirst(items, (_) => _.id === r.id)
1374
+ .findFirst(items, (_) => _[idKey] === r.id)
1193
1375
  .pipe(Option.match({
1194
1376
  onNone: () => Exit.fail(new NotFoundError({ type: repo.itemType, id: r.id })),
1195
1377
  onSome: Exit.succeed
@@ -1207,5 +1389,5 @@ export const makeRequest = <
1207
1389
  RequestResolver.contextFromServices(repo)
1208
1390
  )
1209
1391
 
1210
- return (id: T["id"]) => Effect.request(_request({ id }), requestResolver)
1392
+ return (id: T[IdKey]) => Effect.request(_request({ id }), requestResolver)
1211
1393
  }