@effect-app/infra 0.210.11 → 0.211.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 +13 -0
- package/_cjs/services/RepositoryBase.cjs +0 -22
- package/_cjs/services/RepositoryBase.cjs.map +1 -1
- package/_cjs/services/Store/Cosmos/query.cjs +0 -137
- package/_cjs/services/Store/Cosmos/query.cjs.map +1 -1
- package/_cjs/services/Store/Cosmos.cjs +5 -35
- package/_cjs/services/Store/Cosmos.cjs.map +1 -1
- package/_cjs/services/Store/Disk.cjs +0 -1
- package/_cjs/services/Store/Disk.cjs.map +1 -1
- package/_cjs/services/Store/Memory.cjs +0 -6
- package/_cjs/services/Store/Memory.cjs.map +1 -1
- package/_cjs/services/Store/service.cjs.map +1 -1
- package/_cjs/services/Store/utils.cjs +1 -106
- package/_cjs/services/Store/utils.cjs.map +1 -1
- package/dist/services/RepositoryBase.d.ts +3 -60
- package/dist/services/RepositoryBase.d.ts.map +1 -1
- package/dist/services/RepositoryBase.js +1 -22
- package/dist/services/Store/Cosmos/query.d.ts +1 -45
- package/dist/services/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/services/Store/Cosmos/query.js +1 -145
- package/dist/services/Store/Cosmos.d.ts.map +1 -1
- package/dist/services/Store/Cosmos.js +18 -61
- package/dist/services/Store/Disk.d.ts.map +1 -1
- package/dist/services/Store/Disk.js +1 -2
- package/dist/services/Store/Memory.d.ts.map +1 -1
- package/dist/services/Store/Memory.js +2 -10
- package/dist/services/Store/filterApi/query.d.ts +1 -1
- package/dist/services/Store/filterApi/query.d.ts.map +1 -1
- package/dist/services/Store/service.d.ts +1 -38
- package/dist/services/Store/service.d.ts.map +1 -1
- package/dist/services/Store/service.js +1 -1
- package/dist/services/Store/utils.d.ts +1 -6
- package/dist/services/Store/utils.d.ts.map +1 -1
- package/dist/services/Store/utils.js +3 -140
- package/dist/services/query/dsl.d.ts +2 -2
- package/dist/services/query/dsl.d.ts.map +1 -1
- package/package.json +4 -14
- package/src/services/RepositoryBase.ts +1 -34
- package/src/services/Store/Cosmos/query.ts +1 -203
- package/src/services/Store/Cosmos.ts +38 -135
- package/src/services/Store/Disk.ts +0 -1
- package/src/services/Store/Memory.ts +2 -17
- package/src/services/Store/Redis.ts.bak +2 -4
- package/src/services/Store/filterApi/query.ts +2 -2
- package/src/services/Store/service.ts +1 -35
- package/src/services/Store/utils.ts +3 -152
- package/src/services/query/dsl.ts +4 -4
- package/_cjs/filter.cjs +0 -363
- package/_cjs/filter.cjs.map +0 -1
- package/_cjs/services/Store/Cosmos.test.cjs +0 -55
- package/_cjs/services/Store/Cosmos.test.cjs.map +0 -1
- package/_cjs/services/Store/codeFilter.test.cjs +0 -63
- package/_cjs/services/Store/codeFilter.test.cjs.map +0 -1
- package/dist/filter.d.ts +0 -142
- package/dist/filter.d.ts.map +0 -1
- package/dist/filter.js +0 -248
- package/dist/services/Store/Cosmos.test.d.ts.map +0 -1
- package/dist/services/Store/codeFilter.test.d.ts.map +0 -1
- package/src/filter.ts +0 -420
- package/src/services/Store/Cosmos.test.ts +0 -94
- package/src/services/Store/codeFilter.test.ts +0 -166
|
@@ -2,7 +2,7 @@ import { Effect, Equivalence, pipe, ReadonlyArray } from "effect-app"
|
|
|
2
2
|
import type { NonEmptyReadonlyArray } from "effect-app"
|
|
3
3
|
import { assertUnreachable } from "effect-app/utils"
|
|
4
4
|
import type { FilterR, FilterResult } from "../filterApi/query.js"
|
|
5
|
-
import type {
|
|
5
|
+
import type { SupportedValues } from "../service.js"
|
|
6
6
|
|
|
7
7
|
export function logQuery(q: {
|
|
8
8
|
query: string
|
|
@@ -26,208 +26,6 @@ export function logQuery(q: {
|
|
|
26
26
|
}))
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
/**
|
|
30
|
-
* @deprecated: should build Select into Where query
|
|
31
|
-
*/
|
|
32
|
-
export function buildFilterJoinSelectCosmosQuery(
|
|
33
|
-
filter: FilterJoinSelect,
|
|
34
|
-
k: string,
|
|
35
|
-
name: string,
|
|
36
|
-
skip?: number,
|
|
37
|
-
limit?: number
|
|
38
|
-
) {
|
|
39
|
-
const lm = skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""
|
|
40
|
-
return {
|
|
41
|
-
query: `
|
|
42
|
-
SELECT r, f.id as _rootId
|
|
43
|
-
FROM ${name} f
|
|
44
|
-
JOIN r IN f.${k}
|
|
45
|
-
WHERE r.${filter.valueKey} = @value
|
|
46
|
-
${lm}
|
|
47
|
-
`,
|
|
48
|
-
parameters: [{ name: "@value", value: filter.value }]
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* @deprecated: is now part of Where query as k.-1.valueKey
|
|
54
|
-
*/
|
|
55
|
-
export function buildFindJoinCosmosQuery(
|
|
56
|
-
filter: JoinFindFilter,
|
|
57
|
-
k: string,
|
|
58
|
-
name: string,
|
|
59
|
-
skip?: number,
|
|
60
|
-
limit?: number
|
|
61
|
-
) {
|
|
62
|
-
const lm = skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""
|
|
63
|
-
return {
|
|
64
|
-
query: `
|
|
65
|
-
SELECT DISTINCT VALUE f
|
|
66
|
-
FROM ${name} f
|
|
67
|
-
JOIN r IN f.${k}
|
|
68
|
-
WHERE r.${filter.valueKey} = @value
|
|
69
|
-
${lm}`,
|
|
70
|
-
parameters: [{ name: "@value", value: filter.value }]
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* @deprecated: should build into Where query
|
|
76
|
-
*/
|
|
77
|
-
export function buildLegacyCosmosQuery<PM>(
|
|
78
|
-
filter: LegacyFilter<PM>,
|
|
79
|
-
name: string,
|
|
80
|
-
importedMarkerId: string,
|
|
81
|
-
defaultValues: Record<string, unknown>,
|
|
82
|
-
skip?: number,
|
|
83
|
-
limit?: number
|
|
84
|
-
) {
|
|
85
|
-
if (Object.keys(defaultValues).length) {
|
|
86
|
-
throw new Error("defaultValues not supported with legacy cosmos query: " + JSON.stringify(defaultValues))
|
|
87
|
-
}
|
|
88
|
-
const lm = skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""
|
|
89
|
-
return {
|
|
90
|
-
query: `
|
|
91
|
-
SELECT f
|
|
92
|
-
FROM ${name} f
|
|
93
|
-
WHERE f.id != @id AND f.${
|
|
94
|
-
String(
|
|
95
|
-
filter.by
|
|
96
|
-
)
|
|
97
|
-
} LIKE @filter
|
|
98
|
-
${lm}`,
|
|
99
|
-
parameters: [
|
|
100
|
-
{ name: "@id", value: importedMarkerId },
|
|
101
|
-
{
|
|
102
|
-
name: "@filter",
|
|
103
|
-
value: filter.type === "endsWith"
|
|
104
|
-
? `%${filter.value}`
|
|
105
|
-
: filter.type === "contains"
|
|
106
|
-
? `%${filter.value}%`
|
|
107
|
-
: `${filter.value}%`
|
|
108
|
-
}
|
|
109
|
-
]
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export function buildWhereCosmosQuery(
|
|
114
|
-
filter: StoreWhereFilter,
|
|
115
|
-
name: string,
|
|
116
|
-
importedMarkerId: string,
|
|
117
|
-
defaultValues: Record<string, unknown>,
|
|
118
|
-
skip?: number,
|
|
119
|
-
limit?: number
|
|
120
|
-
) {
|
|
121
|
-
const lm = skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""
|
|
122
|
-
|
|
123
|
-
return {
|
|
124
|
-
query: `
|
|
125
|
-
SELECT f
|
|
126
|
-
FROM ${name} f
|
|
127
|
-
${
|
|
128
|
-
pipe(
|
|
129
|
-
filter
|
|
130
|
-
.where
|
|
131
|
-
.filter((_) => _.key.includes(".-1."))
|
|
132
|
-
.map((_) => _.key.split(".-1.")[0])
|
|
133
|
-
.map((_) => `JOIN ${_} IN f.${_}`),
|
|
134
|
-
ReadonlyArray.dedupeWith(Equivalence.string)
|
|
135
|
-
)
|
|
136
|
-
.join("\n")
|
|
137
|
-
}
|
|
138
|
-
WHERE f.id != @id AND ${
|
|
139
|
-
filter
|
|
140
|
-
.where
|
|
141
|
-
.map((_) =>
|
|
142
|
-
_.key.includes(".-1.")
|
|
143
|
-
? { ..._, f: _.key.split(".-1.")[0], key: _.key.split(".-1.")[1]! }
|
|
144
|
-
: { ..._, f: "f" }
|
|
145
|
-
)
|
|
146
|
-
.map(
|
|
147
|
-
(x, i) => {
|
|
148
|
-
let k = `${x.f}.${x.key}`
|
|
149
|
-
k = x.key in defaultValues ? `(${k} ?? ${JSON.stringify(defaultValues[x.key])})` : k
|
|
150
|
-
const v = `@v${i}`
|
|
151
|
-
|
|
152
|
-
switch (x.t) {
|
|
153
|
-
case "in":
|
|
154
|
-
return `ARRAY_CONTAINS(${v}, ${k})`
|
|
155
|
-
case "not-in":
|
|
156
|
-
return `(NOT ARRAY_CONTAINS(${v}, ${k}))`
|
|
157
|
-
|
|
158
|
-
case "includes":
|
|
159
|
-
return `ARRAY_CONTAINS(${k}, ${v})`
|
|
160
|
-
case "not-includes":
|
|
161
|
-
return `(NOT ARRAY_CONTAINS(${k}, ${v}))`
|
|
162
|
-
case "contains":
|
|
163
|
-
return `CONTAINS(${k}, ${v}, true)`
|
|
164
|
-
case "starts-with":
|
|
165
|
-
return `STARTSWITH(${k}, ${v}, true)`
|
|
166
|
-
case "ends-with":
|
|
167
|
-
return `ENDSWITH(${k}, ${v}, true)`
|
|
168
|
-
case "not-contains":
|
|
169
|
-
return `NOT(CONTAINS(${k}, ${v}, true))`
|
|
170
|
-
case "not-starts-with":
|
|
171
|
-
return `NOT(STARTSWITH(${k}, ${v}, true))`
|
|
172
|
-
case "not-ends-with":
|
|
173
|
-
return `NOT(ENDSWITH(${k}, ${v}, true))`
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
switch (x.t) {
|
|
177
|
-
case "lt":
|
|
178
|
-
return `${k} < ${v}`
|
|
179
|
-
case "lte":
|
|
180
|
-
return `${k} <= ${v}`
|
|
181
|
-
case "gt":
|
|
182
|
-
return `${k} > ${v}`
|
|
183
|
-
case "gte":
|
|
184
|
-
return `${k} >= ${v}`
|
|
185
|
-
case "not-eq":
|
|
186
|
-
return x.value === null
|
|
187
|
-
? `IS_NULL(${k}) = false`
|
|
188
|
-
: `${k} <> ${v}`
|
|
189
|
-
case undefined:
|
|
190
|
-
case "eq":
|
|
191
|
-
return x.value === null
|
|
192
|
-
? `IS_NULL(${k}) = true`
|
|
193
|
-
: `${k} = ${v}`
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
)
|
|
197
|
-
.join(filter.mode === "or" ? " OR " : " AND ")
|
|
198
|
-
}
|
|
199
|
-
${lm}`,
|
|
200
|
-
parameters: [
|
|
201
|
-
{ name: "@id", value: importedMarkerId },
|
|
202
|
-
...filter
|
|
203
|
-
.where
|
|
204
|
-
.map((x, i) => ({
|
|
205
|
-
name: `@v${i}`,
|
|
206
|
-
value: x.value
|
|
207
|
-
}))
|
|
208
|
-
]
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// function isArray(t: SupportedValues | readonly SupportedValues[]): t is readonly SupportedValues[] {
|
|
213
|
-
// return Array.isArray(t)
|
|
214
|
-
// }
|
|
215
|
-
|
|
216
|
-
export function buildCosmosQuery<PM>(
|
|
217
|
-
filter: LegacyFilter<PM> | StoreWhereFilter,
|
|
218
|
-
name: string,
|
|
219
|
-
importedMarkerId: string,
|
|
220
|
-
defaultValues: Record<string, unknown>,
|
|
221
|
-
skip?: number,
|
|
222
|
-
limit?: number
|
|
223
|
-
) {
|
|
224
|
-
return filter.type === "startsWith"
|
|
225
|
-
|| filter.type === "endsWith"
|
|
226
|
-
|| filter.type === "contains"
|
|
227
|
-
? buildLegacyCosmosQuery(filter, name, importedMarkerId, defaultValues, skip, limit)
|
|
228
|
-
: buildWhereCosmosQuery(filter, name, importedMarkerId, defaultValues, skip, limit)
|
|
229
|
-
}
|
|
230
|
-
|
|
231
29
|
export function buildWhereCosmosQuery3(
|
|
232
30
|
filter: readonly FilterResult[],
|
|
233
31
|
name: string,
|
|
@@ -4,24 +4,11 @@ import { toNonEmptyArray } from "@effect-app/core/Array"
|
|
|
4
4
|
import { CosmosClient, CosmosClientLayer } from "@effect-app/infra-adapters/cosmos-client"
|
|
5
5
|
import { Chunk, Duration, Effect, Layer, Option, ReadonlyArray, Secret } from "effect-app"
|
|
6
6
|
import type { NonEmptyReadonlyArray } from "effect-app"
|
|
7
|
-
import { dropUndefinedT, omit, pick
|
|
7
|
+
import { dropUndefinedT, omit, pick } from "effect-app/utils"
|
|
8
8
|
import { OptimisticConcurrencyException } from "../../errors.js"
|
|
9
|
-
import {
|
|
10
|
-
buildCosmosQuery,
|
|
11
|
-
buildFilterJoinSelectCosmosQuery,
|
|
12
|
-
buildFindJoinCosmosQuery,
|
|
13
|
-
buildWhereCosmosQuery3,
|
|
14
|
-
logQuery
|
|
15
|
-
} from "./Cosmos/query.js"
|
|
9
|
+
import { buildWhereCosmosQuery3, logQuery } from "./Cosmos/query.js"
|
|
16
10
|
import { StoreMaker } from "./service.js"
|
|
17
|
-
import type {
|
|
18
|
-
FilterArgs,
|
|
19
|
-
FilterJoinSelect,
|
|
20
|
-
PersistenceModelType,
|
|
21
|
-
StorageConfig,
|
|
22
|
-
Store,
|
|
23
|
-
StoreConfig
|
|
24
|
-
} from "./service.js"
|
|
11
|
+
import type { FilterArgs, PersistenceModelType, StorageConfig, Store, StoreConfig } from "./service.js"
|
|
25
12
|
|
|
26
13
|
class CosmosDbOperationError {
|
|
27
14
|
constructor(readonly message: string) {}
|
|
@@ -213,15 +200,14 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
213
200
|
parameters: [{ name: "@id", value: importedMarkerId }]
|
|
214
201
|
}))
|
|
215
202
|
.pipe(
|
|
216
|
-
Effect
|
|
217
|
-
.tap((q) => logQuery(q)),
|
|
203
|
+
Effect.tap((q) => logQuery(q)),
|
|
218
204
|
Effect.flatMap((q) =>
|
|
219
205
|
Effect.promise(() =>
|
|
220
206
|
container
|
|
221
207
|
.items
|
|
222
208
|
.query<PM>(q)
|
|
223
209
|
.fetchAll()
|
|
224
|
-
.then(({ resources }) => resources)
|
|
210
|
+
.then(({ resources }) => resources.map((_) => ({ ...defaultValues, ..._ })))
|
|
225
211
|
)
|
|
226
212
|
),
|
|
227
213
|
Effect
|
|
@@ -229,48 +215,6 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
229
215
|
attributes: { "repository.container_id": containerId, "repository.model_name": name }
|
|
230
216
|
})
|
|
231
217
|
),
|
|
232
|
-
filterJoinSelect: <T extends object>(
|
|
233
|
-
filter: FilterJoinSelect,
|
|
234
|
-
cursor?: { skip?: number; limit?: number }
|
|
235
|
-
) =>
|
|
236
|
-
Effect
|
|
237
|
-
.forEach(
|
|
238
|
-
filter
|
|
239
|
-
.keys,
|
|
240
|
-
(k) =>
|
|
241
|
-
Effect
|
|
242
|
-
.sync(() => buildFilterJoinSelectCosmosQuery(filter, k, name, cursor?.skip, cursor?.limit))
|
|
243
|
-
.pipe(
|
|
244
|
-
Effect
|
|
245
|
-
.tap((q) => logQuery(q)),
|
|
246
|
-
Effect.flatMap((q) =>
|
|
247
|
-
Effect.promise(() =>
|
|
248
|
-
container
|
|
249
|
-
.items
|
|
250
|
-
.query<T>(q)
|
|
251
|
-
.fetchAll()
|
|
252
|
-
.then(({ resources }) => resources.map((_) => ({ ...defaultValues, ..._ })))
|
|
253
|
-
)
|
|
254
|
-
)
|
|
255
|
-
)
|
|
256
|
-
)
|
|
257
|
-
.pipe(
|
|
258
|
-
Effect.map((a) => {
|
|
259
|
-
const v = a
|
|
260
|
-
.flatMap((_) => _)
|
|
261
|
-
.map((x) =>
|
|
262
|
-
spread(
|
|
263
|
-
x,
|
|
264
|
-
({ r, ...rest }: any) => ({ ...rest, ...r } as T & { _rootId: string })
|
|
265
|
-
)
|
|
266
|
-
)
|
|
267
|
-
return v
|
|
268
|
-
}),
|
|
269
|
-
Effect
|
|
270
|
-
.withSpan("Cosmos.filterJoinSelect [effect-app/infra/Store]", {
|
|
271
|
-
attributes: { "repository.container_id": containerId, "repository.model_name": name }
|
|
272
|
-
})
|
|
273
|
-
),
|
|
274
218
|
/**
|
|
275
219
|
* May return duplicate results for "join_find", when matching more than once.
|
|
276
220
|
*/
|
|
@@ -281,82 +225,40 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
281
225
|
const limit = f?.limit
|
|
282
226
|
const filter = f.filter ?? { type: "new-kid", build: () => [] }
|
|
283
227
|
type M = U extends undefined ? PM : Pick<PM, U>
|
|
284
|
-
return
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
.pipe(
|
|
296
|
-
Effect.tap((q) => logQuery(q)),
|
|
297
|
-
Effect
|
|
298
|
-
.flatMap((q) =>
|
|
299
|
-
Effect.promise(() =>
|
|
300
|
-
container
|
|
301
|
-
.items
|
|
302
|
-
.query<M>(q)
|
|
303
|
-
.fetchAll()
|
|
304
|
-
.then(({ resources }) => resources.map((_) => ({ ...defaultValues, ..._ })))
|
|
305
|
-
)
|
|
306
|
-
)
|
|
307
|
-
)
|
|
228
|
+
return Effect
|
|
229
|
+
.sync(() =>
|
|
230
|
+
buildWhereCosmosQuery3(
|
|
231
|
+
filter.build(),
|
|
232
|
+
name,
|
|
233
|
+
importedMarkerId,
|
|
234
|
+
defaultValues,
|
|
235
|
+
f.select as NonEmptyReadonlyArray<string> | undefined,
|
|
236
|
+
f.order as NonEmptyReadonlyArray<{ key: string; direction: "ASC" | "DESC" }> | undefined,
|
|
237
|
+
skip,
|
|
238
|
+
limit
|
|
308
239
|
)
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
240
|
+
)
|
|
241
|
+
.pipe(
|
|
242
|
+
Effect.tap((q) => logQuery(q)),
|
|
243
|
+
Effect
|
|
244
|
+
.flatMap((q) =>
|
|
245
|
+
Effect.promise(() =>
|
|
246
|
+
f.select
|
|
247
|
+
? container
|
|
248
|
+
.items
|
|
249
|
+
.query<M>(q)
|
|
250
|
+
.fetchAll()
|
|
251
|
+
.then(({ resources }) =>
|
|
252
|
+
resources.map((_) => ({ ...pick(defaultValues, f.select!), ..._ }))
|
|
253
|
+
)
|
|
254
|
+
: container
|
|
255
|
+
.items
|
|
256
|
+
.query<{ f: M }>(q)
|
|
257
|
+
.fetchAll()
|
|
258
|
+
.then(({ resources }) => resources.map((_) => ({ ...defaultValues, ..._.f })))
|
|
322
259
|
)
|
|
323
260
|
)
|
|
324
|
-
|
|
325
|
-
Effect.tap((q) => logQuery(q)),
|
|
326
|
-
Effect
|
|
327
|
-
.flatMap((q) =>
|
|
328
|
-
Effect.promise(() =>
|
|
329
|
-
f.select
|
|
330
|
-
? container
|
|
331
|
-
.items
|
|
332
|
-
.query<M>(q)
|
|
333
|
-
.fetchAll()
|
|
334
|
-
.then(({ resources }) =>
|
|
335
|
-
resources.map((_) => ({ ...pick(defaultValues, f.select!), ..._ }))
|
|
336
|
-
)
|
|
337
|
-
: container
|
|
338
|
-
.items
|
|
339
|
-
.query<{ f: M }>(q)
|
|
340
|
-
.fetchAll()
|
|
341
|
-
.then(({ resources }) => resources.map((_) => ({ ...defaultValues, ..._.f })))
|
|
342
|
-
)
|
|
343
|
-
)
|
|
344
|
-
)
|
|
345
|
-
: Effect
|
|
346
|
-
.sync(() => buildCosmosQuery(filter, name, importedMarkerId, defaultValues, skip, limit))
|
|
347
|
-
.pipe(
|
|
348
|
-
Effect.tap((q) => logQuery(q)),
|
|
349
|
-
Effect
|
|
350
|
-
.flatMap((q) =>
|
|
351
|
-
Effect.promise(() =>
|
|
352
|
-
container
|
|
353
|
-
.items
|
|
354
|
-
.query<{ f: M }>(q)
|
|
355
|
-
.fetchAll()
|
|
356
|
-
.then(({ resources }) => resources.map((_) => ({ ...defaultValues, ..._.f })))
|
|
357
|
-
)
|
|
358
|
-
)
|
|
359
|
-
)))
|
|
261
|
+
)
|
|
360
262
|
.pipe(Effect.withSpan("Cosmos.filter [effect-app/infra/Store]", {
|
|
361
263
|
attributes: { "repository.container_id": containerId, "repository.model_name": name }
|
|
362
264
|
}))
|
|
@@ -468,7 +370,8 @@ function makeCosmosStore({ prefix }: StorageConfig) {
|
|
|
468
370
|
Effect.promise(() =>
|
|
469
371
|
container.items.create({
|
|
470
372
|
_partitionKey: importedMarkerId,
|
|
471
|
-
id: importedMarkerId
|
|
373
|
+
id: importedMarkerId,
|
|
374
|
+
ttl: -1
|
|
472
375
|
})
|
|
473
376
|
)
|
|
474
377
|
)
|
|
@@ -150,7 +150,6 @@ export function makeDiskStore({ prefix }: StorageConfig, dir: string) {
|
|
|
150
150
|
all: Effect.flatMap(getStore, (_) => _.all),
|
|
151
151
|
find: (...args) => Effect.flatMap(getStore, (_) => _.find(...args)),
|
|
152
152
|
filter: (...args) => Effect.flatMap(getStore, (_) => _.filter(...args)),
|
|
153
|
-
filterJoinSelect: (...args) => Effect.flatMap(getStore, (_) => _.filterJoinSelect(...args)),
|
|
154
153
|
set: (...args) => Effect.flatMap(getStore, (_) => _.set(...args)),
|
|
155
154
|
batchSet: (...args) => Effect.flatMap(getStore, (_) => _.batchSet(...args)),
|
|
156
155
|
bulkSet: (...args) => Effect.flatMap(getStore, (_) => _.bulkSet(...args)),
|
|
@@ -4,9 +4,9 @@ import { Effect, FiberRef, flow, Option, Order, pipe, ReadonlyArray, Ref } from
|
|
|
4
4
|
import type { NonEmptyArray, NonEmptyReadonlyArray } from "effect-app"
|
|
5
5
|
import { get, pick } from "effect-app/utils"
|
|
6
6
|
import type { RequestContext } from "../../RequestContext.js"
|
|
7
|
-
import type { FilterArgs,
|
|
7
|
+
import type { FilterArgs, PersistenceModelType, Store, StoreConfig } from "./service.js"
|
|
8
8
|
import { StoreMaker } from "./service.js"
|
|
9
|
-
import { codeFilter,
|
|
9
|
+
import { codeFilter, makeUpdateETag } from "./utils.js"
|
|
10
10
|
|
|
11
11
|
export function memFilter<T extends PersistenceModelType<string>, U extends keyof T = never>(f: FilterArgs<T, U>) {
|
|
12
12
|
type M = U extends undefined ? T : Pick<T, U>
|
|
@@ -149,20 +149,6 @@ export function makeMemoryStoreInt<Id extends string, PM extends PersistenceMode
|
|
|
149
149
|
attributes: { "repository.model_name": modelName, "repository.namespace": namespace }
|
|
150
150
|
})
|
|
151
151
|
),
|
|
152
|
-
filterJoinSelect: <T extends object>(filter: FilterJoinSelect) =>
|
|
153
|
-
all
|
|
154
|
-
.pipe(
|
|
155
|
-
Effect.map((c) => c.flatMap(codeFilterJoinSelect<PM, T>(filter))),
|
|
156
|
-
Effect
|
|
157
|
-
.withSpan(
|
|
158
|
-
"Memory.filterJoinSelect [effect-app/infra/Store]",
|
|
159
|
-
{
|
|
160
|
-
attributes: {
|
|
161
|
-
modelName
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
)
|
|
165
|
-
),
|
|
166
152
|
set: (e) =>
|
|
167
153
|
s
|
|
168
154
|
.find(e.id)
|
|
@@ -257,7 +243,6 @@ export const makeMemoryStore = () => ({
|
|
|
257
243
|
all: Effect.flatMap(getStore, (_) => _.all),
|
|
258
244
|
find: (...args) => Effect.flatMap(getStore, (_) => _.find(...args)),
|
|
259
245
|
filter: (...args) => Effect.flatMap(getStore, (_) => _.filter(...args)),
|
|
260
|
-
filterJoinSelect: (...args) => Effect.flatMap(getStore, (_) => _.filterJoinSelect(...args)),
|
|
261
246
|
set: (...args) => Effect.flatMap(getStore, (_) => _.set(...args)),
|
|
262
247
|
batchSet: (...args) => Effect.flatMap(getStore, (_) => _.batchSet(...args)),
|
|
263
248
|
bulkSet: (...args) => Effect.flatMap(getStore, (_) => _.bulkSet(...args)),
|
|
@@ -4,9 +4,9 @@ import { Effect, Layer, Option, ReadonlyArray, Secret } from "effect-app"
|
|
|
4
4
|
import type { NonEmptyArray, NonEmptyReadonlyArray } from "effect-app"
|
|
5
5
|
import { NotFoundError } from "../../errors.js"
|
|
6
6
|
import { memFilter } from "./Memory.js"
|
|
7
|
-
import type {
|
|
7
|
+
import type { PersistenceModelType, StorageConfig, Store, StoreConfig } from "./service.js"
|
|
8
8
|
import { StoreMaker } from "./service.js"
|
|
9
|
-
import {
|
|
9
|
+
import { makeETag, makeUpdateETag } from "./utils.js"
|
|
10
10
|
|
|
11
11
|
function makeRedisStore({ prefix }: StorageConfig) {
|
|
12
12
|
return Effect.gen(function*($) {
|
|
@@ -61,8 +61,6 @@ function makeRedisStore({ prefix }: StorageConfig) {
|
|
|
61
61
|
const s: Store<PM, Id> = {
|
|
62
62
|
all,
|
|
63
63
|
filter: (f) => all.map(memFilter(f)),
|
|
64
|
-
filterJoinSelect: <T extends object>(filter: FilterJoinSelect) =>
|
|
65
|
-
all.map((c) => c.flatMap(codeFilterJoinSelect<PM, T>(filter))),
|
|
66
64
|
find: (id) => asMap.map((_) => Option.fromNullable(_.get(id))),
|
|
67
65
|
set: (e) =>
|
|
68
66
|
s
|
|
@@ -210,11 +210,11 @@ export type Filts<TFieldValues extends FieldValues> = {
|
|
|
210
210
|
): QueryBuilder<TFieldValues>
|
|
211
211
|
<
|
|
212
212
|
TFieldName extends FieldPath<TFieldValues>,
|
|
213
|
-
V extends
|
|
213
|
+
V extends string
|
|
214
214
|
>(
|
|
215
215
|
path: TFieldName,
|
|
216
216
|
op: "startsWith" | "endsWith" | "contains" | "notContains" | "notStartsWith" | "notEndsWith",
|
|
217
|
-
value: V
|
|
217
|
+
value: V
|
|
218
218
|
): QueryBuilder<TFieldValues>
|
|
219
219
|
<
|
|
220
220
|
TFieldName extends FieldPath<TFieldValues>,
|
|
@@ -34,37 +34,7 @@ export type Where =
|
|
|
34
34
|
value: readonly (SupportedValues)[]
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
export type StoreWhereFilter = {
|
|
39
|
-
type?: "where" | undefined
|
|
40
|
-
mode?: "and" | "or" | undefined // default is and
|
|
41
|
-
where: readonly [
|
|
42
|
-
Where,
|
|
43
|
-
...(Where[])
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
export type LegacyFilter<E> =
|
|
47
|
-
| { by: keyof E; type: "startsWith"; value: any }
|
|
48
|
-
| { by: keyof E; type: "endsWith"; value: any }
|
|
49
|
-
| { by: keyof E; type: "contains"; value: any }
|
|
50
|
-
export type JoinFindFilter = {
|
|
51
|
-
type: "join_find"
|
|
52
|
-
keys: readonly string[] /* value paths of E */
|
|
53
|
-
valueKey: string /* value paths of E[keys][valueKey] */
|
|
54
|
-
value: any /* value path[valueKey] of E */
|
|
55
|
-
}
|
|
56
|
-
export type Filter<E extends FieldValues> =
|
|
57
|
-
| JoinFindFilter
|
|
58
|
-
| StoreWhereFilter
|
|
59
|
-
| LegacyFilter<E>
|
|
60
|
-
| QueryBuilder<E>
|
|
61
|
-
|
|
62
|
-
export type FilterJoinSelect = {
|
|
63
|
-
type: "filter_join_select"
|
|
64
|
-
keys: readonly string[] /* value paths of E */
|
|
65
|
-
valueKey: string /* value paths of E[keys][valueKey] */
|
|
66
|
-
value: any /* value path[valueKey] of E */
|
|
67
|
-
}
|
|
37
|
+
export type Filter<E extends FieldValues> = QueryBuilder<E>
|
|
68
38
|
|
|
69
39
|
export interface O<PM extends PersistenceModelType<unknown>> {
|
|
70
40
|
key: keyof PM
|
|
@@ -86,10 +56,6 @@ export type FilterFunc<PM extends PersistenceModelType<unknown>> = <U extends ke
|
|
|
86
56
|
export interface Store<PM extends PersistenceModelType<Id>, Id> {
|
|
87
57
|
all: Effect<PM[]>
|
|
88
58
|
filter: FilterFunc<PM>
|
|
89
|
-
/** @deprecated */
|
|
90
|
-
filterJoinSelect: <T extends object>(
|
|
91
|
-
filter: FilterJoinSelect
|
|
92
|
-
) => Effect<(T & { _rootId: string })[]>
|
|
93
59
|
find: (id: Id) => Effect<Option<PM>>
|
|
94
60
|
set: (e: PM) => Effect<PM, OptimisticConcurrencyException>
|
|
95
61
|
batchSet: (
|