@effect-app/infra 1.36.0 → 1.38.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 +26 -0
- package/_cjs/services/RepositoryBase.cjs +6 -1
- package/_cjs/services/RepositoryBase.cjs.map +1 -1
- package/_cjs/services/Store/Cosmos/query.cjs +14 -2
- package/_cjs/services/Store/Cosmos/query.cjs.map +1 -1
- package/_cjs/services/Store/Memory.cjs.map +1 -1
- package/_cjs/services/Store/codeFilter.cjs +12 -0
- package/_cjs/services/Store/codeFilter.cjs.map +1 -1
- package/dist/RequestContext.d.ts +3 -3
- package/dist/api/internal/RequestContextMiddleware.d.ts +1 -1
- package/dist/api/reportError.d.ts +2 -2
- package/dist/services/Repository/ext.d.ts +4 -4
- package/dist/services/RepositoryBase.d.ts +2 -2
- package/dist/services/RepositoryBase.d.ts.map +1 -1
- package/dist/services/RepositoryBase.js +5 -5
- package/dist/services/RequestContextContainer.d.ts +1 -1
- package/dist/services/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/services/Store/Cosmos/query.js +14 -3
- package/dist/services/Store/Memory.d.ts.map +1 -1
- package/dist/services/Store/Memory.js +2 -4
- package/dist/services/Store/codeFilter.d.ts.map +1 -1
- package/dist/services/Store/codeFilter.js +12 -1
- 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 -1
- package/dist/services/query/dsl.d.ts +7 -0
- package/dist/services/query/dsl.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/services/RepositoryBase.ts +8 -5
- package/src/services/Store/Cosmos/query.ts +17 -2
- package/src/services/Store/Memory.ts +2 -4
- package/src/services/Store/codeFilter.ts +12 -0
- package/src/services/Store/filterApi/query.ts +4 -1
- package/src/services/query/dsl.ts +95 -3
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/infra",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@azure/cosmos": "^4.1.1",
|
|
8
8
|
"@azure/service-bus": "^7.9.5",
|
|
9
|
-
"@effect/rpc": "^0.43.
|
|
10
|
-
"@effect/rpc-http": "^0.41.
|
|
9
|
+
"@effect/rpc": "^0.43.4",
|
|
10
|
+
"@effect/rpc-http": "^0.41.4",
|
|
11
11
|
"express-oauth2-jwt-bearer": "^1.6.0",
|
|
12
12
|
"@faker-js/faker": "^8.4.1",
|
|
13
13
|
"@sendgrid/helpers": "^8.0.0",
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"proper-lockfile": "^4.1.2",
|
|
21
21
|
"pure-rand": "6.1.0",
|
|
22
22
|
"redlock": "^4.2.0",
|
|
23
|
-
"@effect-app/
|
|
24
|
-
"effect-app": "1.
|
|
25
|
-
"@effect-app/
|
|
26
|
-
"@effect-app/
|
|
23
|
+
"@effect-app/core": "1.17.0",
|
|
24
|
+
"effect-app": "1.28.0",
|
|
25
|
+
"@effect-app/schema": "1.19.0",
|
|
26
|
+
"@effect-app/infra-adapters": "1.19.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@babel/cli": "^7.25.7",
|
|
@@ -39,13 +39,13 @@
|
|
|
39
39
|
"mongodb": "6.9.0",
|
|
40
40
|
"redis": "^3.1.2",
|
|
41
41
|
"typescript": "^5.6.3",
|
|
42
|
-
"vitest": "^2.1.
|
|
42
|
+
"vitest": "^2.1.3"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"express": "^4.21.1",
|
|
46
|
-
"@effect/platform": "^0.68.
|
|
46
|
+
"@effect/platform": "^0.68.5",
|
|
47
47
|
"@effect/schema": "^0.75.4",
|
|
48
|
-
"@effect/sql": "^0.16.
|
|
48
|
+
"@effect/sql": "^0.16.5",
|
|
49
49
|
"@effect/vitest": "^0.12.1",
|
|
50
50
|
"effect": "^3.9.2"
|
|
51
51
|
},
|
|
@@ -525,11 +525,12 @@ export function makeRepo<
|
|
|
525
525
|
.pipe(Effect.orDie, Effect.withSpan("parseMany2", { captureStackTrace: false })))
|
|
526
526
|
const filter = <U extends keyof Encoded = keyof Encoded>(args: FilterArgs<Encoded, U>) =>
|
|
527
527
|
store
|
|
528
|
-
.filter(
|
|
528
|
+
.filter(
|
|
529
|
+
// always enforce id and _etag because they are system fields, required for etag tracking etc
|
|
530
|
+
{ ...args, select: args.select ? [...args.select, "id", "_etag" as any] : undefined } as typeof args
|
|
531
|
+
)
|
|
529
532
|
.pipe(Effect.tap((items) =>
|
|
530
|
-
|
|
531
|
-
? Effect.void
|
|
532
|
-
: Effect.map(cms, ({ set }) => items.forEach((_) => set((_ as Encoded).id, (_ as PM)._etag)))
|
|
533
|
+
Effect.map(cms, ({ set }) => items.forEach((_) => set((_ as Encoded).id, (_ as PM)._etag)))
|
|
533
534
|
))
|
|
534
535
|
|
|
535
536
|
// TODO: For raw we should use S.from, and drop the R...
|
|
@@ -543,7 +544,9 @@ export function makeRepo<
|
|
|
543
544
|
const eff = a.mode === "project"
|
|
544
545
|
? filter(a)
|
|
545
546
|
// TODO: mapFrom but need to support per field and dependencies
|
|
546
|
-
.pipe(
|
|
547
|
+
.pipe(
|
|
548
|
+
Effect.andThen(flow(S.decode(S.Array(a.schema ?? schema)), Effect.provide(rctx)))
|
|
549
|
+
)
|
|
547
550
|
: a.mode === "collect"
|
|
548
551
|
? filter(a)
|
|
549
552
|
// TODO: mapFrom but need to support per field and dependencies
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
1
2
|
import { Array, Effect, Equivalence, pipe } from "effect-app"
|
|
2
3
|
import type { NonEmptyReadonlyArray } from "effect-app"
|
|
3
4
|
import { assertUnreachable } from "effect-app/utils"
|
|
@@ -27,6 +28,9 @@ export function logQuery(q: {
|
|
|
27
28
|
}))
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
const arrayContains = (v: any[]) => v.map((_) => JSON.stringify(_)).join(", ")
|
|
32
|
+
const vAsArr = (v: string) => v as unknown as any[]
|
|
33
|
+
|
|
30
34
|
export function buildWhereCosmosQuery3(
|
|
31
35
|
filter: readonly FilterResult[],
|
|
32
36
|
name: string,
|
|
@@ -53,9 +57,20 @@ export function buildWhereCosmosQuery3(
|
|
|
53
57
|
return `(NOT ARRAY_CONTAINS(${v}, ${k}))`
|
|
54
58
|
|
|
55
59
|
case "includes":
|
|
56
|
-
return `ARRAY_CONTAINS(${k}, ${v})`
|
|
60
|
+
return `ARRAY_CONTAINS(${k}, ${arrayContains(vAsArr(v))})`
|
|
57
61
|
case "notIncludes":
|
|
58
|
-
return `(NOT ARRAY_CONTAINS(${k}, ${v}))`
|
|
62
|
+
return `(NOT ARRAY_CONTAINS(${k}, ${arrayContains(vAsArr(v))}))`
|
|
63
|
+
|
|
64
|
+
case "includes-any":
|
|
65
|
+
return `ARRAY_CONTAINS_ANY(${k}, ${arrayContains(vAsArr(v))})`
|
|
66
|
+
case "notIncludes-any":
|
|
67
|
+
return `(NOT ARRAY_CONTAINS_ANY(${k}, ${arrayContains(vAsArr(v))}))`
|
|
68
|
+
|
|
69
|
+
case "includes-all":
|
|
70
|
+
return `ARRAY_CONTAINS_ALL(${k}, ${arrayContains(vAsArr(v))})`
|
|
71
|
+
case "notIncludes-all":
|
|
72
|
+
return `(NOT ARRAY_CONTAINS_ALL(${k}, ${arrayContains(vAsArr(v))}))`
|
|
73
|
+
|
|
59
74
|
case "contains":
|
|
60
75
|
return `CONTAINS(${k}, ${v}, true)`
|
|
61
76
|
|
|
@@ -240,10 +240,8 @@ export const makeMemoryStore = () => ({
|
|
|
240
240
|
return makeMemoryStoreInt(modelName, namespace, seed, config?.defaultValues)
|
|
241
241
|
.pipe(
|
|
242
242
|
Effect.orDie,
|
|
243
|
-
Effect
|
|
244
|
-
|
|
245
|
-
Effect
|
|
246
|
-
.tap((store) => Effect.sync(() => stores.set(namespace, store)))
|
|
243
|
+
Effect.provide(ctx),
|
|
244
|
+
Effect.tap((store) => Effect.sync(() => stores.set(namespace, store)))
|
|
247
245
|
)
|
|
248
246
|
}))
|
|
249
247
|
}))
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
1
3
|
import { Array } from "effect-app"
|
|
2
4
|
import { assertUnreachable, get } from "effect-app/utils"
|
|
3
5
|
import type { FilterR, FilterResult } from "./filterApi/query.js"
|
|
4
6
|
import { compare, greaterThan, greaterThanExclusive, lowerThan, lowerThanExclusive } from "./utils.js"
|
|
5
7
|
|
|
8
|
+
const vAsArr = (v: string) => v as unknown as any[]
|
|
9
|
+
|
|
6
10
|
export const codeFilterStatement = <E>(p: FilterR, x: E) => {
|
|
7
11
|
const k = get(x, p.path)
|
|
8
12
|
switch (p.op) {
|
|
@@ -22,6 +26,14 @@ export const codeFilterStatement = <E>(p: FilterR, x: E) => {
|
|
|
22
26
|
return (k as Array<string>).includes(p.value)
|
|
23
27
|
case "notIncludes":
|
|
24
28
|
return !(k as Array<string>).includes(p.value)
|
|
29
|
+
case "includes-any":
|
|
30
|
+
return (vAsArr(p.value)).some((_) => (k as Array<string>)?.includes(_))
|
|
31
|
+
case "notIncludes-any":
|
|
32
|
+
return !(vAsArr(p.value)).some((_) => (k as Array<string>)?.includes(_))
|
|
33
|
+
case "includes-all":
|
|
34
|
+
return (vAsArr(p.value)).every((_) => (k as Array<string>)?.includes(_))
|
|
35
|
+
case "notIncludes-all":
|
|
36
|
+
return !(vAsArr(p.value)).every((_) => (k as Array<string>)?.includes(_))
|
|
25
37
|
case "contains":
|
|
26
38
|
return (k as string).toLowerCase().includes(p.value.toLowerCase())
|
|
27
39
|
case "endsWith":
|
|
@@ -11,6 +11,10 @@ export type OtherOps =
|
|
|
11
11
|
| "notContains"
|
|
12
12
|
| "includes"
|
|
13
13
|
| "notIncludes"
|
|
14
|
+
| "includes-any"
|
|
15
|
+
| "notIncludes-any"
|
|
16
|
+
| "includes-all"
|
|
17
|
+
| "notIncludes-all"
|
|
14
18
|
| "eq"
|
|
15
19
|
| "neq"
|
|
16
20
|
| "gt"
|
|
@@ -18,7 +22,6 @@ export type OtherOps =
|
|
|
18
22
|
| "lt"
|
|
19
23
|
| "lte"
|
|
20
24
|
|
|
21
|
-
// TODO: includes | notIncludes
|
|
22
25
|
export type Ops = OtherOps | InOps
|
|
23
26
|
|
|
24
27
|
export type FilterScopes = {
|
|
@@ -316,11 +316,41 @@ export type FilterWheres = {
|
|
|
316
316
|
V extends FieldPathValue<TFieldValues, TFieldName>
|
|
317
317
|
>(
|
|
318
318
|
path: TFieldName,
|
|
319
|
-
op:
|
|
319
|
+
op:
|
|
320
|
+
| "in"
|
|
321
|
+
| "notIn",
|
|
320
322
|
value: readonly V[]
|
|
321
323
|
): (
|
|
322
324
|
current: Query<TFieldValues>
|
|
323
325
|
) => QueryWhere<TFieldValues>
|
|
326
|
+
<
|
|
327
|
+
TFieldValues extends FieldValues,
|
|
328
|
+
TFieldName extends FieldPath<TFieldValues>,
|
|
329
|
+
V extends FieldPathValue<TFieldValues, TFieldName>
|
|
330
|
+
>(
|
|
331
|
+
path: TFieldName,
|
|
332
|
+
op:
|
|
333
|
+
| "includes"
|
|
334
|
+
| "notIncludes",
|
|
335
|
+
value: GetArV<V>
|
|
336
|
+
): (
|
|
337
|
+
current: Query<TFieldValues>
|
|
338
|
+
) => QueryWhere<TFieldValues>
|
|
339
|
+
<
|
|
340
|
+
TFieldValues extends FieldValues,
|
|
341
|
+
TFieldName extends FieldPath<TFieldValues>,
|
|
342
|
+
V extends FieldPathValue<TFieldValues, TFieldName>
|
|
343
|
+
>(
|
|
344
|
+
path: TFieldName,
|
|
345
|
+
op:
|
|
346
|
+
| "includes-any"
|
|
347
|
+
| "notIncludes-any"
|
|
348
|
+
| "includes-all"
|
|
349
|
+
| "notIncludes-all",
|
|
350
|
+
value: readonly GetArV<V>[]
|
|
351
|
+
): (
|
|
352
|
+
current: Query<TFieldValues>
|
|
353
|
+
) => QueryWhere<TFieldValues>
|
|
324
354
|
}
|
|
325
355
|
|
|
326
356
|
export type FilterWhere =
|
|
@@ -504,11 +534,41 @@ export type FilterWhere =
|
|
|
504
534
|
V extends FieldPathValue<TFieldValues, TFieldName>
|
|
505
535
|
>(
|
|
506
536
|
path: TFieldName,
|
|
507
|
-
op:
|
|
537
|
+
op:
|
|
538
|
+
| "in"
|
|
539
|
+
| "notIn",
|
|
508
540
|
value: readonly V[]
|
|
509
541
|
): (
|
|
510
542
|
current: Query<TFieldValues>
|
|
511
543
|
) => QueryWhere<TFieldValues>
|
|
544
|
+
<
|
|
545
|
+
TFieldValues extends FieldValues,
|
|
546
|
+
TFieldName extends FieldPath<TFieldValues>,
|
|
547
|
+
V extends FieldPathValue<TFieldValues, TFieldName>
|
|
548
|
+
>(
|
|
549
|
+
path: TFieldName,
|
|
550
|
+
op:
|
|
551
|
+
| "includes"
|
|
552
|
+
| "notIncludes",
|
|
553
|
+
value: GetArV<V>
|
|
554
|
+
): (
|
|
555
|
+
current: Query<TFieldValues>
|
|
556
|
+
) => QueryWhere<TFieldValues>
|
|
557
|
+
<
|
|
558
|
+
TFieldValues extends FieldValues,
|
|
559
|
+
TFieldName extends FieldPath<TFieldValues>,
|
|
560
|
+
V extends FieldPathValue<TFieldValues, TFieldName>
|
|
561
|
+
>(
|
|
562
|
+
path: TFieldName,
|
|
563
|
+
op:
|
|
564
|
+
| "includes-any"
|
|
565
|
+
| "notIncludes-any"
|
|
566
|
+
| "includes-all"
|
|
567
|
+
| "notIncludes-all",
|
|
568
|
+
value: readonly GetArV<V>[]
|
|
569
|
+
): (
|
|
570
|
+
current: Query<TFieldValues>
|
|
571
|
+
) => QueryWhere<TFieldValues>
|
|
512
572
|
}
|
|
513
573
|
|
|
514
574
|
export type FilterContinuations = {
|
|
@@ -562,13 +622,45 @@ export type FilterContinuations = {
|
|
|
562
622
|
V extends FieldPathValue<TFieldValues, TFieldName>
|
|
563
623
|
>(
|
|
564
624
|
path: TFieldName,
|
|
565
|
-
op:
|
|
625
|
+
op:
|
|
626
|
+
| "in"
|
|
627
|
+
| "notIn",
|
|
566
628
|
value: readonly V[]
|
|
567
629
|
): (
|
|
568
630
|
current: QueryWhere<TFieldValues>
|
|
569
631
|
) => QueryWhere<TFieldValues>
|
|
632
|
+
<
|
|
633
|
+
TFieldValues extends FieldValues,
|
|
634
|
+
TFieldName extends FieldPath<TFieldValues>,
|
|
635
|
+
V extends FieldPathValue<TFieldValues, TFieldName>
|
|
636
|
+
>(
|
|
637
|
+
path: TFieldName,
|
|
638
|
+
op:
|
|
639
|
+
| "includes"
|
|
640
|
+
| "notIncludes",
|
|
641
|
+
value: GetArV<V>
|
|
642
|
+
): (
|
|
643
|
+
current: QueryWhere<TFieldValues>
|
|
644
|
+
) => QueryWhere<TFieldValues>
|
|
645
|
+
<
|
|
646
|
+
TFieldValues extends FieldValues,
|
|
647
|
+
TFieldName extends FieldPath<TFieldValues>,
|
|
648
|
+
V extends FieldPathValue<TFieldValues, TFieldName>
|
|
649
|
+
>(
|
|
650
|
+
path: TFieldName,
|
|
651
|
+
op:
|
|
652
|
+
| "includes-any"
|
|
653
|
+
| "notIncludes-any"
|
|
654
|
+
| "includes-all"
|
|
655
|
+
| "notIncludes-all",
|
|
656
|
+
value: readonly GetArV<V>[]
|
|
657
|
+
): (
|
|
658
|
+
current: QueryWhere<TFieldValues>
|
|
659
|
+
) => QueryWhere<TFieldValues>
|
|
570
660
|
}
|
|
571
661
|
|
|
662
|
+
type GetArV<T> = T extends readonly (infer R)[] ? R : never
|
|
663
|
+
|
|
572
664
|
export type FilterContinuationClosure = {
|
|
573
665
|
<TFieldValues extends FieldValues>(
|
|
574
666
|
fb: (current: Query<TFieldValues>) => QueryWhere<TFieldValues>
|