@effect-app/infra 0.210.11 → 0.211.1
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 +19 -0
- package/_cjs/services/RepositoryBase.cjs +2 -23
- 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/api/routing/match.d.ts +1 -1
- package/dist/api/setupRequest.d.ts +1 -1
- package/dist/services/QueueMaker/memQueue.d.ts +1 -1
- package/dist/services/QueueMaker/sbqueue.d.ts +1 -1
- package/dist/services/RepositoryBase.d.ts +3 -60
- package/dist/services/RepositoryBase.d.ts.map +1 -1
- package/dist/services/RepositoryBase.js +3 -23
- 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 +2 -12
- package/src/services/RepositoryBase.ts +3 -35
- 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
|
@@ -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: (
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { Effect, Option
|
|
2
|
-
import { get } from "effect-app/utils"
|
|
1
|
+
import { Effect, Option } from "effect-app"
|
|
3
2
|
import objectHash from "object-hash"
|
|
4
3
|
import { OptimisticConcurrencyException } from "../../errors.js"
|
|
5
4
|
import { codeFilter3_ } from "./codeFilter.js"
|
|
6
|
-
import type { Filter,
|
|
5
|
+
import type { Filter, PersistenceModelType, SupportedValues2 } from "./service.js"
|
|
7
6
|
|
|
8
7
|
export const makeETag = <E extends PersistenceModelType<Id>, Id extends string>(
|
|
9
8
|
{ _etag, ...e }: E
|
|
@@ -37,155 +36,7 @@ export const makeUpdateETag =
|
|
|
37
36
|
})
|
|
38
37
|
|
|
39
38
|
export function codeFilter<E extends { id: string }, NE extends E>(filter: Filter<NE>) {
|
|
40
|
-
return (x: E) =>
|
|
41
|
-
filter.type === "new-kid"
|
|
42
|
-
? codeFilter3_(filter.build(), x) ? Option.some(x as unknown as NE) : Option.none()
|
|
43
|
-
: filter.type === "startsWith"
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
-
? lowercaseIfString((x as any)[filter.by]).startsWith(filter.value.toLowerCase())
|
|
46
|
-
? Option.some(x as unknown as NE)
|
|
47
|
-
: Option.none()
|
|
48
|
-
: filter.type === "endsWith"
|
|
49
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
-
? lowercaseIfString((x as any)[filter.by]).endsWith(filter.value.toLowerCase())
|
|
51
|
-
? Option.some(x as unknown as NE)
|
|
52
|
-
: Option.none()
|
|
53
|
-
: filter.type === "contains"
|
|
54
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
55
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
56
|
-
? lowercaseIfString((x as any)[filter.by]).includes(filter.value.toLowerCase())
|
|
57
|
-
? Option.some(x as unknown as NE)
|
|
58
|
-
: Option.none()
|
|
59
|
-
: filter.type === "join_find"
|
|
60
|
-
? filter.keys.some((k) => {
|
|
61
|
-
const value = get(x, k) as Record<string, unknown>[]
|
|
62
|
-
// we mimic the behavior of cosmosdb; if the shape in db does not match what we're looking for, we imagine false hit
|
|
63
|
-
return (
|
|
64
|
-
value
|
|
65
|
-
&& value.some((v) => compare(v[filter.valueKey], filter.value))
|
|
66
|
-
)
|
|
67
|
-
})
|
|
68
|
-
? Option.some(x as unknown as NE)
|
|
69
|
-
: Option.none()
|
|
70
|
-
// TODO: support mixed or/and
|
|
71
|
-
: filter.mode === "or"
|
|
72
|
-
? filter
|
|
73
|
-
.where
|
|
74
|
-
.some((p) => {
|
|
75
|
-
const k = get(x, p.key)
|
|
76
|
-
switch (p.t) {
|
|
77
|
-
case "in":
|
|
78
|
-
return p.value.includes(k)
|
|
79
|
-
case "not-in":
|
|
80
|
-
return !p.value.includes(k)
|
|
81
|
-
case "lt":
|
|
82
|
-
return lowerThan(k, p.value)
|
|
83
|
-
case "lte":
|
|
84
|
-
return lowerThanExclusive(k, p.value)
|
|
85
|
-
case "gt":
|
|
86
|
-
return greaterThan(k, p.value)
|
|
87
|
-
case "gte":
|
|
88
|
-
return greaterThanExclusive(k, p.value)
|
|
89
|
-
case "includes":
|
|
90
|
-
return (k as Array<string>).includes(p.value)
|
|
91
|
-
case "not-includes":
|
|
92
|
-
return !(k as Array<string>).includes(p.value)
|
|
93
|
-
case "contains":
|
|
94
|
-
return (k as string).toLowerCase().includes(p.value.toLowerCase())
|
|
95
|
-
case "ends-with":
|
|
96
|
-
return (k as string).toLowerCase().endsWith(p.value.toLowerCase())
|
|
97
|
-
case "starts-with":
|
|
98
|
-
return (k as string).toLowerCase().startsWith(p.value.toLowerCase())
|
|
99
|
-
case "not-contains":
|
|
100
|
-
return !(k as string).toLowerCase().includes(p.value.toLowerCase())
|
|
101
|
-
case "not-ends-with":
|
|
102
|
-
return !(k as string).toLowerCase().endsWith(p.value.toLowerCase())
|
|
103
|
-
case "not-starts-with":
|
|
104
|
-
return !(k as string).toLowerCase().startsWith(p.value.toLowerCase())
|
|
105
|
-
case "not-eq":
|
|
106
|
-
return !compare(k, p.value)
|
|
107
|
-
case "eq":
|
|
108
|
-
case undefined:
|
|
109
|
-
return compare(k, p.value)
|
|
110
|
-
}
|
|
111
|
-
})
|
|
112
|
-
? Option.some(x as unknown as NE)
|
|
113
|
-
: Option.none()
|
|
114
|
-
: filter
|
|
115
|
-
.where
|
|
116
|
-
.every((p) => {
|
|
117
|
-
const k = get(x, p.key)
|
|
118
|
-
switch (p.t) {
|
|
119
|
-
case "in":
|
|
120
|
-
return p.value.includes(k)
|
|
121
|
-
case "not-in":
|
|
122
|
-
return !p.value.includes(k)
|
|
123
|
-
case "lt":
|
|
124
|
-
return lowerThan(k, p.value)
|
|
125
|
-
case "lte":
|
|
126
|
-
return lowerThanExclusive(k, p.value)
|
|
127
|
-
case "gt":
|
|
128
|
-
return greaterThan(k, p.value)
|
|
129
|
-
case "gte":
|
|
130
|
-
return greaterThanExclusive(k, p.value)
|
|
131
|
-
case "includes":
|
|
132
|
-
return (k as Array<string>).includes(p.value)
|
|
133
|
-
case "not-includes":
|
|
134
|
-
return !(k as Array<string>).includes(p.value)
|
|
135
|
-
case "contains":
|
|
136
|
-
return (k as string).toLowerCase().includes(p.value.toLowerCase())
|
|
137
|
-
case "ends-with":
|
|
138
|
-
return (k as string).toLowerCase().endsWith(p.value.toLowerCase())
|
|
139
|
-
case "starts-with":
|
|
140
|
-
return (k as string).toLowerCase().startsWith(p.value.toLowerCase())
|
|
141
|
-
case "not-contains":
|
|
142
|
-
return !(k as string).toLowerCase().includes(p.value.toLowerCase())
|
|
143
|
-
case "not-ends-with":
|
|
144
|
-
return !(k as string).toLowerCase().endsWith(p.value.toLowerCase())
|
|
145
|
-
case "not-starts-with":
|
|
146
|
-
return !(k as string).toLowerCase().startsWith(p.value.toLowerCase())
|
|
147
|
-
case "not-eq":
|
|
148
|
-
return p.key.includes(".-1.")
|
|
149
|
-
? (get(x, p.key.split(".-1.")[0]) as any[])
|
|
150
|
-
// TODO: or vs and
|
|
151
|
-
.every((_) => !compare(get(_, p.key.split(".-1.")[1]!), p.value))
|
|
152
|
-
: !compare(k, p.value)
|
|
153
|
-
case "eq":
|
|
154
|
-
case undefined:
|
|
155
|
-
return p.key.includes(".-1.")
|
|
156
|
-
? (get(x, p.key.split(".-1.")[0]) as any[])
|
|
157
|
-
// TODO: or vs and
|
|
158
|
-
.some((_) => compare(get(_, p.key.split(".-1.")[1]!), p.value))
|
|
159
|
-
: compare(k, p.value)
|
|
160
|
-
}
|
|
161
|
-
})
|
|
162
|
-
? Option.some(x as unknown as NE)
|
|
163
|
-
: Option.none()
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export function codeFilterJoinSelect<E extends { id: string }, NE>(
|
|
167
|
-
filter: FilterJoinSelect
|
|
168
|
-
) {
|
|
169
|
-
return (x: E) =>
|
|
170
|
-
ReadonlyArray
|
|
171
|
-
.filterMap(
|
|
172
|
-
filter
|
|
173
|
-
.keys,
|
|
174
|
-
(k) => {
|
|
175
|
-
const value = get(x, k)
|
|
176
|
-
// we mimic the behavior of cosmosdb; if the shape in db does not match what we're looking for, we imagine false hit
|
|
177
|
-
return value
|
|
178
|
-
? Option.some(
|
|
179
|
-
ReadonlyArray.filterMap(value as readonly NE[], (v) =>
|
|
180
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
181
|
-
compare((v as any)[filter.valueKey], filter.value)
|
|
182
|
-
? Option.some({ ...v, _rootId: x.id })
|
|
183
|
-
: Option.none())
|
|
184
|
-
)
|
|
185
|
-
: Option.none()
|
|
186
|
-
}
|
|
187
|
-
)
|
|
188
|
-
.flatMap((_) => _)
|
|
39
|
+
return (x: E) => codeFilter3_(filter.build(), x) ? Option.some(x as unknown as NE) : Option.none()
|
|
189
40
|
}
|
|
190
41
|
|
|
191
42
|
export function lowercaseIfString<T>(val: T) {
|
|
@@ -251,11 +251,11 @@ export type FilterWheres = {
|
|
|
251
251
|
<
|
|
252
252
|
TFieldValues extends FieldValues,
|
|
253
253
|
TFieldName extends FieldPath<TFieldValues>,
|
|
254
|
-
V extends
|
|
254
|
+
V extends string
|
|
255
255
|
>(
|
|
256
256
|
path: TFieldName,
|
|
257
257
|
op: "startsWith" | "endsWith" | "contains" | "notContains" | "notStartsWith" | "notEndsWith",
|
|
258
|
-
value: V
|
|
258
|
+
value: V
|
|
259
259
|
): (
|
|
260
260
|
current: Query<TFieldValues>
|
|
261
261
|
) => QueryWhere<TFieldValues>
|
|
@@ -322,11 +322,11 @@ export type FilterContinuations = {
|
|
|
322
322
|
<
|
|
323
323
|
TFieldValues extends FieldValues,
|
|
324
324
|
TFieldName extends FieldPath<TFieldValues>,
|
|
325
|
-
V extends
|
|
325
|
+
V extends string
|
|
326
326
|
>(
|
|
327
327
|
path: TFieldName,
|
|
328
328
|
op: "startsWith" | "endsWith" | "contains" | "notContains" | "notStartsWith" | "notEndsWith",
|
|
329
|
-
value: V
|
|
329
|
+
value: V
|
|
330
330
|
): (
|
|
331
331
|
current: QueryWhere<TFieldValues>
|
|
332
332
|
) => QueryWhere<TFieldValues>
|