@effect-app/infra 2.11.0 → 2.12.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 +6 -0
- package/_cjs/Model/Repository/ext.cjs +1 -1
- package/_cjs/Model/Repository/ext.cjs.map +1 -1
- package/_cjs/Model/Repository/internal/internal.cjs +18 -20
- package/_cjs/Model/Repository/internal/internal.cjs.map +1 -1
- package/_cjs/Model/Repository/makeRepo.cjs.map +1 -1
- package/_cjs/Store/Cosmos/query.cjs +9 -2
- package/_cjs/Store/Cosmos/query.cjs.map +1 -1
- package/_cjs/Store/Cosmos.cjs +49 -23
- package/_cjs/Store/Cosmos.cjs.map +1 -1
- package/_cjs/Store/Disk.cjs +5 -5
- package/_cjs/Store/Disk.cjs.map +1 -1
- package/_cjs/Store/Memory.cjs +9 -9
- package/_cjs/Store/Memory.cjs.map +1 -1
- package/_cjs/Store/codeFilter.cjs.map +1 -1
- package/_cjs/Store/service.cjs.map +1 -1
- package/_cjs/Store/utils.cjs +3 -3
- package/_cjs/Store/utils.cjs.map +1 -1
- package/dist/Model/Repository/ext.d.ts +6 -9
- package/dist/Model/Repository/ext.d.ts.map +1 -1
- package/dist/Model/Repository/ext.js +2 -2
- package/dist/Model/Repository/internal/internal.d.ts +4 -9
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +19 -21
- package/dist/Model/Repository/legacy.d.ts +2 -6
- package/dist/Model/Repository/legacy.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.d.ts +4 -9
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.js +1 -1
- package/dist/Model/Repository/service.d.ts +1 -3
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/QueueMaker/sbqueue.d.ts +2 -2
- package/dist/Store/Cosmos/query.d.ts +1 -1
- package/dist/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/Store/Cosmos/query.js +7 -3
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +43 -23
- package/dist/Store/Disk.d.ts +2 -3
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +6 -6
- package/dist/Store/Memory.d.ts +4 -9
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +12 -12
- package/dist/Store/codeFilter.d.ts +2 -3
- package/dist/Store/codeFilter.d.ts.map +1 -1
- package/dist/Store/codeFilter.js +1 -1
- package/dist/Store/service.d.ts +9 -23
- package/dist/Store/service.d.ts.map +1 -1
- package/dist/Store/service.js +1 -1
- package/dist/Store/utils.d.ts +1 -3
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +4 -4
- package/package.json +1 -1
- package/src/Model/Repository/ext.ts +6 -5
- package/src/Model/Repository/internal/internal.ts +37 -36
- package/src/Model/Repository/legacy.ts +2 -2
- package/src/Model/Repository/makeRepo.ts +8 -9
- package/src/Model/Repository/service.ts +1 -1
- package/src/Store/Cosmos/query.ts +6 -1
- package/src/Store/Cosmos.ts +85 -48
- package/src/Store/Disk.ts +20 -8
- package/src/Store/Memory.ts +25 -16
- package/src/Store/codeFilter.ts +2 -1
- package/src/Store/service.ts +8 -7
- package/src/Store/utils.ts +4 -3
package/src/Store/Memory.ts
CHANGED
|
@@ -5,12 +5,13 @@ import type { NonEmptyReadonlyArray } from "effect-app"
|
|
|
5
5
|
import { NonEmptyString255 } from "effect-app/Schema"
|
|
6
6
|
import { get } from "effect-app/utils"
|
|
7
7
|
import { InfraLogger } from "../logger.js"
|
|
8
|
+
import type { FieldValues } from "../Model/filter/types.js"
|
|
8
9
|
import { codeFilter } from "./codeFilter.js"
|
|
9
10
|
import type { FilterArgs, PersistenceModelType, Store, StoreConfig } from "./service.js"
|
|
10
11
|
import { StoreMaker } from "./service.js"
|
|
11
12
|
import { makeUpdateETag } from "./utils.js"
|
|
12
13
|
|
|
13
|
-
export function memFilter<T extends
|
|
14
|
+
export function memFilter<T extends FieldValues, U extends keyof T = never>(f: FilterArgs<T, U>) {
|
|
14
15
|
type M = U extends undefined ? T : Pick<T, U>
|
|
15
16
|
return ((c: T[]): M[] => {
|
|
16
17
|
const select = (r: T[]): M[] => (f.select ? r.map(Struct.pick(...f.select)) : r) as any
|
|
@@ -76,8 +77,9 @@ function logQuery(f: FilterArgs<any, any>, defaultValues?: any) {
|
|
|
76
77
|
}))
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
export function makeMemoryStoreInt<
|
|
80
|
+
export function makeMemoryStoreInt<IdKey extends keyof Encoded, Encoded extends FieldValues, R = never, E = never>(
|
|
80
81
|
modelName: string,
|
|
82
|
+
idKey: IdKey,
|
|
81
83
|
namespace: string,
|
|
82
84
|
seed?: Effect<Iterable<Encoded>, E, R>,
|
|
83
85
|
_defaultValues?: Partial<Encoded>
|
|
@@ -88,8 +90,8 @@ export function makeMemoryStoreInt<Id extends string, Encoded extends { id: Id }
|
|
|
88
90
|
const items_ = yield* seed ?? Effect.sync(() => [])
|
|
89
91
|
const defaultValues = _defaultValues ?? {}
|
|
90
92
|
|
|
91
|
-
const items = new Map([...items_].map((_) => [_
|
|
92
|
-
const store = Ref.unsafeMake<ReadonlyMap<
|
|
93
|
+
const items = new Map([...items_].map((_) => [_[idKey], { _etag: undefined, ...defaultValues, ..._ }] as const))
|
|
94
|
+
const store = Ref.unsafeMake<ReadonlyMap<string, PM>>(items)
|
|
93
95
|
const sem = Effect.unsafeMakeSemaphore(1)
|
|
94
96
|
const withPermit = sem.withPermits(1)
|
|
95
97
|
const values = Effect.map(Ref.get(store), (s) => s.values())
|
|
@@ -98,7 +100,7 @@ export function makeMemoryStoreInt<Id extends string, Encoded extends { id: Id }
|
|
|
98
100
|
|
|
99
101
|
const batchSet = (items: NonEmptyReadonlyArray<PM>) =>
|
|
100
102
|
Effect
|
|
101
|
-
.forEach(items, (i) => Effect.flatMap(s.find(i
|
|
103
|
+
.forEach(items, (i) => Effect.flatMap(s.find(i[idKey]), (current) => updateETag(i, idKey, current)))
|
|
102
104
|
.pipe(
|
|
103
105
|
Effect
|
|
104
106
|
.tap((items) =>
|
|
@@ -107,8 +109,8 @@ export function makeMemoryStoreInt<Id extends string, Encoded extends { id: Id }
|
|
|
107
109
|
.pipe(
|
|
108
110
|
Effect
|
|
109
111
|
.map((m) => {
|
|
110
|
-
const mut = m as Map<
|
|
111
|
-
items.forEach((e) => mut.set(e
|
|
112
|
+
const mut = m as Map<string, PM>
|
|
113
|
+
items.forEach((e) => mut.set(e[idKey], e))
|
|
112
114
|
return mut
|
|
113
115
|
}),
|
|
114
116
|
Effect
|
|
@@ -119,7 +121,7 @@ export function makeMemoryStoreInt<Id extends string, Encoded extends { id: Id }
|
|
|
119
121
|
.map((_) => _),
|
|
120
122
|
withPermit
|
|
121
123
|
)
|
|
122
|
-
const s: Store<
|
|
124
|
+
const s: Store<IdKey, Encoded> = {
|
|
123
125
|
all: all.pipe(Effect.withSpan("Memory.all [effect-app/infra/Store]", {
|
|
124
126
|
captureStackTrace: false,
|
|
125
127
|
attributes: {
|
|
@@ -153,13 +155,13 @@ export function makeMemoryStoreInt<Id extends string, Encoded extends { id: Id }
|
|
|
153
155
|
),
|
|
154
156
|
set: (e) =>
|
|
155
157
|
s
|
|
156
|
-
.find(e
|
|
158
|
+
.find(e[idKey])
|
|
157
159
|
.pipe(
|
|
158
|
-
Effect.flatMap((current) => updateETag(e, current)),
|
|
160
|
+
Effect.flatMap((current) => updateETag(e, idKey, current)),
|
|
159
161
|
Effect
|
|
160
162
|
.tap((e) =>
|
|
161
163
|
Ref.get(store).pipe(
|
|
162
|
-
Effect.map((_) => new Map([..._, [e
|
|
164
|
+
Effect.map((_) => new Map([..._, [e[idKey], e]])),
|
|
163
165
|
Effect.flatMap((_) => Ref.set(store, _))
|
|
164
166
|
)
|
|
165
167
|
),
|
|
@@ -197,7 +199,7 @@ export function makeMemoryStoreInt<Id extends string, Encoded extends { id: Id }
|
|
|
197
199
|
Ref
|
|
198
200
|
.get(store)
|
|
199
201
|
.pipe(
|
|
200
|
-
Effect.map((_) => new Map([..._].filter(([_]) => _ !== e
|
|
202
|
+
Effect.map((_) => new Map([..._].filter(([_]) => _ !== e[idKey]))),
|
|
201
203
|
Effect.flatMap((_) => Ref.set(store, _)),
|
|
202
204
|
withPermit,
|
|
203
205
|
Effect.withSpan("Memory.remove [effect-app/infra/Store]", {
|
|
@@ -211,14 +213,21 @@ export function makeMemoryStoreInt<Id extends string, Encoded extends { id: Id }
|
|
|
211
213
|
}
|
|
212
214
|
|
|
213
215
|
export const makeMemoryStore = () => ({
|
|
214
|
-
make: <
|
|
216
|
+
make: <IdKey extends keyof Encoded, Encoded extends FieldValues, R, E>(
|
|
215
217
|
modelName: string,
|
|
218
|
+
idKey: IdKey,
|
|
216
219
|
seed?: Effect<Iterable<Encoded>, E, R>,
|
|
217
220
|
config?: StoreConfig<Encoded>
|
|
218
221
|
) =>
|
|
219
222
|
Effect.gen(function*() {
|
|
220
223
|
const storesSem = Effect.unsafeMakeSemaphore(1)
|
|
221
|
-
const primary = yield* makeMemoryStoreInt<
|
|
224
|
+
const primary = yield* makeMemoryStoreInt<IdKey, Encoded, R, E>(
|
|
225
|
+
modelName,
|
|
226
|
+
idKey,
|
|
227
|
+
"primary",
|
|
228
|
+
seed,
|
|
229
|
+
config?.defaultValues
|
|
230
|
+
)
|
|
222
231
|
const ctx = yield* Effect.context<R>()
|
|
223
232
|
const stores = new Map([["primary", primary]])
|
|
224
233
|
const getStore = !config?.allowNamespace
|
|
@@ -234,7 +243,7 @@ export const makeMemoryStore = () => ({
|
|
|
234
243
|
return storesSem.withPermits(1)(Effect.suspend(() => {
|
|
235
244
|
const store = stores.get(namespace)
|
|
236
245
|
if (store) return Effect.sync(() => store)
|
|
237
|
-
return makeMemoryStoreInt(modelName, namespace, seed, config?.defaultValues)
|
|
246
|
+
return makeMemoryStoreInt(modelName, idKey, namespace, seed, config?.defaultValues)
|
|
238
247
|
.pipe(
|
|
239
248
|
Effect.orDie,
|
|
240
249
|
Effect.provide(ctx),
|
|
@@ -242,7 +251,7 @@ export const makeMemoryStore = () => ({
|
|
|
242
251
|
)
|
|
243
252
|
}))
|
|
244
253
|
}))
|
|
245
|
-
const s: Store<
|
|
254
|
+
const s: Store<IdKey, Encoded> = {
|
|
246
255
|
all: Effect.flatMap(getStore, (_) => _.all),
|
|
247
256
|
find: (...args) => Effect.flatMap(getStore, (_) => _.find(...args)),
|
|
248
257
|
filter: (...args) => Effect.flatMap(getStore, (_) => _.filter(...args)),
|
package/src/Store/codeFilter.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { Array, Option } from "effect-app"
|
|
4
4
|
import { assertUnreachable, get } from "effect-app/utils"
|
|
5
5
|
import type { FilterR, FilterResult } from "../Model/filter/filterApi.js"
|
|
6
|
+
import type { FieldValues } from "../Model/filter/types.js"
|
|
6
7
|
import type { Filter } from "./service.js"
|
|
7
8
|
import { compare, greaterThan, greaterThanExclusive, lowerThan, lowerThanExclusive } from "./utils.js"
|
|
8
9
|
|
|
@@ -120,6 +121,6 @@ export const codeFilter3_ = <E>(state: readonly FilterResult[], sut: E): boolean
|
|
|
120
121
|
return eval(s)
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
export function codeFilter<E extends
|
|
124
|
+
export function codeFilter<E extends FieldValues, NE extends E>(filter: Filter) {
|
|
124
125
|
return (x: E) => codeFilter3_(filter, x) ? Option.some(x as unknown as NE) : Option.none()
|
|
125
126
|
}
|
package/src/Store/service.ts
CHANGED
|
@@ -57,7 +57,7 @@ export interface O<TFieldValues extends FieldValues> {
|
|
|
57
57
|
direction: "ASC" | "DESC"
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
export interface FilterArgs<Encoded extends
|
|
60
|
+
export interface FilterArgs<Encoded extends FieldValues, U extends keyof Encoded = never> {
|
|
61
61
|
t: Encoded
|
|
62
62
|
filter?: Filter | undefined
|
|
63
63
|
select?: NonEmptyReadonlyArray<U> | undefined
|
|
@@ -66,18 +66,18 @@ export interface FilterArgs<Encoded extends { id: string }, U extends keyof Enco
|
|
|
66
66
|
skip?: number | undefined
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
export type FilterFunc<Encoded extends
|
|
69
|
+
export type FilterFunc<Encoded extends FieldValues> = <U extends keyof Encoded = never>(
|
|
70
70
|
args: FilterArgs<Encoded, U>
|
|
71
71
|
) => Effect<(U extends undefined ? Encoded : Pick<Encoded, U>)[]>
|
|
72
72
|
|
|
73
73
|
export interface Store<
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
IdKey extends keyof Encoded,
|
|
75
|
+
Encoded extends FieldValues,
|
|
76
76
|
PM extends PersistenceModelType<Encoded> = PersistenceModelType<Encoded>
|
|
77
77
|
> {
|
|
78
78
|
all: Effect<PM[]>
|
|
79
79
|
filter: FilterFunc<Encoded>
|
|
80
|
-
find: (id:
|
|
80
|
+
find: (id: Encoded[IdKey]) => Effect<Option<PM>>
|
|
81
81
|
set: (e: PM) => Effect<PM, OptimisticConcurrencyException>
|
|
82
82
|
batchSet: (
|
|
83
83
|
items: NonEmptyReadonlyArray<PM>
|
|
@@ -96,11 +96,12 @@ export interface Store<
|
|
|
96
96
|
* @tsplus companion StoreMaker.Ops
|
|
97
97
|
*/
|
|
98
98
|
export class StoreMaker extends Context.TagId("effect-app/StoreMaker")<StoreMaker, {
|
|
99
|
-
make: <
|
|
99
|
+
make: <IdKey extends keyof Encoded, Encoded extends FieldValues, R = never, E = never>(
|
|
100
100
|
name: string,
|
|
101
|
+
idKey: IdKey,
|
|
101
102
|
seed?: Effect<Iterable<Encoded>, E, R>,
|
|
102
103
|
config?: StoreConfig<Encoded>
|
|
103
|
-
) => Effect<Store<
|
|
104
|
+
) => Effect<Store<IdKey, Encoded>, E, R>
|
|
104
105
|
}>() {
|
|
105
106
|
}
|
|
106
107
|
|
package/src/Store/utils.ts
CHANGED
|
@@ -13,18 +13,19 @@ export const makeETag = <E extends PersistenceModelType<{}>>(
|
|
|
13
13
|
}) as any
|
|
14
14
|
|
|
15
15
|
export const makeUpdateETag =
|
|
16
|
-
(type: string) =>
|
|
16
|
+
(type: string) =>
|
|
17
|
+
<IdKey extends keyof E, E extends PersistenceModelType<{}>>(e: E, idKey: IdKey, current: Option<E>) =>
|
|
17
18
|
Effect.gen(function*() {
|
|
18
19
|
if (e._etag) {
|
|
19
20
|
yield* Effect.mapError(
|
|
20
21
|
current,
|
|
21
|
-
() => new OptimisticConcurrencyException({ type, id: e
|
|
22
|
+
() => new OptimisticConcurrencyException({ type, id: e[idKey] as string, current: "", found: e._etag })
|
|
22
23
|
)
|
|
23
24
|
}
|
|
24
25
|
if (Option.isSome(current) && current.value._etag !== e._etag) {
|
|
25
26
|
return yield* new OptimisticConcurrencyException({
|
|
26
27
|
type,
|
|
27
|
-
id: current.value
|
|
28
|
+
id: current.value[idKey] as string,
|
|
28
29
|
current: current.value._etag,
|
|
29
30
|
found: e._etag
|
|
30
31
|
})
|