@effect-app/infra 0.12.6 → 0.14.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 (161) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/_cjs/api/codec.cjs +2 -4
  3. package/_cjs/api/codec.cjs.map +1 -1
  4. package/_cjs/api/defaultErrorHandler.cjs +18 -21
  5. package/_cjs/api/defaultErrorHandler.cjs.map +1 -1
  6. package/_cjs/api/express/makeJsonSchema.cjs +4 -4
  7. package/_cjs/api/express/makeJsonSchema.cjs.map +1 -1
  8. package/_cjs/api/express/makeOpenApiSpecs.cjs +5 -7
  9. package/_cjs/api/express/makeOpenApiSpecs.cjs.map +1 -1
  10. package/_cjs/api/express/schema/requestHandler.cjs +49 -49
  11. package/_cjs/api/express/schema/requestHandler.cjs.map +1 -1
  12. package/_cjs/api/express/schema/routing.cjs +22 -22
  13. package/_cjs/api/express/schema/routing.cjs.map +1 -1
  14. package/_cjs/api/reportError.cjs +6 -17
  15. package/_cjs/api/reportError.cjs.map +1 -1
  16. package/_cjs/api/routing.cjs +63 -63
  17. package/_cjs/api/routing.cjs.map +1 -1
  18. package/_cjs/api/setupRequest.cjs +2 -4
  19. package/_cjs/api/setupRequest.cjs.map +1 -1
  20. package/_cjs/api/writeDocs.cjs +6 -8
  21. package/_cjs/api/writeDocs.cjs.map +1 -1
  22. package/_cjs/errorReporter.cjs +11 -13
  23. package/_cjs/errorReporter.cjs.map +1 -1
  24. package/_cjs/errors.cjs +1 -1
  25. package/_cjs/errors.cjs.map +1 -1
  26. package/_cjs/filter.cjs.map +1 -1
  27. package/_cjs/instrument.cjs +1 -3
  28. package/_cjs/instrument.cjs.map +1 -1
  29. package/_cjs/rateLimit.cjs +6 -8
  30. package/_cjs/rateLimit.cjs.map +1 -1
  31. package/_cjs/services/Emailer/Sendgrid.cjs +12 -18
  32. package/_cjs/services/Emailer/Sendgrid.cjs.map +1 -1
  33. package/_cjs/services/Emailer/fake.cjs +4 -7
  34. package/_cjs/services/Emailer/fake.cjs.map +1 -1
  35. package/_cjs/services/Operations/live.cjs +23 -26
  36. package/_cjs/services/Operations/live.cjs.map +1 -1
  37. package/_cjs/services/Operations/service.cjs +3 -5
  38. package/_cjs/services/Operations/service.cjs.map +1 -1
  39. package/_cjs/services/Repository.cjs +44 -29
  40. package/_cjs/services/Repository.cjs.map +1 -1
  41. package/_cjs/services/Store/Cosmos.cjs +56 -60
  42. package/_cjs/services/Store/Cosmos.cjs.map +1 -1
  43. package/_cjs/services/Store/Disk.cjs +15 -16
  44. package/_cjs/services/Store/Disk.cjs.map +1 -1
  45. package/_cjs/services/Store/Memory.cjs +14 -16
  46. package/_cjs/services/Store/Memory.cjs.map +1 -1
  47. package/_cjs/services/Store/Redis.cjs +22 -23
  48. package/_cjs/services/Store/Redis.cjs.map +1 -1
  49. package/_cjs/services/Store/codeFilter.test.cjs +1 -1
  50. package/_cjs/services/Store/codeFilter.test.cjs.map +1 -1
  51. package/_cjs/services/Store/index.cjs +7 -7
  52. package/_cjs/services/Store/index.cjs.map +1 -1
  53. package/_cjs/services/Store/service.cjs +2 -4
  54. package/_cjs/services/Store/service.cjs.map +1 -1
  55. package/_cjs/services/Store/utils.cjs +16 -17
  56. package/_cjs/services/Store/utils.cjs.map +1 -1
  57. package/_cjs/services/simpledb/cosmosdb.cjs +23 -25
  58. package/_cjs/services/simpledb/cosmosdb.cjs.map +1 -1
  59. package/_cjs/services/simpledb/diskdb.cjs +20 -21
  60. package/_cjs/services/simpledb/diskdb.cjs.map +1 -1
  61. package/_cjs/services/simpledb/memdb.cjs +10 -10
  62. package/_cjs/services/simpledb/memdb.cjs.map +1 -1
  63. package/_cjs/services/simpledb/mongodb.cjs +18 -18
  64. package/_cjs/services/simpledb/mongodb.cjs.map +1 -1
  65. package/_cjs/services/simpledb/redisdb.cjs +23 -23
  66. package/_cjs/services/simpledb/redisdb.cjs.map +1 -1
  67. package/_cjs/services/simpledb/shared.cjs +4 -6
  68. package/_cjs/services/simpledb/shared.cjs.map +1 -1
  69. package/_cjs/services/simpledb/simpledb.cjs +16 -15
  70. package/_cjs/services/simpledb/simpledb.cjs.map +1 -1
  71. package/_src/api/defaultErrorHandler.ts +3 -5
  72. package/_src/api/routing.ts +12 -13
  73. package/_src/errors.ts +1 -1
  74. package/_src/filter/types/path/common.ts +9 -9
  75. package/_src/filter/types/path/eager.ts +12 -12
  76. package/_src/filter/types/utils.ts +1 -1
  77. package/_src/filter.ts +7 -11
  78. package/_src/services/Repository.ts +111 -50
  79. package/_src/services/Store/Cosmos.ts +14 -14
  80. package/_src/services/Store/codeFilter.test.ts +37 -30
  81. package/_src/services/Store/utils.ts +34 -34
  82. package/_src/services/simpledb/memdb.ts +1 -1
  83. package/_src/services/simpledb/simpledb.ts +5 -6
  84. package/dist/RequestContext.d.ts +12 -12
  85. package/dist/api/codec.js +3 -5
  86. package/dist/api/defaultErrorHandler.d.ts.map +1 -1
  87. package/dist/api/defaultErrorHandler.js +22 -23
  88. package/dist/api/express/makeJsonSchema.js +3 -5
  89. package/dist/api/express/makeOpenApiSpecs.js +5 -7
  90. package/dist/api/express/schema/requestHandler.d.ts +5 -5
  91. package/dist/api/express/schema/requestHandler.js +45 -45
  92. package/dist/api/express/schema/routing.js +21 -23
  93. package/dist/api/reportError.js +6 -18
  94. package/dist/api/routing.d.ts.map +1 -1
  95. package/dist/api/routing.js +60 -60
  96. package/dist/api/setupRequest.js +3 -5
  97. package/dist/api/writeDocs.js +7 -9
  98. package/dist/errorReporter.js +10 -12
  99. package/dist/errors.js +2 -2
  100. package/dist/filter/types/path/common.d.ts.map +1 -1
  101. package/dist/filter/types/path/eager.d.ts.map +1 -1
  102. package/dist/filter/types/utils.d.ts.map +1 -1
  103. package/dist/filter.d.ts.map +1 -1
  104. package/dist/filter.js +2 -2
  105. package/dist/instrument.js +2 -4
  106. package/dist/rateLimit.js +7 -9
  107. package/dist/services/Emailer/Sendgrid.js +15 -22
  108. package/dist/services/Emailer/fake.js +5 -8
  109. package/dist/services/Emailer/service.d.ts +1 -1
  110. package/dist/services/Operations/live.js +24 -27
  111. package/dist/services/Operations/service.js +4 -6
  112. package/dist/services/Repository.d.ts +26 -8
  113. package/dist/services/Repository.d.ts.map +1 -1
  114. package/dist/services/Repository.js +41 -25
  115. package/dist/services/Store/Cosmos.d.ts +1 -1
  116. package/dist/services/Store/Cosmos.js +66 -68
  117. package/dist/services/Store/Disk.js +16 -19
  118. package/dist/services/Store/Memory.d.ts +1 -1
  119. package/dist/services/Store/Memory.js +16 -18
  120. package/dist/services/Store/Redis.d.ts +1 -1
  121. package/dist/services/Store/Redis.js +21 -24
  122. package/dist/services/Store/codeFilter.test.d.ts.map +1 -1
  123. package/dist/services/Store/index.js +6 -8
  124. package/dist/services/Store/service.d.ts +1 -1
  125. package/dist/services/Store/service.js +3 -5
  126. package/dist/services/Store/utils.d.ts +2 -2
  127. package/dist/services/Store/utils.d.ts.map +1 -1
  128. package/dist/services/Store/utils.js +45 -46
  129. package/dist/services/simpledb/cosmosdb.d.ts +2 -2
  130. package/dist/services/simpledb/cosmosdb.js +23 -25
  131. package/dist/services/simpledb/diskdb.d.ts +2 -2
  132. package/dist/services/simpledb/diskdb.js +18 -18
  133. package/dist/services/simpledb/memdb.d.ts +3 -3
  134. package/dist/services/simpledb/memdb.js +12 -11
  135. package/dist/services/simpledb/mongodb.d.ts +2 -2
  136. package/dist/services/simpledb/mongodb.js +18 -18
  137. package/dist/services/simpledb/redisdb.d.ts +8 -8
  138. package/dist/services/simpledb/redisdb.js +21 -21
  139. package/dist/services/simpledb/shared.d.ts +9 -9
  140. package/dist/services/simpledb/shared.js +5 -7
  141. package/dist/services/simpledb/simpledb.d.ts +1 -1
  142. package/dist/services/simpledb/simpledb.d.ts.map +1 -1
  143. package/dist/services/simpledb/simpledb.js +19 -17
  144. package/package.json +11 -11
  145. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-314902b6271c341511f7398a50469024 +0 -0
  146. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-3f072cc7afa09b6adaead0527ab9df83 +0 -0
  147. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-74c3c295c110fc861b6a4c673afc3e24 +0 -0
  148. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-bf6dae8cb9ea9740ceb39aefaf12716c +0 -0
  149. package/.jest-cache/haste-map-369fa5ca2164cc35b19159bd76147276-e7a7ff05756c055cb63be97ba8537525-cf9d1486029526079a5f68f2041dea02 +0 -0
  150. package/.jest-cache/haste-map-4ca41cc04e60c616a19cbb483cbf487b-e2f1f4b6d87214e3c49442fed31f310c-b4710ed9fb3d0757c4bf23045c585670 +0 -0
  151. package/.jest-cache/haste-map-4ca41cc04e60c616a19cbb483cbf487b-e2f1f4b6d87214e3c49442fed31f310c-ee17e5395bb1b7b36a4e2e22a6ae1449 +0 -0
  152. package/.jest-cache/haste-map-7dc16d7fae8c072843ed1c69eae73100-a8a4225b317477b49bca31f54559afb3-c16136699bb7f463be85273162b447c3 +0 -0
  153. package/.jest-cache/haste-map-9aa1e395a82e108eb49698982c574272-e2f1f4b6d87214e3c49442fed31f310c-f7435f46fc41ac5a13d06a49cae9a650 +0 -0
  154. package/.jest-cache/haste-map-9d206b45d610536c9ec65eec263c6964-a8a4225b317477b49bca31f54559afb3-3510506a330b44f1ae629033aac8fbb3 +0 -0
  155. package/.jest-cache/haste-map-a00ab30d0d656f9d3990958a54b9ccfd-87603b0fc921b26b622a5859b4c92bed-17b550b450b18840c25861aa6e835f0c +0 -0
  156. package/.jest-cache/haste-map-a00ab30d0d656f9d3990958a54b9ccfd-87603b0fc921b26b622a5859b4c92bed-4dc31290b1efc98335eb4c89167d75c3 +0 -0
  157. package/.jest-cache/haste-map-ab843cb0ffbadfd0deea4adb182c7ecd-87603b0fc921b26b622a5859b4c92bed-997106edf4bbc31567a378146180e45e +0 -0
  158. package/.jest-cache/haste-map-ab843cb0ffbadfd0deea4adb182c7ecd-87603b0fc921b26b622a5859b4c92bed-f0cd25414f9ed16c446940ca3aa23c1b +0 -0
  159. package/.jest-cache/haste-map-cf17f2edf0e949eebfdfca561816457c-e7a7ff05756c055cb63be97ba8537525-2cac07d09e6384e2d37c49714edad0ba +0 -0
  160. package/.jest-cache/haste-map-cf17f2edf0e949eebfdfca561816457c-e7a7ff05756c055cb63be97ba8537525-d7967c2976c5feac7161c964f0aa442f +0 -0
  161. package/.jest-cache/haste-map-fb1a173276d25bbff02f815600059283-938122bdc1c8836874b6585d7acb2e99-f705929cca05ce95ceaa6d520b560ce8 +0 -0
@@ -1,22 +1,28 @@
1
1
  // Update = Must return updated items
2
2
  // Modify = Must `set` updated items, and can return anything.
3
+ import type { FixEnv, PureLogT } from "@effect-app/prelude/_ext/Pure"
4
+ import { Pure } from "@effect-app/prelude/_ext/Pure"
5
+ import type { ParserEnv } from "@effect-app/schema/custom/Parser"
3
6
  import type { InvalidStateError, OptimisticConcurrencyException } from "../errors.js"
4
7
  import { NotFoundError } from "../errors.js"
5
8
  import type { RequestContext } from "../RequestContext.js"
6
- import { ContextMap} from "../services/Store.js";
9
+ import { ContextMap } from "../services/Store.js"
7
10
  import type { Filter } from "../services/Store.js"
8
- import type { FixEnv, PureLogT} from "@effect-app/prelude/_ext/Pure";
9
- import { Pure } from "@effect-app/prelude/_ext/Pure"
10
- import type { ParserEnv } from "@effect-app/schema/custom/Parser"
11
11
 
12
12
  /**
13
13
  * @tsplus type Repository
14
14
  */
15
- export interface Repository<T extends { id: Id }, PM extends { id: string }, Evt, Id extends string, ItemType extends string> {
15
+ export interface Repository<
16
+ T extends { id: Id },
17
+ PM extends { id: string },
18
+ Evt,
19
+ Id extends string,
20
+ ItemType extends string
21
+ > {
16
22
  itemType: ItemType
17
23
  find: (id: Id) => Effect<ContextMap | RequestContext, never, Opt<T>>
18
24
  all: Effect<ContextMap, never, Chunk<T>>
19
- save: (
25
+ saveAndPublish: (
20
26
  items: Iterable<T>,
21
27
  events?: Iterable<Evt>
22
28
  ) => Effect<ContextMap | RequestContext, InvalidStateError | OptimisticConcurrencyException, void>
@@ -24,18 +30,24 @@ export interface Repository<T extends { id: Id }, PM extends { id: string }, Evt
24
30
  mapReverse: (
25
31
  pm: PM,
26
32
  setEtag: (id: string, eTag: string | undefined) => void
27
- ) => unknown, // TODO
28
- parse: (a: unknown, env?: ParserEnv | undefined) => T,
29
- all: Effect<never, never, Chunk<PM>>,
30
- filter: (filter: Filter<PM>, cursor?: { limit?: number, skip?: number}) => Effect<never, never, Chunk<PM>>
33
+ ) => unknown // TODO
34
+ parse: (a: unknown, env?: ParserEnv | undefined) => T
35
+ all: Effect<never, never, Chunk<PM>>
36
+ filter: (filter: Filter<PM>, cursor?: { limit?: number; skip?: number }) => Effect<never, never, Chunk<PM>>
31
37
  }
32
38
  }
33
39
 
34
40
  export interface PureDSL<S, S2, W> {
35
- get: ReturnType<typeof Pure.get<S>>, set: typeof Pure.set<S2>, log: (...w: W[]) => PureLogT<W>
41
+ get: ReturnType<typeof Pure.get<S>>
42
+ set: typeof Pure.set<S2>
43
+ log: (...w: W[]) => PureLogT<W>
36
44
  }
37
45
 
38
- export const AnyPureDSL: PureDSL<any, any, any> = { get: Pure.get(), set: Pure.set, log: (...evt: any[]) => Pure.logMany(evt) }
46
+ export const AnyPureDSL: PureDSL<any, any, any> = {
47
+ get: Pure.get(),
48
+ set: Pure.set,
49
+ log: (...evt: any[]) => Pure.logMany(evt)
50
+ }
39
51
 
40
52
  /**
41
53
  * @tsplus fluent Repository get
@@ -61,7 +73,7 @@ export function filter<
61
73
  T extends { id: Id },
62
74
  PM extends { id: string },
63
75
  Evt,
64
- ItemType extends string,
76
+ ItemType extends string
65
77
  >(self: Repository<T, PM, Evt, Id, ItemType>, filter: Predicate<T>) {
66
78
  return self.all.map(_ => _.filter(filter))
67
79
  }
@@ -75,12 +87,11 @@ export function filterAll<
75
87
  PM extends { id: string },
76
88
  Evt,
77
89
  ItemType extends string,
78
- S extends T,
90
+ S extends T
79
91
  >(self: Repository<T, PM, Evt, Id, ItemType>, map: (items: Chunk<T>) => Chunk<S>) {
80
92
  return self.all.map(map)
81
93
  }
82
94
 
83
-
84
95
  /**
85
96
  * @tsplus fluent Repository collect
86
97
  */
@@ -90,7 +101,7 @@ export function collect<
90
101
  PM extends { id: string },
91
102
  Evt,
92
103
  ItemType extends string,
93
- S extends T,
104
+ S extends T
94
105
  >(self: Repository<T, PM, Evt, Id, ItemType>, collect: (item: T) => Opt<S>) {
95
106
  return self.all.map(_ => _.filterMap(collect))
96
107
  }
@@ -127,7 +138,7 @@ export function projectEffect<
127
138
  ) {
128
139
  // TODO: a projection that gets sent to the db instead.
129
140
  return map.flatMap(f =>
130
- (f.filter ? self.utils.filter(f.filter, { limit: f.limit, skip: f.skip}) : self.utils.all)
141
+ (f.filter ? self.utils.filter(f.filter, { limit: f.limit, skip: f.skip }) : self.utils.all)
131
142
  .map(_ => _.filterMap(f.collect))
132
143
  )
133
144
  }
@@ -142,7 +153,7 @@ export function project<
142
153
  PM extends { id: string },
143
154
  Evt,
144
155
  ItemType extends string,
145
- S,
156
+ S
146
157
  >(
147
158
  self: Repository<T, PM, Evt, Id, ItemType>,
148
159
  map: { filter?: Filter<PM>; collect: (t: PM) => Opt<S>; limit?: number; skip?: number }
@@ -150,7 +161,6 @@ export function project<
150
161
  return self.projectEffect(Effect(map))
151
162
  }
152
163
 
153
-
154
164
  /**
155
165
  * @tsplus fluent Repository queryEffect
156
166
  */
@@ -162,14 +172,14 @@ export function queryEffect<
162
172
  ItemType extends string,
163
173
  R,
164
174
  E,
165
- S,
175
+ S
166
176
  >(
167
177
  self: Repository<T, PM, Evt, Id, ItemType>,
168
178
  // TODO: think about collectPM, collectE, and collect(Parsed)
169
179
  map: Effect<R, E, { filter?: Filter<PM>; collect: (t: T) => Opt<S>; limit?: number; skip?: number }>
170
180
  ) {
171
181
  return map.flatMap(f =>
172
- (f.filter ? self.utils.filter(f.filter, { limit: f.limit, skip: f.skip}) : self.utils.all)
182
+ (f.filter ? self.utils.filter(f.filter, { limit: f.limit, skip: f.skip }) : self.utils.all)
173
183
  .flatMap(items =>
174
184
  Do($ => {
175
185
  const { set } = $(Effect.service(ContextMap))
@@ -192,7 +202,7 @@ export function queryOneEffect<
192
202
  ItemType extends string,
193
203
  R,
194
204
  E,
195
- S,
205
+ S
196
206
  >(
197
207
  self: Repository<T, PM, Evt, Id, ItemType>,
198
208
  // TODO: think about collectPM, collectE, and collect(Parsed)
@@ -207,7 +217,11 @@ export function queryOneEffect<
207
217
  })
208
218
  )
209
219
  .map(_ => _.map(_ => self.utils.parse(_)))
210
- .flatMap(_ => _.filterMap(f.collect).toNonEmptyArray.encaseInEffect(() => new NotFoundError(self.itemType, JSON.stringify(f.filter))).map(_ => _[0]))
220
+ .flatMap(_ =>
221
+ _.filterMap(f.collect).toNonEmptyArray.encaseInEffect(() =>
222
+ new NotFoundError(self.itemType, JSON.stringify(f.filter))
223
+ ).map(_ => _[0])
224
+ )
211
225
  )
212
226
  }
213
227
 
@@ -220,7 +234,7 @@ export function query<
220
234
  PM extends { id: string },
221
235
  Evt,
222
236
  ItemType extends string,
223
- S,
237
+ S
224
238
  >(
225
239
  self: Repository<T, PM, Evt, Id, ItemType>,
226
240
  // TODO: think about collectPM, collectE, and collect(Parsed)
@@ -238,7 +252,7 @@ export function queryOne<
238
252
  PM extends { id: string },
239
253
  Evt,
240
254
  ItemType extends string,
241
- S,
255
+ S
242
256
  >(
243
257
  self: Repository<T, PM, Evt, Id, ItemType>,
244
258
  // TODO: think about collectPM, collectE, and collect(Parsed)
@@ -258,7 +272,7 @@ export function queryAndSavePureEffect<
258
272
  ItemType extends string,
259
273
  R,
260
274
  E,
261
- S extends T = T,
275
+ S extends T = T
262
276
  >(
263
277
  self: Repository<T, PM, Evt, Id, ItemType>,
264
278
  // TODO: think about collectPM, collectE, and collect(Parsed)
@@ -278,7 +292,7 @@ export function queryAndSavePure<
278
292
  PM extends { id: string },
279
293
  Evt,
280
294
  ItemType extends string,
281
- S extends T = T,
295
+ S extends T = T
282
296
  >(
283
297
  self: Repository<T, PM, Evt, Id, ItemType>,
284
298
  // TODO: think about collectPM, collectE, and collect(Parsed)
@@ -298,7 +312,7 @@ export function saveManyWithPure<
298
312
  ItemType extends string
299
313
  >(self: Repository<T, PM, Evt, Id, ItemType>) {
300
314
  return <R, A, E, S1 extends T, S2 extends T>(pure: Effect<FixEnv<R, Evt, Chunk<S1>, Iterable<S2>>, E, A>) =>
301
- (items: Iterable<S1>) => saveManyWithPure_(self, items, pure)
315
+ (items: Iterable<S1>) => saveManyWithPure_(self, items, pure)
302
316
  }
303
317
 
304
318
  /**
@@ -311,7 +325,8 @@ export function byIdAndSaveWithPure<
311
325
  Evt,
312
326
  ItemType extends string
313
327
  >(self: Repository<T, PM, Evt, Id, ItemType>, id: Id) {
314
- return <R, A, E, S2 extends T>(pure: Effect<FixEnv<R, Evt, T, S2>, E, A>) => get(self, id).flatMap(item => saveWithPure_(self, item, pure))
328
+ return <R, A, E, S2 extends T>(pure: Effect<FixEnv<R, Evt, T, S2>, E, A>) =>
329
+ get(self, id).flatMap(item => saveWithPure_(self, item, pure))
315
330
  }
316
331
 
317
332
  /**
@@ -323,9 +338,12 @@ export function handleByIdAndSaveWithPure<
323
338
  T extends { id: Id },
324
339
  PM extends { id: string },
325
340
  Evt,
326
- ItemType extends string,
341
+ ItemType extends string
327
342
  >(self: Repository<T, PM, Evt, Id, ItemType>) {
328
- return <Req extends { id: Id }, Context, R, A, E, S2 extends T>(pure: (req: Req, ctx: Context) => Effect<FixEnv<R, Evt, T, S2>, E, A>) => (req: Req, ctx: Context) => byIdAndSaveWithPure(self, req.id)(pure(req, ctx))
343
+ return <Req extends { id: Id }, Context, R, A, E, S2 extends T>(
344
+ pure: (req: Req, ctx: Context) => Effect<FixEnv<R, Evt, T, S2>, E, A>
345
+ ) =>
346
+ (req: Req, ctx: Context) => byIdAndSaveWithPure(self, req.id)(pure(req, ctx))
329
347
  }
330
348
 
331
349
  /**
@@ -375,7 +393,7 @@ export function saveWithPure_<
375
393
  return saveAllWithEffectInt(
376
394
  self,
377
395
  pure.runTerm(item)
378
- .map(([item, events, a]) => [[item], events, a])
396
+ .map(([item, events, a]) => [[item], events, a])
379
397
  )
380
398
  }
381
399
 
@@ -396,7 +414,7 @@ function saveAllWithEffectInt<
396
414
  return gen
397
415
  .flatMap(
398
416
  ([items, events, a]) =>
399
- self.save(items, events)
417
+ self.saveAndPublish(items, events)
400
418
  .map(() => a)
401
419
  )
402
420
  }
@@ -404,16 +422,21 @@ function saveAllWithEffectInt<
404
422
  const anyDSL = makeDSL<any, any, any>()
405
423
 
406
424
  export type AllDSL<T, Evt> =
407
- (<R, A, E, S1 extends T, S2 extends T>(pure: (dsl: PureDSL<Chunk<S1>, Iterable<S2>, Evt>) => Effect<R, E, A>) => Effect<FixEnv<R, Evt, Chunk<S1>, Iterable<S2>>, E, A>)
408
- & AllDSLExt<T, Evt>
425
+ & (<R, A, E, S1 extends T, S2 extends T>(
426
+ pure: (dsl: PureDSL<Chunk<S1>, Iterable<S2>, Evt>) => Effect<R, E, A>
427
+ ) => Effect<FixEnv<R, Evt, Chunk<S1>, Iterable<S2>>, E, A>)
428
+ & AllDSLExt<T, Evt>
409
429
 
410
-
411
430
  /**
412
431
  * @tsplus type DSLExt
413
432
  */
414
- export interface AllDSLExt<T, Evt> {
415
- modify: <R, E, A, S1 extends T, S2 extends T>(pure: (items: Chunk<S1>, dsl: PureDSL<Chunk<S1>, Iterable<S2>, Evt>) => Effect<R, E, A>) => Effect<FixEnv<R, Evt, Chunk<S1>, Iterable<S2>>, E, A>;
416
- update: <R, E, S1 extends T, S2 extends T>(pure: (items: Chunk<S1>, log: (...evt: Evt[]) => PureLogT<Evt>) => Effect<R, E, Iterable<S2>>) => Effect<FixEnv<R, Evt, Chunk<S1>, Iterable<S2>>, E, Iterable<S2>>;
433
+ export interface AllDSLExt<T, Evt> {
434
+ modify: <R, E, A, S1 extends T, S2 extends T>(
435
+ pure: (items: Chunk<S1>, dsl: PureDSL<Chunk<S1>, Iterable<S2>, Evt>) => Effect<R, E, A>
436
+ ) => Effect<FixEnv<R, Evt, Chunk<S1>, Iterable<S2>>, E, A>
437
+ update: <R, E, S1 extends T, S2 extends T>(
438
+ pure: (items: Chunk<S1>, log: (...evt: Evt[]) => PureLogT<Evt>) => Effect<R, E, Iterable<S2>>
439
+ ) => Effect<FixEnv<R, Evt, Chunk<S1>, Iterable<S2>>, E, Iterable<S2>>
417
440
  }
418
441
 
419
442
  export function makeAllDSL<T, Evt>() {
@@ -422,16 +445,21 @@ export function makeAllDSL<T, Evt>() {
422
445
  }
423
446
 
424
447
  export type OneDSL<T, Evt> =
425
- (<R, A, E, S1 extends T, S2 extends T>(pure: (dsl: PureDSL<S1, S2, Evt>) => Effect<FixEnv<R, Evt, S1, S2>, E, A>) => Effect<FixEnv<R, Evt, S1, S2>, E, A>)
426
- & OneDSLExt<T, Evt>
427
-
448
+ & (<R, A, E, S1 extends T, S2 extends T>(
449
+ pure: (dsl: PureDSL<S1, S2, Evt>) => Effect<FixEnv<R, Evt, S1, S2>, E, A>
450
+ ) => Effect<FixEnv<R, Evt, S1, S2>, E, A>)
451
+ & OneDSLExt<T, Evt>
428
452
 
429
453
  /**
430
454
  * @tsplus type DSLExt
431
455
  */
432
456
  export interface OneDSLExt<T, Evt> {
433
- modify: <R, E, A, S1 extends T, S2 extends T>(pure: (items: S1, dsl: PureDSL<S1, S2, Evt>) => Effect<FixEnv<R, Evt, S1, S2>, E, A>) => Effect<FixEnv<R, Evt, S1, S2> | PureEnvEnv<Evt, S1, S1>, E, A>;
434
- update: <R, E, S1 extends T, S2 extends T>(pure: (items: S1, log: (...evt: Evt[]) => PureLogT<Evt>) => Effect<FixEnv<R, Evt, S1, S2>, E, S2>) => Effect<FixEnv<R, Evt, S1, S2>, E, S2>;
457
+ modify: <R, E, A, S1 extends T, S2 extends T>(
458
+ pure: (items: S1, dsl: PureDSL<S1, S2, Evt>) => Effect<FixEnv<R, Evt, S1, S2>, E, A>
459
+ ) => Effect<FixEnv<R, Evt, S1, S2> | PureEnvEnv<Evt, S1, S1>, E, A>
460
+ update: <R, E, S1 extends T, S2 extends T>(
461
+ pure: (items: S1, log: (...evt: Evt[]) => PureLogT<Evt>) => Effect<FixEnv<R, Evt, S1, S2>, E, S2>
462
+ ) => Effect<FixEnv<R, Evt, S1, S2>, E, S2>
435
463
  }
436
464
 
437
465
  /**
@@ -444,11 +472,14 @@ export function updateWithOne<T, Evt, S1 extends T, S2 extends T>(self: OneDSL<T
444
472
  /**
445
473
  * @tsplus fluent DSLExt updateWith
446
474
  */
447
- export function updateWith<T, Evt, S1 extends T, S2 extends T>(self: AllDSL<T, Evt>, upd: (item: Chunk<S1>) => Iterable<S2>) {
475
+ export function updateWith<T, Evt, S1 extends T, S2 extends T>(
476
+ self: AllDSL<T, Evt>,
477
+ upd: (item: Chunk<S1>) => Iterable<S2>
478
+ ) {
448
479
  return self.update((_: Chunk<S1>) => Effect(upd(_)))
449
480
  }
450
481
 
451
- export function makeOneDSL<T, Evt>(): OneDSL<T, Evt> {
482
+ export function makeOneDSL<T, Evt>(): OneDSL<T, Evt> {
452
483
  return anyDSL
453
484
  }
454
485
 
@@ -491,15 +522,15 @@ export function makeDSL<S1, S2, Evt>() {
491
522
  }
492
523
 
493
524
  return Object.assign(
494
- withDSL, {
525
+ withDSL,
526
+ {
495
527
  modify,
496
- update,
528
+ update
497
529
  }
498
530
  )
499
531
  }
500
532
 
501
- export interface DSLExt<S1, S2, Evt> extends ReturnType<typeof makeDSL<S1, S2, Evt>> { }
502
-
533
+ export interface DSLExt<S1, S2, Evt> extends ReturnType<typeof makeDSL<S1, S2, Evt>> {}
503
534
 
504
535
  export function ifAny<T, R, E, A>(fn: (items: NonEmptyReadonlyArray<T>) => Effect<R, E, A>) {
505
536
  return (items: Iterable<T>) => Effect(items.toNonEmptyArray).flatMapOpt(fn)
@@ -511,3 +542,33 @@ export function ifAny<T, R, E, A>(fn: (items: NonEmptyReadonlyArray<T>) => Effec
511
542
  export function ifAny_<T, R, E, A>(items: Iterable<T>, fn: (items: NonEmptyReadonlyArray<T>) => Effect<R, E, A>) {
512
543
  return Effect(items.toNonEmptyArray).flatMapOpt(fn)
513
544
  }
545
+
546
+ /**
547
+ * @tsplus getter Repository save
548
+ */
549
+ export function save<
550
+ Id extends string,
551
+ T extends { id: Id },
552
+ PM extends { id: string },
553
+ Evt,
554
+ ItemType extends string
555
+ >(
556
+ self: Repository<T, PM, Evt, Id, ItemType>
557
+ ) {
558
+ return (...items: NonEmptyArray<T>) => self.saveAndPublish(items)
559
+ }
560
+
561
+ /**
562
+ * @tsplus getter Repository saveWithEvents
563
+ */
564
+ export function saveWithEvents<
565
+ Id extends string,
566
+ T extends { id: Id },
567
+ PM extends { id: string },
568
+ Evt,
569
+ ItemType extends string
570
+ >(
571
+ self: Repository<T, PM, Evt, Id, ItemType>
572
+ ) {
573
+ return (events: Iterable<Evt>) => (...items: NonEmptyArray<T>) => self.saveAndPublish(items, events)
574
+ }
@@ -237,23 +237,23 @@ export function makeCosmosStore({ prefix }: StorageConfig) {
237
237
  const skip = cursor?.skip
238
238
  const limit = cursor?.limit
239
239
  return (filter.type === "join_find"
240
- ? // This is a problem if one of the multiple joined arrays can be empty!
240
+ // This is a problem if one of the multiple joined arrays can be empty!
241
241
  // https://stackoverflow.com/questions/60320780/azure-cosmosdb-sql-join-not-returning-results-when-the-child-contains-empty-arra
242
242
  // so we use multiple queries instead.
243
- filter.keys
244
- .forEachEffect(k =>
245
- Effect(() => buildFindJoinCosmosQuery(filter, k, name, skip, limit))
246
- .tap(q => logQuery(q))
247
- .flatMap(q =>
248
- Effect.promise(() =>
249
- container.items
250
- .query<PM>(q)
251
- .fetchAll()
252
- .then(({ resources }) => resources.toChunk)
253
- )
243
+ ? filter.keys
244
+ .forEachEffect(k =>
245
+ Effect(() => buildFindJoinCosmosQuery(filter, k, name, skip, limit))
246
+ .tap(q => logQuery(q))
247
+ .flatMap(q =>
248
+ Effect.promise(() =>
249
+ container.items
250
+ .query<PM>(q)
251
+ .fetchAll()
252
+ .then(({ resources }) => resources.toChunk)
254
253
  )
255
- )
256
- .map(_ => _.flatMap(_ => _))
254
+ )
255
+ )
256
+ .map(_ => _.flatMap(_ => _))
257
257
  : Effect(() => buildCosmosQuery(filter, name, importedMarkerId, skip, limit))
258
258
  .tap(q => logQuery(q))
259
259
  .flatMap(q =>
@@ -1,12 +1,11 @@
1
- import { expect, test } from "vitest"
2
1
  import type { StoreWhereFilter, Where } from "@effect-app/infra/services/Store"
2
+ import { expect, test } from "vitest"
3
3
  import { makeFilters } from "../../filter.js"
4
4
  import { codeFilter } from "./utils.js"
5
5
 
6
-
7
6
  const somethings = [
8
- {a: 1, b: "b", c: ["c"], d: [{a: "a2", b: 1}, {a: "a", b: 1}], id: "1"},
9
- {a: 2, b: "b2", c: ["c2"], d: [{a: "a4", b: 2}, {a: "a5", b: 2}], id: "2"},
7
+ { a: 1, b: "b", c: ["c"], d: [{ a: "a2", b: 1 }, { a: "a", b: 1 }], id: "1" },
8
+ { a: 2, b: "b2", c: ["c2"], d: [{ a: "a4", b: 2 }, { a: "a5", b: 2 }], id: "2" }
10
9
  ] satisfies readonly Something[]
11
10
 
12
11
  const f_ = makeFilters<Something>()
@@ -31,44 +30,52 @@ export function somethingsWhere(
31
30
  })
32
31
  }
33
32
 
34
-
35
33
  type SomethingElse = {
36
- a: string,
34
+ a: string
37
35
  b: number
38
36
  }
39
37
 
40
38
  type Something = {
41
- a: number,
42
- id: string,
43
- b: string,
39
+ a: number
40
+ id: string
41
+ b: string
44
42
  c: readonly string[]
45
43
  d: readonly SomethingElse[]
46
44
  }
47
45
 
48
46
  test("works", () => {
49
- expect(somethings.filterMap(codeFilter(
50
- somethingsWhere(_ => _("b", _ => "b2"))
51
- )).toArray)
52
- .toEqual([somethings[1]])
53
-
54
- expect(somethings.filterMap(codeFilter(
55
- somethingsWhere(_ => _("b", _ => "b"))
56
- )).toArray)
57
- .toEqual([somethings[0]])
47
+ expect(
48
+ somethings.filterMap(codeFilter(
49
+ somethingsWhere(_ => _("b", _ => "b2"))
50
+ )).toArray
51
+ )
52
+ .toEqual([somethings[1]])
58
53
 
54
+ expect(
55
+ somethings.filterMap(codeFilter(
56
+ somethingsWhere(_ => _("b", _ => "b"))
57
+ )).toArray
58
+ )
59
+ .toEqual([somethings[0]])
59
60
 
60
- expect(somethings.filterMap(codeFilter(
61
- somethingsWhere(_ => _("d.-1.a", _ => "a5"))
62
- )).toArray)
63
- .toEqual([somethings[1]])
61
+ expect(
62
+ somethings.filterMap(codeFilter(
63
+ somethingsWhere(_ => _("d.-1.a", _ => "a5"))
64
+ )).toArray
65
+ )
66
+ .toEqual([somethings[1]])
64
67
 
65
- expect(somethings.filterMap(codeFilter(
66
- somethingsWhere(_ => _("d.-1.a", _ => "a"))
67
- )).toArray)
68
- .toEqual([somethings[0]])
68
+ expect(
69
+ somethings.filterMap(codeFilter(
70
+ somethingsWhere(_ => _("d.-1.a", _ => "a"))
71
+ )).toArray
72
+ )
73
+ .toEqual([somethings[0]])
69
74
 
70
- expect(somethings.filterMap(codeFilter(
71
- somethingsWhere(_ => _("d.-1.a", _ => _.$isnt("a")))
72
- )).toArray)
73
- .toEqual([somethings[1]])
75
+ expect(
76
+ somethings.filterMap(codeFilter(
77
+ somethingsWhere(_ => _("d.-1.a", _ => _.$isnt("a")))
78
+ )).toArray
79
+ )
80
+ .toEqual([somethings[1]])
74
81
  })
@@ -13,8 +13,8 @@ export const makeETag = <E extends PersistenceModelType<Id>, Id extends string>(
13
13
  ...e,
14
14
  _etag: objectHash(e)
15
15
  }) as any
16
- export const makeUpdateETag = (name: string) =>
17
- <E extends PersistenceModelType<Id>, Id extends string>(e: E, current: Opt<E>) =>
16
+ export const makeUpdateETag =
17
+ (name: string) => <E extends PersistenceModelType<Id>, Id extends string>(e: E, current: Opt<E>) =>
18
18
  Effect.gen(function*($) {
19
19
  if (current.isSome() && current.value._etag !== e._etag) {
20
20
  return yield* $(
@@ -54,40 +54,40 @@ export function codeFilter<E extends { id: string }, NE extends E>(filter: Filte
54
54
  })
55
55
  ? Opt(x as unknown as NE)
56
56
  : Opt.none
57
- : // TODO: support mixed or/and
58
- filter.mode === "or"
59
- ? filter.where
60
- .some(p =>
61
- p.t === "in"
62
- ? p.value.includes(get(x, p.key))
63
- : p.t === "not-in"
64
- ? !p.value.includes(get(x, p.key))
65
- : p.t === "not-eq"
66
- ? !compareCaseInsensitive(get(x, p.key), p.value)
67
- : compareCaseInsensitive(get(x, p.key), p.value)
68
- )
69
- ? Opt(x as unknown as NE)
70
- : Opt.none
71
- : filter.where
72
- .every(p =>
73
- p.t === "in"
74
- ? p.value.includes(get(x, p.key))
75
- : p.t === "not-in"
76
- ? !p.value.includes(get(x, p.key))
77
- : p.t === "not-eq"
78
- ? p.key.includes(".-1.")
79
- ? (get(x, p.key.split(".-1.")[0]) as any[])
80
- // TODO: or vs and
81
- .every(_ => !compareCaseInsensitive(get(_, p.key.split(".-1.")[1]!), p.value))
82
- : !compareCaseInsensitive(get(x, p.key), p.value)
83
- : p.key.includes(".-1.")
84
- ? (get(x, p.key.split(".-1.")[0]) as any[])
85
- // TODO: or vs and
86
- .some(_ => compareCaseInsensitive(get(_, p.key.split(".-1.")[1]!), p.value))
87
- : compareCaseInsensitive(get(x, p.key), p.value)
88
- )
57
+ // TODO: support mixed or/and
58
+ : filter.mode === "or"
59
+ ? filter.where
60
+ .some(p =>
61
+ p.t === "in"
62
+ ? p.value.includes(get(x, p.key))
63
+ : p.t === "not-in"
64
+ ? !p.value.includes(get(x, p.key))
65
+ : p.t === "not-eq"
66
+ ? !compareCaseInsensitive(get(x, p.key), p.value)
67
+ : compareCaseInsensitive(get(x, p.key), p.value)
68
+ )
89
69
  ? Opt(x as unknown as NE)
90
70
  : Opt.none
71
+ : filter.where
72
+ .every(p =>
73
+ p.t === "in"
74
+ ? p.value.includes(get(x, p.key))
75
+ : p.t === "not-in"
76
+ ? !p.value.includes(get(x, p.key))
77
+ : p.t === "not-eq"
78
+ ? p.key.includes(".-1.")
79
+ ? (get(x, p.key.split(".-1.")[0]) as any[])
80
+ // TODO: or vs and
81
+ .every(_ => !compareCaseInsensitive(get(_, p.key.split(".-1.")[1]!), p.value))
82
+ : !compareCaseInsensitive(get(x, p.key), p.value)
83
+ : p.key.includes(".-1.")
84
+ ? (get(x, p.key.split(".-1.")[0]) as any[])
85
+ // TODO: or vs and
86
+ .some(_ => compareCaseInsensitive(get(_, p.key.split(".-1.")[1]!), p.value))
87
+ : compareCaseInsensitive(get(x, p.key), p.value)
88
+ )
89
+ ? Opt(x as unknown as NE)
90
+ : Opt.none
91
91
  }
92
92
 
93
93
  export function codeFilterJoinSelect<E extends { id: string }, NE>(
@@ -44,7 +44,7 @@ export function createContext<TKey extends string, EA, A extends DBRecord<TKey>>
44
44
  const cr = { data: JSON.parse(sdb.data) as EA, version: sdb.version }
45
45
  const r = yield* $(
46
46
  decode(cr.data).flatMap(d =>
47
- eq(d as unknown as V)(keys)
47
+ eq(keys, d as unknown as V)
48
48
  ? Effect(d)
49
49
  : Effect.fail("not equals")
50
50
  ).exit
@@ -30,12 +30,11 @@ export const RecordCache = Tag<RecordCache>()
30
30
 
31
31
  export const LiveRecordCache = Effect(makeLiveRecordCache()).toLayer(RecordCache)
32
32
 
33
- const getM = <T>(type: string) =>
34
- <R, E, A>(eff: (m: EffectMap<string, CachedRecord<T>>) => Effect<R, E, A>) =>
35
- Effect.gen(function*($) {
36
- const { get } = yield* $(RecordCache.access)
37
- return yield* $(get<T>(type).flatMap(eff))
38
- })
33
+ const getM = <T>(type: string) => <R, E, A>(eff: (m: EffectMap<string, CachedRecord<T>>) => Effect<R, E, A>) =>
34
+ Effect.gen(function*($) {
35
+ const { get } = yield* $(RecordCache.access)
36
+ return yield* $(get<T>(type).flatMap(eff))
37
+ })
39
38
 
40
39
  export function find<R, RDecode, EDecode, E, EA, A>(
41
40
  tryRead: (id: string) => Effect<R, E, Opt<CachedRecord<EA>>>,