@effect-app/infra 0.96.1 → 0.97.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 +10 -0
- package/_cjs/services/Repository.cjs.map +1 -1
- package/_cjs/services/RepositoryBase.cjs +101 -76
- package/_cjs/services/RepositoryBase.cjs.map +1 -1
- package/_src/services/Repository.ts +27 -50
- package/_src/services/RepositoryBase.ts +167 -144
- package/dist/services/Repository.d.ts +42 -59
- package/dist/services/Repository.d.ts.map +1 -1
- package/dist/services/Repository.js +1 -1
- package/dist/services/RepositoryBase.d.ts +75 -104
- package/dist/services/RepositoryBase.d.ts.map +1 -1
- package/dist/services/RepositoryBase.js +99 -77
- package/package.json +4 -4
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
// Modify = Must `set` updated items, and can return anything.
|
|
4
4
|
import type { FixEnv, PureLogT } from "@effect-app/prelude/Pure"
|
|
5
5
|
import { Pure } from "@effect-app/prelude/Pure"
|
|
6
|
-
import type { ParserEnv } from "@effect-app/schema/custom/Parser"
|
|
7
|
-
import type { InvalidStateError, OptimisticConcurrencyException } from "../errors.js"
|
|
8
6
|
import { NotFoundError } from "../errors.js"
|
|
9
7
|
import type { Filter } from "../services/Store.js"
|
|
8
|
+
import type { RepositoryBaseC } from "./RepositoryBase.js"
|
|
10
9
|
import { ContextMapContainer } from "./Store/ContextMapContainer.js"
|
|
11
10
|
|
|
12
11
|
/**
|
|
@@ -17,29 +16,7 @@ export interface Repository<
|
|
|
17
16
|
PM extends { id: string },
|
|
18
17
|
Evt,
|
|
19
18
|
ItemType extends string
|
|
20
|
-
> {
|
|
21
|
-
itemType: ItemType
|
|
22
|
-
find: (id: T["id"]) => Effect<never, never, Option<T>>
|
|
23
|
-
all: Effect<never, never, T[]>
|
|
24
|
-
saveAndPublish: (
|
|
25
|
-
items: Iterable<T>,
|
|
26
|
-
events?: Iterable<Evt>
|
|
27
|
-
) => Effect<never, InvalidStateError | OptimisticConcurrencyException, void>
|
|
28
|
-
removeAndPublish: (
|
|
29
|
-
items: Iterable<T>,
|
|
30
|
-
events?: Iterable<Evt>
|
|
31
|
-
) => Effect<never, never, void>
|
|
32
|
-
utils: {
|
|
33
|
-
mapReverse: (
|
|
34
|
-
pm: PM,
|
|
35
|
-
setEtag: (id: string, eTag: string | undefined) => void
|
|
36
|
-
) => unknown // TODO
|
|
37
|
-
parse: (a: unknown, env?: ParserEnv | undefined) => T
|
|
38
|
-
all: Effect<never, never, PM[]>
|
|
39
|
-
filter: (filter: Filter<PM>, cursor?: { limit?: number; skip?: number }) => Effect<never, never, PM[]>
|
|
40
|
-
}
|
|
41
|
-
changeFeed: PubSub<[T[], "save" | "remove"]>
|
|
42
|
-
}
|
|
19
|
+
> extends RepositoryBaseC<T, PM, Evt, ItemType> {}
|
|
43
20
|
|
|
44
21
|
export interface PureDSL<S, S2, W> {
|
|
45
22
|
get: ReturnType<typeof Pure.get<S>>
|
|
@@ -62,7 +39,7 @@ export function get<
|
|
|
62
39
|
Evt,
|
|
63
40
|
ItemType extends string
|
|
64
41
|
>(
|
|
65
|
-
self:
|
|
42
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
66
43
|
id: T["id"]
|
|
67
44
|
) {
|
|
68
45
|
return self.find(id).flatMap((_) => _.encaseInEffect(() => new NotFoundError({ type: self.itemType, id })))
|
|
@@ -76,7 +53,7 @@ export function filter<
|
|
|
76
53
|
PM extends { id: string },
|
|
77
54
|
Evt,
|
|
78
55
|
ItemType extends string
|
|
79
|
-
>(self:
|
|
56
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>, filter: Predicate<T>) {
|
|
80
57
|
return self.all.map((_) => _.filter(filter))
|
|
81
58
|
}
|
|
82
59
|
|
|
@@ -89,7 +66,7 @@ export function filterAll<
|
|
|
89
66
|
Evt,
|
|
90
67
|
ItemType extends string,
|
|
91
68
|
S extends T
|
|
92
|
-
>(self:
|
|
69
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>, map: (items: T[]) => S[]) {
|
|
93
70
|
return self.all.map(map)
|
|
94
71
|
}
|
|
95
72
|
|
|
@@ -102,7 +79,7 @@ export function collect<
|
|
|
102
79
|
Evt,
|
|
103
80
|
ItemType extends string,
|
|
104
81
|
S extends T
|
|
105
|
-
>(self:
|
|
82
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>, collect: (item: T) => Option<S>) {
|
|
106
83
|
return self.all.map((_) => _.filterMap(collect))
|
|
107
84
|
}
|
|
108
85
|
|
|
@@ -114,7 +91,7 @@ export function log<
|
|
|
114
91
|
PM extends { id: string },
|
|
115
92
|
Evt,
|
|
116
93
|
ItemType extends string
|
|
117
|
-
>(_:
|
|
94
|
+
>(_: RepositoryBaseC<T, PM, Evt, ItemType>) {
|
|
118
95
|
return (evt: Evt) => AnyPureDSL.log(evt)
|
|
119
96
|
}
|
|
120
97
|
|
|
@@ -131,7 +108,7 @@ export function projectEffect<
|
|
|
131
108
|
E,
|
|
132
109
|
S = PM
|
|
133
110
|
>(
|
|
134
|
-
self:
|
|
111
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
135
112
|
map: Effect<R, E, { filter?: Filter<PM>; collect?: (t: PM) => Option<S>; limit?: number; skip?: number }>
|
|
136
113
|
) {
|
|
137
114
|
// TODO: a projection that gets sent to the db instead.
|
|
@@ -152,7 +129,7 @@ export function project<
|
|
|
152
129
|
ItemType extends string,
|
|
153
130
|
S = PM
|
|
154
131
|
>(
|
|
155
|
-
self:
|
|
132
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
156
133
|
map: { filter?: Filter<PM>; collect?: (t: PM) => Option<S>; limit?: number; skip?: number }
|
|
157
134
|
) {
|
|
158
135
|
return self.projectEffect(Effect(map))
|
|
@@ -176,7 +153,7 @@ export function queryEffect<
|
|
|
176
153
|
E,
|
|
177
154
|
S = T
|
|
178
155
|
>(
|
|
179
|
-
self:
|
|
156
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
180
157
|
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
181
158
|
map: Effect<R, E, { filter?: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }>
|
|
182
159
|
) {
|
|
@@ -205,7 +182,7 @@ export function queryOneEffect<
|
|
|
205
182
|
E,
|
|
206
183
|
S = T
|
|
207
184
|
>(
|
|
208
|
-
self:
|
|
185
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
209
186
|
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
210
187
|
map: Effect<R, E, { filter?: Filter<PM>; collect?: (t: T) => Option<S> }>
|
|
211
188
|
) {
|
|
@@ -237,7 +214,7 @@ export function query<
|
|
|
237
214
|
ItemType extends string,
|
|
238
215
|
S = T
|
|
239
216
|
>(
|
|
240
|
-
self:
|
|
217
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
241
218
|
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
242
219
|
map: { filter?: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }
|
|
243
220
|
) {
|
|
@@ -254,7 +231,7 @@ export function queryOne<
|
|
|
254
231
|
ItemType extends string,
|
|
255
232
|
S = T
|
|
256
233
|
>(
|
|
257
|
-
self:
|
|
234
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
258
235
|
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
259
236
|
map: { filter?: Filter<PM>; collect?: (t: T) => Option<S> }
|
|
260
237
|
) {
|
|
@@ -273,7 +250,7 @@ export function queryAndSavePureEffect<
|
|
|
273
250
|
E,
|
|
274
251
|
S extends T = T
|
|
275
252
|
>(
|
|
276
|
-
self:
|
|
253
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
277
254
|
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
278
255
|
map: Effect<R, E, { filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }>
|
|
279
256
|
) {
|
|
@@ -292,7 +269,7 @@ export function queryAndSavePure<
|
|
|
292
269
|
ItemType extends string,
|
|
293
270
|
S extends T = T
|
|
294
271
|
>(
|
|
295
|
-
self:
|
|
272
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
296
273
|
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
297
274
|
map: { filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }
|
|
298
275
|
) {
|
|
@@ -307,7 +284,7 @@ export function saveManyWithPure<
|
|
|
307
284
|
PM extends { id: string },
|
|
308
285
|
Evt,
|
|
309
286
|
ItemType extends string
|
|
310
|
-
>(self:
|
|
287
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>) {
|
|
311
288
|
return <R, A, E, S1 extends T, S2 extends T>(pure: Effect<FixEnv<R, Evt, S1[], S2[]>, E, A>) =>
|
|
312
289
|
(items: Iterable<S1>) => saveManyWithPure_(self, items, pure)
|
|
313
290
|
}
|
|
@@ -320,7 +297,7 @@ export function byIdAndSaveWithPure<
|
|
|
320
297
|
PM extends { id: string },
|
|
321
298
|
Evt,
|
|
322
299
|
ItemType extends string
|
|
323
|
-
>(self:
|
|
300
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>, id: T["id"]) {
|
|
324
301
|
return <R, A, E, S2 extends T>(pure: Effect<FixEnv<R, Evt, T, S2>, E, A>) =>
|
|
325
302
|
get(self, id).flatMap((item) => saveWithPure_(self, item, pure))
|
|
326
303
|
}
|
|
@@ -334,7 +311,7 @@ export function handleByIdAndSaveWithPure<
|
|
|
334
311
|
PM extends { id: string },
|
|
335
312
|
Evt,
|
|
336
313
|
ItemType extends string
|
|
337
|
-
>(self:
|
|
314
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>) {
|
|
338
315
|
return <Req extends { id: T["id"] }, Context, R, A, E, S2 extends T>(
|
|
339
316
|
pure: (req: Req, ctx: Context) => Effect<FixEnv<R, Evt, T, S2>, E, A>
|
|
340
317
|
) =>
|
|
@@ -356,7 +333,7 @@ export function saveManyWithPure_<
|
|
|
356
333
|
S2 extends T,
|
|
357
334
|
ItemType extends string
|
|
358
335
|
>(
|
|
359
|
-
self:
|
|
336
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
360
337
|
items: Iterable<S1>,
|
|
361
338
|
pure: Effect<FixEnv<R, Evt, S1[], S2[]>, E, A>
|
|
362
339
|
) {
|
|
@@ -381,7 +358,7 @@ export function saveWithPure_<
|
|
|
381
358
|
S2 extends T,
|
|
382
359
|
ItemType extends string
|
|
383
360
|
>(
|
|
384
|
-
self:
|
|
361
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
385
362
|
item: S1,
|
|
386
363
|
pure: Effect<FixEnv<R, Evt, S1, S2>, E, A>
|
|
387
364
|
) {
|
|
@@ -403,7 +380,7 @@ export function saveAllWithEffectInt<
|
|
|
403
380
|
E,
|
|
404
381
|
A
|
|
405
382
|
>(
|
|
406
|
-
self:
|
|
383
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
407
384
|
gen: Effect<R, E, readonly [Iterable<P>, Iterable<Evt>, A]>
|
|
408
385
|
) {
|
|
409
386
|
return gen
|
|
@@ -424,7 +401,7 @@ export function queryAndSavePureEffectBatched<
|
|
|
424
401
|
E,
|
|
425
402
|
S extends T = T
|
|
426
403
|
>(
|
|
427
|
-
self:
|
|
404
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
428
405
|
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
429
406
|
map: Effect<R, E, { filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number }>,
|
|
430
407
|
batchSize = 100
|
|
@@ -444,7 +421,7 @@ export function queryAndSavePureBatched<
|
|
|
444
421
|
ItemType extends string,
|
|
445
422
|
S extends T = T
|
|
446
423
|
>(
|
|
447
|
-
self:
|
|
424
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
448
425
|
// TODO: think about collectPM, collectE, and collect(Parsed)
|
|
449
426
|
map: { filter: Filter<PM>; collect?: (t: T) => Option<S>; limit?: number; skip?: number },
|
|
450
427
|
batchSize = 100
|
|
@@ -460,7 +437,7 @@ export function saveManyWithPureBatched<
|
|
|
460
437
|
PM extends { id: string },
|
|
461
438
|
Evt,
|
|
462
439
|
ItemType extends string
|
|
463
|
-
>(self:
|
|
440
|
+
>(self: RepositoryBaseC<T, PM, Evt, ItemType>, batchSize = 100) {
|
|
464
441
|
return <R, A, E, S1 extends T, S2 extends T>(pure: Effect<FixEnv<R, Evt, S1[], S2[]>, E, A>) =>
|
|
465
442
|
(items: Iterable<S1>) => saveManyWithPureBatched_(self, items, pure, batchSize)
|
|
466
443
|
}
|
|
@@ -480,7 +457,7 @@ export function saveManyWithPureBatched_<
|
|
|
480
457
|
S2 extends T,
|
|
481
458
|
ItemType extends string
|
|
482
459
|
>(
|
|
483
|
-
self:
|
|
460
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>,
|
|
484
461
|
items: Iterable<S1>,
|
|
485
462
|
pure: Effect<FixEnv<R, Evt, S1[], S2[]>, E, A>,
|
|
486
463
|
batchSize = 100
|
|
@@ -628,7 +605,7 @@ export function save<
|
|
|
628
605
|
Evt,
|
|
629
606
|
ItemType extends string
|
|
630
607
|
>(
|
|
631
|
-
self:
|
|
608
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>
|
|
632
609
|
) {
|
|
633
610
|
return (...items: NonEmptyArray<T>) => self.saveAndPublish(items)
|
|
634
611
|
}
|
|
@@ -642,7 +619,7 @@ export function saveWithEvents<
|
|
|
642
619
|
Evt,
|
|
643
620
|
ItemType extends string
|
|
644
621
|
>(
|
|
645
|
-
self:
|
|
622
|
+
self: RepositoryBaseC<T, PM, Evt, ItemType>
|
|
646
623
|
) {
|
|
647
624
|
return (events: Iterable<Evt>) => (...items: NonEmptyArray<T>) => self.saveAndPublish(items, events)
|
|
648
625
|
}
|
|
@@ -15,55 +15,74 @@ import type { InvalidStateError, OptimisticConcurrencyException } from "../error
|
|
|
15
15
|
import { ContextMapContainer } from "./Store/ContextMapContainer.js"
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* @tsplus type Repository
|
|
19
19
|
*/
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
20
|
+
export abstract class RepositoryBaseC<
|
|
21
|
+
T extends { id: string },
|
|
22
|
+
PM extends { id: string },
|
|
23
|
+
Evt,
|
|
24
|
+
ItemType extends string
|
|
25
|
+
> {
|
|
26
|
+
abstract readonly itemType: ItemType
|
|
27
|
+
abstract readonly find: (id: T["id"]) => Effect<never, never, Opt<T>>
|
|
28
|
+
abstract readonly all: Effect<never, never, T[]>
|
|
29
|
+
abstract readonly saveAndPublish: (
|
|
30
|
+
items: Iterable<T>,
|
|
31
|
+
events?: Iterable<Evt>
|
|
32
|
+
) => Effect<never, InvalidStateError | OptimisticConcurrencyException, void>
|
|
33
|
+
abstract readonly utils: {
|
|
34
|
+
mapReverse: (
|
|
35
|
+
pm: PM,
|
|
36
|
+
setEtag: (id: string, eTag: string | undefined) => void
|
|
37
|
+
) => unknown // TODO
|
|
38
|
+
parse: (a: unknown, env?: ParserEnv | undefined) => T
|
|
39
|
+
all: Effect<never, never, PM[]>
|
|
40
|
+
filter: (filter: Filter<PM>, cursor?: { limit?: number; skip?: number }) => Effect<never, never, PM[]>
|
|
41
|
+
}
|
|
42
|
+
abstract readonly changeFeed: PubSub<[T[], "save" | "remove"]>
|
|
43
|
+
abstract readonly removeAndPublish: (
|
|
44
|
+
items: Iterable<T>,
|
|
45
|
+
events?: Iterable<Evt>
|
|
46
|
+
) => Effect<never, never, void>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export abstract class RepositoryBaseC1<
|
|
50
|
+
T extends { id: string },
|
|
51
|
+
PM extends { id: string },
|
|
52
|
+
Evt,
|
|
53
|
+
ItemType extends string
|
|
54
|
+
> extends RepositoryBaseC<T, PM, Evt, ItemType> {
|
|
55
|
+
constructor(
|
|
56
|
+
public readonly itemType: ItemType
|
|
57
|
+
) {
|
|
58
|
+
super()
|
|
58
59
|
}
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
export class RepositoryBaseC2<T extends { id: string }, PM extends { id: string }, Evt, ItemType extends string>
|
|
63
|
+
extends RepositoryBaseC1<T, PM, Evt, ItemType>
|
|
64
|
+
{
|
|
65
|
+
constructor(
|
|
66
|
+
itemType: ItemType,
|
|
67
|
+
protected readonly impl: Repository<T, PM, Evt, ItemType>
|
|
68
|
+
) {
|
|
69
|
+
super(itemType)
|
|
70
|
+
}
|
|
71
|
+
// makes super calls a compiler error, as it should
|
|
72
|
+
override saveAndPublish = this.impl.saveAndPublish
|
|
73
|
+
override removeAndPublish = this.impl.removeAndPublish
|
|
74
|
+
override find = this.impl.find
|
|
75
|
+
override all = this.impl.all
|
|
76
|
+
override utils = this.impl.utils
|
|
77
|
+
override changeFeed = this.impl.changeFeed
|
|
78
|
+
}
|
|
79
|
+
|
|
61
80
|
/**
|
|
62
81
|
* A base implementation to create a repository.
|
|
63
82
|
*/
|
|
64
83
|
export function makeRepo<
|
|
65
84
|
PM extends { id: string; _etag: string | undefined },
|
|
66
|
-
Evt =
|
|
85
|
+
Evt = never
|
|
67
86
|
>() {
|
|
68
87
|
return <
|
|
69
88
|
ItemType extends string,
|
|
@@ -97,14 +116,14 @@ export function makeRepo<
|
|
|
97
116
|
const mkStore = makeStore<PM>()(name, schema, mapTo)
|
|
98
117
|
|
|
99
118
|
function make<R = never, E = never, R2 = never>(
|
|
100
|
-
args: [Evt] extends [
|
|
101
|
-
publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<R2, never, void>
|
|
119
|
+
args: [Evt] extends [never] ? {
|
|
102
120
|
makeInitial?: Effect<R, E, readonly T[]>
|
|
103
121
|
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
104
122
|
partitionValue?: (a: PM) => string
|
|
105
123
|
}
|
|
106
124
|
}
|
|
107
125
|
: {
|
|
126
|
+
publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<R2, never, void>
|
|
108
127
|
makeInitial?: Effect<R, E, readonly T[]>
|
|
109
128
|
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
110
129
|
partitionValue?: (a: PM) => string
|
|
@@ -326,49 +345,85 @@ export function makeStore<
|
|
|
326
345
|
}
|
|
327
346
|
}
|
|
328
347
|
|
|
348
|
+
type Repos<
|
|
349
|
+
Service,
|
|
350
|
+
Out,
|
|
351
|
+
T extends { id: string },
|
|
352
|
+
PM extends { id: string; _etag: string | undefined },
|
|
353
|
+
Evt
|
|
354
|
+
> = {
|
|
355
|
+
make<R = never, E = never, R2 = never>(
|
|
356
|
+
args: [Evt] extends [never] ? {
|
|
357
|
+
makeInitial?: Effect<R, E, readonly T[]>
|
|
358
|
+
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
359
|
+
partitionValue?: (a: PM) => string
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
: {
|
|
363
|
+
publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<R2, never, void>
|
|
364
|
+
makeInitial?: Effect<R, E, readonly T[]>
|
|
365
|
+
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
366
|
+
partitionValue?: (a: PM) => string
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
): Effect<
|
|
370
|
+
StoreMaker | ContextMapContainer | R | R2,
|
|
371
|
+
E,
|
|
372
|
+
Out
|
|
373
|
+
>
|
|
374
|
+
where: ReturnType<typeof makeWhere<PM>>
|
|
375
|
+
flatMap: <R1, E1, B>(f: (a: Service) => Effect<R1, E1, B>) => Effect<Service | R1, E1, B>
|
|
376
|
+
makeLayer: (svc: Service) => Layer<never, never, Service>
|
|
377
|
+
map: <B>(f: (a: Service) => B) => Effect<Service, never, B>
|
|
378
|
+
}
|
|
379
|
+
|
|
329
380
|
export const RepositoryBaseImpl = <Service>() => {
|
|
330
381
|
return <
|
|
331
382
|
PM extends { id: string; _etag: string | undefined },
|
|
332
|
-
Evt =
|
|
383
|
+
Evt = never
|
|
333
384
|
>() =>
|
|
334
385
|
<ItemType extends string, T extends { id: string }, ConstructorInput, Api, E extends { id: string }>(
|
|
335
386
|
itemType: ItemType,
|
|
336
387
|
schema: Schema.Schema<unknown, T, ConstructorInput, E, Api>,
|
|
337
388
|
mapFrom: (pm: Omit<PM, "_etag">) => E,
|
|
338
389
|
mapTo: (e: E, etag: string | undefined) => PM
|
|
339
|
-
):
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
351
|
-
partitionValue?: (a: PM) => string
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
): Effect<StoreMaker | ContextMapContainer | R | R2, E, Repository<T, PM, Evt, ItemType>>
|
|
355
|
-
where: ReturnType<typeof makeWhere<PM>>
|
|
356
|
-
flatMap: <R1, E1, B>(f: (a: Service) => Effect<R1, E1, B>) => Effect<Service | R1, E1, B>
|
|
357
|
-
makeLayer: (svc: Service) => Layer<never, never, Service>
|
|
358
|
-
map: <B>(f: (a: Service) => B) => Effect<Service, never, B>
|
|
359
|
-
} => {
|
|
390
|
+
):
|
|
391
|
+
& (abstract new() => Omit<RepositoryBaseC1<T, PM, Evt, ItemType>, "impl">)
|
|
392
|
+
& Tag<Service, Service>
|
|
393
|
+
& Repos<
|
|
394
|
+
Service,
|
|
395
|
+
Repository<T, PM, Evt, ItemType>,
|
|
396
|
+
T,
|
|
397
|
+
PM,
|
|
398
|
+
Evt
|
|
399
|
+
> =>
|
|
400
|
+
{
|
|
360
401
|
const mkRepo = makeRepo<PM, Evt>()(itemType, schema, mapFrom, mapTo)
|
|
361
|
-
abstract class Cls extends
|
|
402
|
+
abstract class Cls extends RepositoryBaseC1<T, PM, Evt, ItemType> {
|
|
403
|
+
constructor() {
|
|
404
|
+
super(itemType)
|
|
405
|
+
}
|
|
362
406
|
static readonly make = mkRepo.make
|
|
407
|
+
|
|
408
|
+
static readonly where = makeWhere<PM>()
|
|
409
|
+
static flatMap<R1, E1, B>(f: (a: Service) => Effect<R1, E1, B>): Effect<Service | R1, E1, B> {
|
|
410
|
+
return Effect.flatMap(this as unknown as Tag<Service, Service>, f)
|
|
411
|
+
}
|
|
412
|
+
static map<B>(f: (a: Service) => B): Effect<Service, never, B> {
|
|
413
|
+
return Effect.map(this as unknown as Tag<Service, Service>, f)
|
|
414
|
+
}
|
|
415
|
+
static makeLayer(svc: Service) {
|
|
416
|
+
return Layer.succeed(this as unknown as Tag<Service, Service>, svc)
|
|
417
|
+
}
|
|
363
418
|
}
|
|
364
|
-
return Cls
|
|
419
|
+
return assignTag<Service>()(Cls)
|
|
365
420
|
}
|
|
366
421
|
}
|
|
367
422
|
|
|
368
423
|
export const RepositoryDefaultImpl = <Service>() => {
|
|
369
424
|
return <
|
|
370
425
|
PM extends { id: string; _etag: string | undefined },
|
|
371
|
-
Evt =
|
|
426
|
+
Evt = never
|
|
372
427
|
>() =>
|
|
373
428
|
<ItemType extends string, T extends { id: string }, ConstructorInput, Api, E extends { id: string }>(
|
|
374
429
|
itemType: ItemType,
|
|
@@ -376,88 +431,56 @@ export const RepositoryDefaultImpl = <Service>() => {
|
|
|
376
431
|
mapFrom: (pm: Omit<PM, "_etag">) => E,
|
|
377
432
|
mapTo: (e: E, etag: string | undefined) => PM
|
|
378
433
|
):
|
|
434
|
+
& (abstract new(
|
|
435
|
+
impl: Repository<T, PM, Evt, ItemType>
|
|
436
|
+
) => RepositoryBaseC2<T, PM, Evt, ItemType>)
|
|
379
437
|
& Tag<Service, Service>
|
|
380
|
-
&
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
makeLayer: (svc: Service) => Layer<never, never, Service>
|
|
388
|
-
map: <B>(f: (a: Service) => B) => Effect<Service, never, B>
|
|
389
|
-
repo: Repository<T, PM, Evt, ItemType> // just a helper to type the constructor
|
|
390
|
-
}
|
|
391
|
-
& ([Evt] extends [object] ? {
|
|
392
|
-
make<R = never, E = never, R2 = never>(
|
|
393
|
-
args: {
|
|
394
|
-
publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<R2, never, void>
|
|
395
|
-
makeInitial?: Effect<R, E, readonly T[]>
|
|
396
|
-
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
397
|
-
partitionValue?: (a: PM) => string
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
): Effect<StoreMaker | R | R2, E, Repository<T, PM, Evt, ItemType>>
|
|
401
|
-
|
|
402
|
-
toLayer<R = never, E = never, R2 = never>(
|
|
403
|
-
args: {
|
|
404
|
-
publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<R2, never, void>
|
|
405
|
-
makeInitial?: Effect<R, E, readonly T[]>
|
|
406
|
-
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
407
|
-
partitionValue?: (a: PM) => string
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
): Layer<StoreMaker | R | R2, E, Service>
|
|
411
|
-
}
|
|
412
|
-
: {
|
|
413
|
-
make<R = never, E = never>(
|
|
414
|
-
args: {
|
|
415
|
-
makeInitial?: Effect<R, E, readonly T[]>
|
|
416
|
-
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
417
|
-
partitionValue?: (a: PM) => string
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
): Effect<StoreMaker | R, E, Repository<T, PM, Evt, ItemType>>
|
|
421
|
-
toLayer<R = never, E = never>(
|
|
422
|
-
args: {
|
|
423
|
-
makeInitial?: Effect<R, E, readonly T[]>
|
|
424
|
-
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
425
|
-
partitionValue?: (a: PM) => string
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
): Layer<StoreMaker | R, E, Service>
|
|
429
|
-
}) =>
|
|
438
|
+
& Repos<
|
|
439
|
+
Service,
|
|
440
|
+
RepositoryBaseC2<T, PM, Evt, ItemType>,
|
|
441
|
+
T,
|
|
442
|
+
PM,
|
|
443
|
+
Evt
|
|
444
|
+
> =>
|
|
430
445
|
{
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
args: [Evt] extends [object] ? {
|
|
434
|
-
publishEvents: (evt: NonEmptyReadonlyArray<Evt>) => Effect<R2, never, void>
|
|
435
|
-
makeInitial?: Effect<R, E, readonly T[]>
|
|
436
|
-
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
437
|
-
partitionValue?: (a: PM) => string
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
: {
|
|
441
|
-
makeInitial?: Effect<R, E, readonly T[]>
|
|
442
|
-
config?: Omit<StoreConfig<PM>, "partitionValue"> & {
|
|
443
|
-
partitionValue?: (a: PM) => string
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
) {
|
|
447
|
-
return this
|
|
448
|
-
.make(args)
|
|
449
|
-
.map((impl) => new this(impl) as any as Service)
|
|
450
|
-
.toLayer(
|
|
451
|
-
this
|
|
452
|
-
)
|
|
453
|
-
}
|
|
454
|
-
static repo: any
|
|
446
|
+
const mkRepo = makeRepo<PM, Evt>()(itemType, schema, mapFrom, mapTo)
|
|
447
|
+
abstract class Cls extends RepositoryBaseC2<T, PM, Evt, ItemType> {
|
|
455
448
|
constructor(
|
|
456
449
|
impl: Repository<T, PM, Evt, ItemType>
|
|
457
450
|
) {
|
|
458
|
-
super()
|
|
459
|
-
|
|
451
|
+
super(itemType, impl)
|
|
452
|
+
}
|
|
453
|
+
static readonly make = mkRepo.make
|
|
454
|
+
|
|
455
|
+
static readonly where = makeWhere<PM>()
|
|
456
|
+
static flatMap<R1, E1, B>(f: (a: Service) => Effect<R1, E1, B>): Effect<Service | R1, E1, B> {
|
|
457
|
+
return Effect.flatMap(this as unknown as Tag<Service, Service>, f)
|
|
460
458
|
}
|
|
461
|
-
|
|
459
|
+
static map<B>(f: (a: Service) => B): Effect<Service, never, B> {
|
|
460
|
+
return Effect.map(this as unknown as Tag<Service, Service>, f)
|
|
461
|
+
}
|
|
462
|
+
static makeLayer(svc: Service) {
|
|
463
|
+
return Layer.succeed(this as unknown as Tag<Service, Service>, svc)
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return assignTag<Service>()(Cls) as any // impl is missing, but its marked protected
|
|
462
467
|
}
|
|
463
468
|
}
|
|
469
|
+
|
|
470
|
+
// @useClassFeaturesForSchema
|
|
471
|
+
// export class Shop extends Model<Shop>()({ id: string }) {}
|
|
472
|
+
|
|
473
|
+
// /**
|
|
474
|
+
// * @tsplus type ShopRepo
|
|
475
|
+
// * @tsplus companion ShopRepo.Ops
|
|
476
|
+
// */
|
|
477
|
+
// export class ShopRepo extends RepositoryDefaultImpl<ShopRepo>()<Shop & { _etag: string | undefined }>()(
|
|
478
|
+
// "Shop",
|
|
479
|
+
// Shop,
|
|
480
|
+
// (pm) => pm,
|
|
481
|
+
// (e, _etag) => ({ ...e, _etag })
|
|
482
|
+
// ) {
|
|
483
|
+
// override saveAndPublish = (items: Iterable<Shop>, events?: Iterable<unknown> | undefined) => {
|
|
484
|
+
// return this.impl.saveAndPublish(items, events)
|
|
485
|
+
// }
|
|
486
|
+
// }
|