@effect-app/infra 0.170.5 → 0.171.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/_cjs/api/routing/base.cjs.map +1 -1
- package/_cjs/api/routing/makeRequestHandler.cjs.map +1 -1
- package/_cjs/services/QueueMaker/errors.cjs.map +1 -1
- package/_cjs/services/Repository/dsl.cjs +70 -0
- package/_cjs/services/Repository/dsl.cjs.map +1 -0
- package/_cjs/services/Repository/ext.cjs +202 -0
- package/_cjs/services/Repository/ext.cjs.map +1 -0
- package/_cjs/services/Repository/service.cjs +6 -0
- package/_cjs/services/Repository/service.cjs.map +1 -0
- package/_cjs/services/Repository.cjs +32 -252
- package/_cjs/services/Repository.cjs.map +1 -1
- package/_cjs/services/RepositoryBase.cjs +173 -48
- package/_cjs/services/RepositoryBase.cjs.map +1 -1
- package/_cjs/services/RequestContextContainer.cjs +6 -7
- package/_cjs/services/RequestContextContainer.cjs.map +1 -1
- package/_cjs/services/Store/ContextMapContainer.cjs +6 -7
- package/_cjs/services/Store/ContextMapContainer.cjs.map +1 -1
- package/_cjs/services/Store/Memory.cjs.map +1 -1
- package/_cjs/services/Store/utils.cjs.map +1 -1
- package/_src/api/routing/base.ts +5 -3
- package/_src/api/routing/makeRequestHandler.ts +20 -12
- package/_src/rateLimit.ts +2 -2
- package/_src/services/Emailer/Sendgrid.ts +2 -2
- package/_src/services/QueueMaker/errors.ts +6 -3
- package/_src/services/QueueMaker/memQueue.ts +2 -2
- package/_src/services/QueueMaker/sbqueue.ts +2 -2
- package/_src/services/Repository/dsl.ts +137 -0
- package/_src/services/Repository/ext.ts +669 -0
- package/_src/services/Repository/service.ts +12 -0
- package/_src/services/Repository.ts +3 -791
- package/_src/services/RepositoryBase.ts +640 -13
- package/_src/services/RequestContextContainer.ts +14 -16
- package/_src/services/Store/ContextMapContainer.ts +6 -9
- package/_src/services/Store/Cosmos.ts +2 -2
- package/_src/services/Store/Disk.ts +2 -2
- package/_src/services/Store/Memory.ts +2 -1
- package/_src/services/Store/Redis.ts +2 -2
- package/_src/services/Store/utils.ts +4 -5
- package/_src/services/simpledb/cosmosdb.ts +1 -1
- package/_src/services/simpledb/diskdb.ts +1 -1
- package/_src/services/simpledb/memdb.ts +1 -1
- package/_src/services/simpledb/mongodb.ts +1 -1
- package/_src/services/simpledb/redisdb.ts +2 -2
- package/dist/api/routing/base.d.ts +1 -2
- package/dist/api/routing/base.d.ts.map +1 -1
- package/dist/api/routing/base.js +1 -1
- package/dist/api/routing/makeRequestHandler.d.ts.map +1 -1
- package/dist/api/routing/makeRequestHandler.js +15 -11
- package/dist/rateLimit.js +1 -1
- package/dist/services/Emailer/Sendgrid.js +1 -1
- package/dist/services/QueueMaker/errors.d.ts.map +1 -1
- package/dist/services/QueueMaker/errors.js +5 -2
- package/dist/services/QueueMaker/memQueue.js +1 -1
- package/dist/services/QueueMaker/sbqueue.js +1 -1
- package/dist/services/QueueMaker/service.d.ts +2 -2
- package/dist/services/Repository/dsl.d.ts +51 -0
- package/dist/services/Repository/dsl.d.ts.map +1 -0
- package/dist/services/Repository/dsl.js +55 -0
- package/dist/services/Repository/ext.d.ts +310 -0
- package/dist/services/Repository/ext.d.ts.map +1 -0
- package/dist/services/Repository/ext.js +166 -0
- package/dist/services/Repository/service.d.ts +10 -0
- package/dist/services/Repository/service.d.ts.map +1 -0
- package/dist/services/Repository/service.js +2 -0
- package/dist/services/Repository.d.ts +3 -363
- package/dist/services/Repository.d.ts.map +1 -1
- package/dist/services/Repository.js +4 -217
- package/dist/services/RepositoryBase.d.ts +241 -6
- package/dist/services/RepositoryBase.d.ts.map +1 -1
- package/dist/services/RepositoryBase.js +176 -52
- package/dist/services/RequestContextContainer.d.ts +3 -5
- package/dist/services/RequestContextContainer.d.ts.map +1 -1
- package/dist/services/RequestContextContainer.js +17 -16
- package/dist/services/Store/ContextMapContainer.d.ts +2 -5
- package/dist/services/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/services/Store/ContextMapContainer.js +7 -8
- package/dist/services/Store/Cosmos.js +1 -1
- package/dist/services/Store/Disk.js +1 -1
- package/dist/services/Store/Memory.d.ts.map +1 -1
- package/dist/services/Store/Memory.js +1 -1
- package/dist/services/Store/Redis.js +1 -1
- package/dist/services/Store/utils.d.ts.map +1 -1
- package/dist/services/Store/utils.js +1 -1
- package/dist/services/simpledb/cosmosdb.js +1 -1
- package/dist/services/simpledb/diskdb.js +1 -1
- package/dist/services/simpledb/memdb.js +1 -1
- package/dist/services/simpledb/mongodb.js +1 -1
- package/dist/services/simpledb/redisdb.js +1 -1
- package/package.json +37 -7
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/ban-types */
|
|
3
3
|
// import type { ParserEnv } from "@effect-app/schema/custom/Parser"
|
|
4
|
-
import
|
|
4
|
+
import {
|
|
5
|
+
AnyPureDSL,
|
|
6
|
+
byIdAndSaveWithPure,
|
|
7
|
+
get,
|
|
8
|
+
queryAndSaveOnePureEffect,
|
|
9
|
+
queryEffect,
|
|
10
|
+
queryOneEffect,
|
|
11
|
+
type Repository,
|
|
12
|
+
saveAllWithEffectInt,
|
|
13
|
+
saveManyWithPure_,
|
|
14
|
+
saveManyWithPureBatched_,
|
|
15
|
+
saveWithPure_
|
|
16
|
+
} from "./Repository.js"
|
|
5
17
|
import { StoreMaker } from "./Store.js"
|
|
6
18
|
import type { Filter, FilterArgs, FilterFunc, PersistenceModelType, StoreConfig, Where } from "./Store.js"
|
|
7
19
|
import type {} from "effect/Equal"
|
|
@@ -9,7 +21,8 @@ import type {} from "effect/Hash"
|
|
|
9
21
|
import type { Opt } from "@effect-app/core/Option"
|
|
10
22
|
import { makeFilters } from "@effect-app/infra/filter"
|
|
11
23
|
import { S } from "@effect-app/prelude"
|
|
12
|
-
import type {
|
|
24
|
+
import type { FixEnv } from "@effect-app/prelude/Pure"
|
|
25
|
+
import { type InvalidStateError, NotFoundError, type OptimisticConcurrencyException } from "../errors.js"
|
|
13
26
|
import { ContextMapContainer } from "./Store/ContextMapContainer.js"
|
|
14
27
|
import { QueryBuilder } from "./Store/filterApi/query.js"
|
|
15
28
|
|
|
@@ -76,6 +89,610 @@ export class RepositoryBaseC2<
|
|
|
76
89
|
override changeFeed = this.impl.changeFeed
|
|
77
90
|
}
|
|
78
91
|
|
|
92
|
+
export class RepositoryBaseC3<
|
|
93
|
+
T extends { id: unknown },
|
|
94
|
+
PM extends PersistenceModelType<string>,
|
|
95
|
+
Evt,
|
|
96
|
+
ItemType extends string
|
|
97
|
+
> extends RepositoryBaseC2<T, PM, Evt, ItemType> {
|
|
98
|
+
get<
|
|
99
|
+
T extends { id: unknown },
|
|
100
|
+
PM extends PersistenceModelType<string>,
|
|
101
|
+
Evt,
|
|
102
|
+
ItemType extends string
|
|
103
|
+
>(
|
|
104
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
105
|
+
id: T["id"]
|
|
106
|
+
) {
|
|
107
|
+
return this
|
|
108
|
+
.find(id)
|
|
109
|
+
.flatMap((_) => _.encaseInEffect(() => new NotFoundError<ItemType>({ type: this.itemType, id })))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
readonly log = (evt: Evt) => AnyPureDSL.log(evt)
|
|
113
|
+
|
|
114
|
+
// TODO: project inside the db.
|
|
115
|
+
projectEffect<
|
|
116
|
+
T extends { id: unknown },
|
|
117
|
+
PM extends PersistenceModelType<string>,
|
|
118
|
+
Evt,
|
|
119
|
+
ItemType extends string,
|
|
120
|
+
R,
|
|
121
|
+
E,
|
|
122
|
+
S = PM
|
|
123
|
+
>(
|
|
124
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
125
|
+
map: Effect<
|
|
126
|
+
{
|
|
127
|
+
filter?: Filter<PM> | undefined
|
|
128
|
+
collect?: ((t: PM) => Option<S>) | undefined
|
|
129
|
+
limit?: number | undefined
|
|
130
|
+
skip?: number | undefined
|
|
131
|
+
},
|
|
132
|
+
E,
|
|
133
|
+
R
|
|
134
|
+
>
|
|
135
|
+
): Effect<S[], E, R>
|
|
136
|
+
projectEffect<
|
|
137
|
+
T extends { id: unknown },
|
|
138
|
+
PM extends PersistenceModelType<string>,
|
|
139
|
+
Evt,
|
|
140
|
+
ItemType extends string,
|
|
141
|
+
R,
|
|
142
|
+
E,
|
|
143
|
+
U extends keyof PM,
|
|
144
|
+
S = PM
|
|
145
|
+
>(
|
|
146
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
147
|
+
map: Effect<
|
|
148
|
+
{
|
|
149
|
+
filter?: QueryBuilder<PM> | undefined
|
|
150
|
+
collect?: ((t: PM) => Option<S>) | undefined
|
|
151
|
+
limit?: number | undefined
|
|
152
|
+
skip?: number | undefined
|
|
153
|
+
},
|
|
154
|
+
E,
|
|
155
|
+
R
|
|
156
|
+
>
|
|
157
|
+
): Effect<Pick<PM, U>[], E, R>
|
|
158
|
+
projectEffect<
|
|
159
|
+
T extends { id: unknown },
|
|
160
|
+
PM extends PersistenceModelType<string>,
|
|
161
|
+
Evt,
|
|
162
|
+
ItemType extends string,
|
|
163
|
+
R,
|
|
164
|
+
E,
|
|
165
|
+
U extends keyof PM,
|
|
166
|
+
S = Pick<PM, U>
|
|
167
|
+
>(
|
|
168
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
169
|
+
map: Effect<
|
|
170
|
+
{
|
|
171
|
+
filter?: Filter<PM> | undefined
|
|
172
|
+
select?: NonEmptyReadonlyArray<U> | undefined
|
|
173
|
+
collect?: ((t: PM) => Option<S>) | undefined
|
|
174
|
+
limit?: number | undefined
|
|
175
|
+
skip?: number | undefined
|
|
176
|
+
},
|
|
177
|
+
E,
|
|
178
|
+
R
|
|
179
|
+
>
|
|
180
|
+
): Effect<S[], E, R> {
|
|
181
|
+
// TODO: a projection that gets sent to the db instead.
|
|
182
|
+
return map.flatMap((f) =>
|
|
183
|
+
this
|
|
184
|
+
.utils
|
|
185
|
+
.filter(f)
|
|
186
|
+
.map((_) => f.collect ? _.filterMap(f.collect) : _ as unknown as S[])
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* TODO: project inside the db.
|
|
192
|
+
* @tsplus fluent Repository project
|
|
193
|
+
*/
|
|
194
|
+
project<
|
|
195
|
+
T extends { id: unknown },
|
|
196
|
+
PM extends PersistenceModelType<string>,
|
|
197
|
+
Evt,
|
|
198
|
+
ItemType extends string,
|
|
199
|
+
S = PM
|
|
200
|
+
>(
|
|
201
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
202
|
+
map: {
|
|
203
|
+
filter?: Filter<PM>
|
|
204
|
+
collect?: (t: PM) => Option<S>
|
|
205
|
+
limit?: number
|
|
206
|
+
skip?: number
|
|
207
|
+
}
|
|
208
|
+
): Effect<S[]>
|
|
209
|
+
project<
|
|
210
|
+
T extends { id: unknown },
|
|
211
|
+
PM extends PersistenceModelType<string>,
|
|
212
|
+
Evt,
|
|
213
|
+
ItemType extends string,
|
|
214
|
+
U extends keyof PM
|
|
215
|
+
>(
|
|
216
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
217
|
+
map: {
|
|
218
|
+
filter?: QueryBuilder<PM>
|
|
219
|
+
select: NonEmptyReadonlyArray<U>
|
|
220
|
+
limit?: number
|
|
221
|
+
skip?: number
|
|
222
|
+
}
|
|
223
|
+
): Effect<Pick<PM, U>[]>
|
|
224
|
+
project<
|
|
225
|
+
T extends { id: unknown },
|
|
226
|
+
PM extends PersistenceModelType<string>,
|
|
227
|
+
Evt,
|
|
228
|
+
ItemType extends string,
|
|
229
|
+
U extends keyof PM,
|
|
230
|
+
S = Pick<PM, U>
|
|
231
|
+
>(
|
|
232
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
233
|
+
map: {
|
|
234
|
+
filter?: Filter<PM>
|
|
235
|
+
select?: NonEmptyReadonlyArray<U>
|
|
236
|
+
collect?: (t: Pick<PM, U>) => Option<S>
|
|
237
|
+
limit?: number
|
|
238
|
+
skip?: number
|
|
239
|
+
}
|
|
240
|
+
): Effect<S[]> {
|
|
241
|
+
return this.projectEffect(Effect.sync(() => map))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* TODO: count inside the db.
|
|
246
|
+
* @tsplus fluent Repository project
|
|
247
|
+
*/
|
|
248
|
+
count<
|
|
249
|
+
T extends { id: unknown },
|
|
250
|
+
PM extends PersistenceModelType<string>,
|
|
251
|
+
Evt,
|
|
252
|
+
ItemType extends string
|
|
253
|
+
>(
|
|
254
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
255
|
+
filter?: Filter<PM>
|
|
256
|
+
) {
|
|
257
|
+
return this
|
|
258
|
+
.projectEffect(Effect.sync(() => ({ filter })))
|
|
259
|
+
.map((_) => NonNegativeInt(_.length))
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* @tsplus fluent Repository queryEffect
|
|
264
|
+
*/
|
|
265
|
+
queryEffect<
|
|
266
|
+
T extends { id: unknown },
|
|
267
|
+
PM extends PersistenceModelType<string>,
|
|
268
|
+
Evt,
|
|
269
|
+
ItemType extends string,
|
|
270
|
+
R,
|
|
271
|
+
E,
|
|
272
|
+
S = T
|
|
273
|
+
>(
|
|
274
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
275
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
276
|
+
map: Effect<{ filter?: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>
|
|
277
|
+
) {
|
|
278
|
+
return map.flatMap((f) =>
|
|
279
|
+
(f.filter ? this.utils.filter(f) : this.utils.all)
|
|
280
|
+
.flatMap((_) => this.utils.parseMany(_))
|
|
281
|
+
.map((_) => f.collect ? _.filterMap(f.collect) : _ as any as S[])
|
|
282
|
+
)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @tsplus fluent Repository queryOneEffect
|
|
287
|
+
*/
|
|
288
|
+
queryOneEffect<
|
|
289
|
+
T extends { id: unknown },
|
|
290
|
+
PM extends PersistenceModelType<string>,
|
|
291
|
+
Evt,
|
|
292
|
+
ItemType extends string,
|
|
293
|
+
R,
|
|
294
|
+
E
|
|
295
|
+
>(
|
|
296
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
297
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
298
|
+
map: Effect<{ filter?: Filter<PM> }, E, R>
|
|
299
|
+
): Effect<T, E | NotFoundError<ItemType>, R>
|
|
300
|
+
queryOneEffect<
|
|
301
|
+
T extends { id: unknown },
|
|
302
|
+
PM extends PersistenceModelType<string>,
|
|
303
|
+
Evt,
|
|
304
|
+
ItemType extends string,
|
|
305
|
+
R,
|
|
306
|
+
E,
|
|
307
|
+
S = T
|
|
308
|
+
>(
|
|
309
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
310
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
311
|
+
map: Effect<{ filter?: Filter<PM>; collect: (t: T) => Option<S> }, E, R>
|
|
312
|
+
): Effect<S, E | NotFoundError<ItemType>, R>
|
|
313
|
+
queryOneEffect<
|
|
314
|
+
T extends { id: unknown },
|
|
315
|
+
PM extends PersistenceModelType<string>,
|
|
316
|
+
Evt,
|
|
317
|
+
ItemType extends string,
|
|
318
|
+
R,
|
|
319
|
+
E,
|
|
320
|
+
S = T
|
|
321
|
+
>(
|
|
322
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
323
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
324
|
+
map: Effect<{ filter?: Filter<PM>; collect?: (t: T) => Option<S> }, E, R>
|
|
325
|
+
): Effect<S, E | NotFoundError<ItemType>, R> {
|
|
326
|
+
return map.flatMap((f) =>
|
|
327
|
+
(f.filter ? this.utils.filter({ filter: f.filter, limit: 1 }) : this.utils.all)
|
|
328
|
+
.flatMap((_) => this.utils.parseMany(_))
|
|
329
|
+
.flatMap((_) =>
|
|
330
|
+
(f.collect ? _.filterMap(f.collect) : _ as any as S[])
|
|
331
|
+
.toNonEmpty
|
|
332
|
+
.encaseInEffect(() => new NotFoundError<ItemType>({ type: this.itemType, id: f.filter }))
|
|
333
|
+
.map((_) => _[0])
|
|
334
|
+
)
|
|
335
|
+
)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* @tsplus fluent Repository query
|
|
340
|
+
*/
|
|
341
|
+
query<
|
|
342
|
+
T extends { id: unknown },
|
|
343
|
+
PM extends PersistenceModelType<string>,
|
|
344
|
+
Evt,
|
|
345
|
+
ItemType extends string,
|
|
346
|
+
S = T
|
|
347
|
+
>(
|
|
348
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
349
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
350
|
+
map: { filter?: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }
|
|
351
|
+
) {
|
|
352
|
+
return this.queryEffect(Effect.sync(() => map))
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* @tsplus fluent Repository queryOne
|
|
357
|
+
*/
|
|
358
|
+
queryOne<
|
|
359
|
+
T extends { id: unknown },
|
|
360
|
+
PM extends PersistenceModelType<string>,
|
|
361
|
+
Evt,
|
|
362
|
+
ItemType extends string,
|
|
363
|
+
S = T
|
|
364
|
+
>(
|
|
365
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
366
|
+
map: { filter?: Filter<PM>; collect: (t: T) => Option<S> }
|
|
367
|
+
): Effect<S, NotFoundError<ItemType>>
|
|
368
|
+
queryOne<
|
|
369
|
+
T extends { id: unknown },
|
|
370
|
+
PM extends PersistenceModelType<string>,
|
|
371
|
+
Evt,
|
|
372
|
+
ItemType extends string
|
|
373
|
+
>(
|
|
374
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
375
|
+
map: { filter?: Filter<PM> }
|
|
376
|
+
): Effect<T, NotFoundError<ItemType>>
|
|
377
|
+
queryOne<
|
|
378
|
+
T extends { id: unknown },
|
|
379
|
+
PM extends PersistenceModelType<string>,
|
|
380
|
+
Evt,
|
|
381
|
+
ItemType extends string,
|
|
382
|
+
S = T
|
|
383
|
+
>(
|
|
384
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
385
|
+
map: { filter?: Filter<PM>; collect?: (t: T) => Option<S> }
|
|
386
|
+
) {
|
|
387
|
+
return this.queryOneEffect(Effect.sync(() => map))
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* @tsplus fluent Repository queryAndSaveOnePureEffect
|
|
392
|
+
*/
|
|
393
|
+
queryAndSaveOnePureEffect<
|
|
394
|
+
T extends { id: unknown },
|
|
395
|
+
PM extends PersistenceModelType<string>,
|
|
396
|
+
Evt,
|
|
397
|
+
ItemType extends string,
|
|
398
|
+
R,
|
|
399
|
+
E,
|
|
400
|
+
S extends T = T
|
|
401
|
+
>(
|
|
402
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
403
|
+
map: Effect<{ filter: Filter<PM>; collect: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>
|
|
404
|
+
): <R2, A, E2, S2 extends T>(
|
|
405
|
+
pure: Effect<A, E2, FixEnv<R2, Evt, S, S2>>
|
|
406
|
+
) => Effect<
|
|
407
|
+
A,
|
|
408
|
+
InvalidStateError | OptimisticConcurrencyException | E | E2 | NotFoundError<ItemType>,
|
|
409
|
+
| R
|
|
410
|
+
| Exclude<R2, {
|
|
411
|
+
env: PureEnv<Evt, S, S2>
|
|
412
|
+
}>
|
|
413
|
+
>
|
|
414
|
+
queryAndSaveOnePureEffect<
|
|
415
|
+
T extends { id: unknown },
|
|
416
|
+
PM extends PersistenceModelType<string>,
|
|
417
|
+
Evt,
|
|
418
|
+
ItemType extends string,
|
|
419
|
+
R,
|
|
420
|
+
E
|
|
421
|
+
>(
|
|
422
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
423
|
+
map: Effect<{ filter: Filter<PM> }, E, R>
|
|
424
|
+
): <R2, A, E2, T2 extends T>(
|
|
425
|
+
pure: Effect<A, E2, FixEnv<R2, Evt, T, T2>>
|
|
426
|
+
) => Effect<
|
|
427
|
+
A,
|
|
428
|
+
InvalidStateError | OptimisticConcurrencyException | E | E2 | NotFoundError<ItemType>,
|
|
429
|
+
| R
|
|
430
|
+
| Exclude<R2, {
|
|
431
|
+
env: PureEnv<Evt, T, T2>
|
|
432
|
+
}>
|
|
433
|
+
>
|
|
434
|
+
queryAndSaveOnePureEffect(
|
|
435
|
+
this: any,
|
|
436
|
+
map: any
|
|
437
|
+
) {
|
|
438
|
+
return (pure: any) =>
|
|
439
|
+
queryOneEffect(this, map)
|
|
440
|
+
.flatMap((_) => saveWithPure_(this, _, pure))
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* @tsplus fluent Repository queryAndSaveOnePure
|
|
445
|
+
*/
|
|
446
|
+
queryAndSaveOnePure<
|
|
447
|
+
T extends { id: unknown },
|
|
448
|
+
PM extends PersistenceModelType<string>,
|
|
449
|
+
Evt,
|
|
450
|
+
ItemType extends string,
|
|
451
|
+
S extends T = T
|
|
452
|
+
>(
|
|
453
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
454
|
+
map: { filter: Filter<PM>; collect: (t: T) => Option<S>; limit?: number; skip?: number }
|
|
455
|
+
): <R2, A, E2, S2>(pure: Effect<A, E2, FixEnv<R2, Evt, S, S2>>) => Effect<
|
|
456
|
+
A,
|
|
457
|
+
InvalidStateError | OptimisticConcurrencyException | E2 | NotFoundError<ItemType>,
|
|
458
|
+
Exclude<R2, {
|
|
459
|
+
env: PureEnv<Evt, S, S2>
|
|
460
|
+
}>
|
|
461
|
+
>
|
|
462
|
+
queryAndSaveOnePure<
|
|
463
|
+
T extends { id: unknown },
|
|
464
|
+
PM extends PersistenceModelType<string>,
|
|
465
|
+
Evt,
|
|
466
|
+
ItemType extends string
|
|
467
|
+
>(
|
|
468
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
469
|
+
map: { filter: Filter<PM> }
|
|
470
|
+
): <R2, A, E2, T2>(pure: Effect<A, E2, FixEnv<R2, Evt, T, T2>>) => Effect<
|
|
471
|
+
A,
|
|
472
|
+
InvalidStateError | OptimisticConcurrencyException | E2 | NotFoundError<ItemType>,
|
|
473
|
+
Exclude<R2, {
|
|
474
|
+
env: PureEnv<Evt, T, T2>
|
|
475
|
+
}>
|
|
476
|
+
>
|
|
477
|
+
queryAndSaveOnePure(
|
|
478
|
+
this: any,
|
|
479
|
+
map: { filter: Filter<any>; collect?: any }
|
|
480
|
+
) {
|
|
481
|
+
return queryAndSaveOnePureEffect(this, Effect.sync(() => map))
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* @tsplus fluent Repository queryAndSavePureEffect
|
|
486
|
+
*/
|
|
487
|
+
queryAndSavePureEffect<
|
|
488
|
+
T extends { id: unknown },
|
|
489
|
+
PM extends PersistenceModelType<string>,
|
|
490
|
+
Evt,
|
|
491
|
+
ItemType extends string,
|
|
492
|
+
R,
|
|
493
|
+
E,
|
|
494
|
+
S extends T = T
|
|
495
|
+
>(
|
|
496
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
497
|
+
map: Effect<{ filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>
|
|
498
|
+
) {
|
|
499
|
+
return <R2, A, E2, S2 extends T>(pure: Effect<A, E2, FixEnv<R2, Evt, S[], S2[]>>) =>
|
|
500
|
+
queryEffect(this, map)
|
|
501
|
+
.flatMap((_) => this.saveManyWithPure_(_, pure))
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* @tsplus fluent Repository queryAndSavePure
|
|
506
|
+
*/
|
|
507
|
+
queryAndSavePure<
|
|
508
|
+
T extends { id: unknown },
|
|
509
|
+
PM extends PersistenceModelType<string>,
|
|
510
|
+
Evt,
|
|
511
|
+
ItemType extends string,
|
|
512
|
+
S extends T = T
|
|
513
|
+
>(
|
|
514
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
515
|
+
map: { filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }
|
|
516
|
+
) {
|
|
517
|
+
return this.queryAndSavePureEffect(Effect.sync(() => map))
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
saveManyWithPure<
|
|
521
|
+
T extends { id: unknown },
|
|
522
|
+
PM extends PersistenceModelType<string>,
|
|
523
|
+
Evt,
|
|
524
|
+
ItemType extends string
|
|
525
|
+
>(this: RepositoryBaseC<T, PM, Evt, ItemType>) {
|
|
526
|
+
return <R, A, E, S1 extends T, S2 extends T>(pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>) =>
|
|
527
|
+
(items: Iterable<S1>) => saveManyWithPure_(this, items, pure)
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
byIdAndSaveWithPure<
|
|
531
|
+
T extends { id: unknown },
|
|
532
|
+
PM extends PersistenceModelType<string>,
|
|
533
|
+
Evt,
|
|
534
|
+
ItemType extends string
|
|
535
|
+
>(this: RepositoryBaseC<T, PM, Evt, ItemType>, id: T["id"]) {
|
|
536
|
+
return <R, A, E, S2 extends T>(pure: Effect<A, E, FixEnv<R, Evt, T, S2>>) =>
|
|
537
|
+
get(this, id).flatMap((item) => saveWithPure_(this, item, pure))
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* NOTE: it's not as composable, only useful when the request is simple, and only this part needs request args.
|
|
542
|
+
*/
|
|
543
|
+
handleByIdAndSaveWithPure<
|
|
544
|
+
T extends { id: unknown },
|
|
545
|
+
PM extends PersistenceModelType<string>,
|
|
546
|
+
Evt,
|
|
547
|
+
ItemType extends string
|
|
548
|
+
>(this: RepositoryBaseC<T, PM, Evt, ItemType>) {
|
|
549
|
+
return <Req extends { id: T["id"] }, Context, R, A, E, S2 extends T>(
|
|
550
|
+
pure: (req: Req, ctx: Context) => Effect<A, E, FixEnv<R, Evt, T, S2>>
|
|
551
|
+
) =>
|
|
552
|
+
(req: Req, ctx: Context) => byIdAndSaveWithPure(this, req.id)(pure(req, ctx))
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
saveManyWithPure_<
|
|
556
|
+
R,
|
|
557
|
+
T extends { id: unknown },
|
|
558
|
+
PM extends PersistenceModelType<string>,
|
|
559
|
+
A,
|
|
560
|
+
E,
|
|
561
|
+
Evt,
|
|
562
|
+
S1 extends T,
|
|
563
|
+
S2 extends T,
|
|
564
|
+
ItemType extends string
|
|
565
|
+
>(
|
|
566
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
567
|
+
items: Iterable<S1>,
|
|
568
|
+
pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>
|
|
569
|
+
) {
|
|
570
|
+
return saveAllWithEffectInt(
|
|
571
|
+
this,
|
|
572
|
+
pure.runTerm([...items])
|
|
573
|
+
)
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
saveWithPure_<
|
|
577
|
+
R,
|
|
578
|
+
T extends { id: unknown },
|
|
579
|
+
PM extends PersistenceModelType<string>,
|
|
580
|
+
A,
|
|
581
|
+
E,
|
|
582
|
+
Evt,
|
|
583
|
+
S1 extends T,
|
|
584
|
+
S2 extends T,
|
|
585
|
+
ItemType extends string
|
|
586
|
+
>(
|
|
587
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
588
|
+
item: S1,
|
|
589
|
+
pure: Effect<A, E, FixEnv<R, Evt, S1, S2>>
|
|
590
|
+
) {
|
|
591
|
+
return saveAllWithEffectInt(
|
|
592
|
+
this,
|
|
593
|
+
pure
|
|
594
|
+
.runTerm(item)
|
|
595
|
+
.map(([item, events, a]) => [[item], events, a])
|
|
596
|
+
)
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
saveAllWithEffectInt<
|
|
600
|
+
T extends { id: unknown },
|
|
601
|
+
PM extends PersistenceModelType<string>,
|
|
602
|
+
P extends T,
|
|
603
|
+
Evt,
|
|
604
|
+
ItemType extends string,
|
|
605
|
+
R,
|
|
606
|
+
E,
|
|
607
|
+
A
|
|
608
|
+
>(
|
|
609
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
610
|
+
gen: Effect<readonly [Iterable<P>, Iterable<Evt>, A], E, R>
|
|
611
|
+
) {
|
|
612
|
+
return gen
|
|
613
|
+
.flatMap(
|
|
614
|
+
([items, events, a]) => this.saveAndPublish(items, events).map(() => a)
|
|
615
|
+
)
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
queryAndSavePureEffectBatched<
|
|
619
|
+
T extends { id: unknown },
|
|
620
|
+
PM extends PersistenceModelType<string>,
|
|
621
|
+
Evt,
|
|
622
|
+
ItemType extends string,
|
|
623
|
+
R,
|
|
624
|
+
E,
|
|
625
|
+
S extends T = T
|
|
626
|
+
>(
|
|
627
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
628
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
629
|
+
map: Effect<{ filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }, E, R>,
|
|
630
|
+
batchSize = 100
|
|
631
|
+
) {
|
|
632
|
+
return <R2, A, E2, S2 extends T>(pure: Effect<A, E2, FixEnv<R2, Evt, S[], S2[]>>) =>
|
|
633
|
+
queryEffect(this, map)
|
|
634
|
+
.flatMap((_) => this.saveManyWithPureBatched_(_, pure, batchSize))
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
queryAndSavePureBatched<
|
|
638
|
+
T extends { id: unknown },
|
|
639
|
+
PM extends PersistenceModelType<string>,
|
|
640
|
+
Evt,
|
|
641
|
+
ItemType extends string,
|
|
642
|
+
S extends T = T
|
|
643
|
+
>(
|
|
644
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
645
|
+
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
646
|
+
map: { filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number },
|
|
647
|
+
batchSize = 100
|
|
648
|
+
) {
|
|
649
|
+
return this.queryAndSavePureEffectBatched(Effect.sync(() => map), batchSize)
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
saveManyWithPureBatched<
|
|
653
|
+
T extends { id: unknown },
|
|
654
|
+
PM extends PersistenceModelType<string>,
|
|
655
|
+
Evt,
|
|
656
|
+
ItemType extends string
|
|
657
|
+
>(this: RepositoryBaseC<T, PM, Evt, ItemType>, batchSize = 100) {
|
|
658
|
+
return <R, A, E, S1 extends T, S2 extends T>(pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>) =>
|
|
659
|
+
(items: Iterable<S1>) => saveManyWithPureBatched_(this, items, pure, batchSize)
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
saveManyWithPureBatched_<
|
|
663
|
+
R,
|
|
664
|
+
T extends { id: unknown },
|
|
665
|
+
PM extends PersistenceModelType<string>,
|
|
666
|
+
A,
|
|
667
|
+
E,
|
|
668
|
+
Evt,
|
|
669
|
+
S1 extends T,
|
|
670
|
+
S2 extends T,
|
|
671
|
+
ItemType extends string
|
|
672
|
+
>(
|
|
673
|
+
this: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
674
|
+
items: Iterable<S1>,
|
|
675
|
+
pure: Effect<A, E, FixEnv<R, Evt, S1[], S2[]>>,
|
|
676
|
+
batchSize = 100
|
|
677
|
+
) {
|
|
678
|
+
return items
|
|
679
|
+
.chunk(batchSize)
|
|
680
|
+
.forEachEffect((batch) =>
|
|
681
|
+
saveAllWithEffectInt(
|
|
682
|
+
this,
|
|
683
|
+
pure.runTerm(batch)
|
|
684
|
+
)
|
|
685
|
+
)
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
readonly save = (...items: NonEmptyArray<T>) => this.saveAndPublish(items)
|
|
689
|
+
|
|
690
|
+
readonly saveWithEvents = (
|
|
691
|
+
events: Iterable<Evt>
|
|
692
|
+
) =>
|
|
693
|
+
(...items: NonEmptyArray<T>) => this.saveAndPublish(items, events)
|
|
694
|
+
}
|
|
695
|
+
|
|
79
696
|
type Exact<A, B> = [A] extends [B] ? [B] extends [A] ? true : false : false
|
|
80
697
|
/**
|
|
81
698
|
* A base implementation to create a repository.
|
|
@@ -164,10 +781,20 @@ export function makeRepo<
|
|
|
164
781
|
(S.make(_._tag === "Transform" ? _.from : _) as unknown as Schema<T, From>)
|
|
165
782
|
.pipe(S.pick("id"))
|
|
166
783
|
))
|
|
167
|
-
: _
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
784
|
+
: _
|
|
785
|
+
.ast
|
|
786
|
+
._tag === "Transform"
|
|
787
|
+
? (S
|
|
788
|
+
.make(
|
|
789
|
+
_
|
|
790
|
+
.ast
|
|
791
|
+
.from
|
|
792
|
+
) as unknown as Schema<T, From>)
|
|
793
|
+
.pipe(S
|
|
794
|
+
.pick("id"))
|
|
795
|
+
: _
|
|
796
|
+
.pipe(S
|
|
797
|
+
.pick("id"))
|
|
171
798
|
)
|
|
172
799
|
const encodeId = flow(i.encode, Effect.provide(rctx))
|
|
173
800
|
function findE(_id: T["id"]) {
|
|
@@ -269,7 +896,7 @@ export function makeRepo<
|
|
|
269
896
|
return r
|
|
270
897
|
})
|
|
271
898
|
// .withSpan("Repository.make [effect-app/infra]", { attributes: { "repository.model_name": name } })
|
|
272
|
-
.withLogSpan("Repository.make: " + name)
|
|
899
|
+
.withLogSpan("Repository.make: " + name)
|
|
273
900
|
}
|
|
274
901
|
|
|
275
902
|
return {
|
|
@@ -277,7 +904,7 @@ export function makeRepo<
|
|
|
277
904
|
where,
|
|
278
905
|
query: QueryBuilder.make<PM>()
|
|
279
906
|
}
|
|
280
|
-
}
|
|
907
|
+
}
|
|
281
908
|
}
|
|
282
909
|
|
|
283
910
|
/**
|
|
@@ -388,7 +1015,7 @@ export function makeStore<
|
|
|
388
1015
|
}
|
|
389
1016
|
|
|
390
1017
|
return makeStore
|
|
391
|
-
}
|
|
1018
|
+
}
|
|
392
1019
|
}
|
|
393
1020
|
|
|
394
1021
|
export interface Repos<
|
|
@@ -476,7 +1103,7 @@ export const RepositoryBaseImpl = <Service>() => {
|
|
|
476
1103
|
static readonly type: Repository<T, PM, Evt, ItemType> = undefined as any
|
|
477
1104
|
}
|
|
478
1105
|
return assignTag<Service>()(Cls) as any
|
|
479
|
-
}
|
|
1106
|
+
}
|
|
480
1107
|
}
|
|
481
1108
|
|
|
482
1109
|
export const RepositoryDefaultImpl = <Service>() => {
|
|
@@ -491,7 +1118,7 @@ export const RepositoryDefaultImpl = <Service>() => {
|
|
|
491
1118
|
): Exact<PM, From & { _etag: string | undefined }> extends true ?
|
|
492
1119
|
& (abstract new(
|
|
493
1120
|
impl: Repository<T, PM, Evt, ItemType>
|
|
494
|
-
) =>
|
|
1121
|
+
) => RepositoryBaseC3<T, PM, Evt, ItemType>)
|
|
495
1122
|
& Tag<Service, Service>
|
|
496
1123
|
& Repos<
|
|
497
1124
|
T,
|
|
@@ -508,7 +1135,7 @@ export const RepositoryDefaultImpl = <Service>() => {
|
|
|
508
1135
|
jitM ? (pm) => jitM(pm as unknown as From) : (pm) => pm as any,
|
|
509
1136
|
(e, _etag) => ({ ...e, _etag })
|
|
510
1137
|
)
|
|
511
|
-
abstract class Cls extends
|
|
1138
|
+
abstract class Cls extends RepositoryBaseC3<T, PM, Evt, ItemType> {
|
|
512
1139
|
constructor(
|
|
513
1140
|
impl: Repository<T, PM, Evt, ItemType>
|
|
514
1141
|
) {
|
|
@@ -523,5 +1150,5 @@ export const RepositoryDefaultImpl = <Service>() => {
|
|
|
523
1150
|
static readonly type: Repository<T, PM, Evt, ItemType> = undefined as any
|
|
524
1151
|
}
|
|
525
1152
|
return assignTag<Service>()(Cls) as any // impl is missing, but its marked protected
|
|
526
|
-
}
|
|
1153
|
+
}
|
|
527
1154
|
}
|