@effect-app/infra 4.0.0-beta.23 → 4.0.0-beta.231
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 +1726 -0
- package/_check.sh +1 -1
- package/dist/CUPS.d.ts +12 -7
- package/dist/CUPS.d.ts.map +1 -1
- package/dist/CUPS.js +16 -12
- package/dist/Emailer/Sendgrid.d.ts +15 -15
- package/dist/Emailer/Sendgrid.d.ts.map +1 -1
- package/dist/Emailer/Sendgrid.js +21 -17
- package/dist/Emailer/fake.d.ts +1 -1
- package/dist/Emailer/fake.js +3 -3
- package/dist/Emailer/service.d.ts +13 -4
- package/dist/Emailer/service.d.ts.map +1 -1
- package/dist/Emailer/service.js +4 -3
- package/dist/Emailer.d.ts +1 -1
- package/dist/MainFiberSet.d.ts +12 -9
- package/dist/MainFiberSet.d.ts.map +1 -1
- package/dist/MainFiberSet.js +10 -6
- package/dist/Model/Repository/Registry.d.ts +21 -0
- package/dist/Model/Repository/Registry.d.ts.map +1 -0
- package/dist/Model/Repository/Registry.js +18 -0
- package/dist/Model/Repository/ext.d.ts +35 -16
- package/dist/Model/Repository/ext.d.ts.map +1 -1
- package/dist/Model/Repository/ext.js +60 -3
- package/dist/Model/Repository/internal/internal.d.ts +9 -6
- package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
- package/dist/Model/Repository/internal/internal.js +141 -59
- package/dist/Model/Repository/legacy.d.ts +4 -2
- package/dist/Model/Repository/legacy.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.d.ts +10 -6
- package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
- package/dist/Model/Repository/makeRepo.js +5 -2
- package/dist/Model/Repository/service.d.ts +32 -24
- package/dist/Model/Repository/service.d.ts.map +1 -1
- package/dist/Model/Repository/validation.d.ts +47 -18
- package/dist/Model/Repository/validation.d.ts.map +1 -1
- package/dist/Model/Repository/validation.js +6 -6
- package/dist/Model/Repository.d.ts +2 -1
- package/dist/Model/Repository.d.ts.map +1 -1
- package/dist/Model/Repository.js +2 -1
- package/dist/Model/dsl.d.ts +6 -5
- package/dist/Model/dsl.d.ts.map +1 -1
- package/dist/Model/dsl.js +2 -3
- package/dist/Model/filter/filterApi.d.ts +5 -5
- package/dist/Model/filter/filterApi.d.ts.map +1 -1
- package/dist/Model/filter/types/errors.d.ts +1 -1
- package/dist/Model/filter/types/fields.d.ts +1 -1
- package/dist/Model/filter/types/path/common.d.ts +1 -1
- package/dist/Model/filter/types/path/eager.d.ts +1 -1
- package/dist/Model/filter/types/path/eager.d.ts.map +1 -1
- package/dist/Model/filter/types/path/eager.js +1 -1
- package/dist/Model/filter/types/path/index.d.ts +1 -1
- package/dist/Model/filter/types/utils.d.ts +1 -1
- package/dist/Model/filter/types/validator.d.ts +1 -1
- package/dist/Model/filter/types.d.ts +1 -1
- package/dist/Model/query/dsl.d.ts +216 -18
- package/dist/Model/query/dsl.d.ts.map +1 -1
- package/dist/Model/query/dsl.js +240 -5
- package/dist/Model/query/new-kid-interpreter.d.ts +116 -8
- package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -1
- package/dist/Model/query/new-kid-interpreter.js +177 -6
- package/dist/Model/query.d.ts +1 -1
- package/dist/Model.d.ts +2 -1
- package/dist/Model.d.ts.map +1 -1
- package/dist/Model.js +2 -1
- package/dist/QueueMaker/SQLQueue.d.ts +7 -8
- package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
- package/dist/QueueMaker/SQLQueue.js +135 -117
- package/dist/QueueMaker/errors.d.ts +5 -3
- package/dist/QueueMaker/errors.d.ts.map +1 -1
- package/dist/QueueMaker/errors.js +4 -2
- package/dist/QueueMaker/memQueue.d.ts +9 -5
- package/dist/QueueMaker/memQueue.d.ts.map +1 -1
- package/dist/QueueMaker/memQueue.js +81 -65
- package/dist/QueueMaker/sbqueue.d.ts +8 -4
- package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
- package/dist/QueueMaker/sbqueue.js +57 -55
- package/dist/QueueMaker/service.d.ts +4 -2
- package/dist/QueueMaker/service.d.ts.map +1 -1
- package/dist/QueueMaker/service.js +1 -1
- package/dist/RequestContext.d.ts +75 -35
- package/dist/RequestContext.d.ts.map +1 -1
- package/dist/RequestContext.js +14 -14
- package/dist/RequestFiberSet.d.ts +10 -7
- package/dist/RequestFiberSet.d.ts.map +1 -1
- package/dist/RequestFiberSet.js +12 -7
- package/dist/Store/ContextMapContainer.d.ts +22 -3
- package/dist/Store/ContextMapContainer.d.ts.map +1 -1
- package/dist/Store/ContextMapContainer.js +18 -4
- package/dist/Store/Cosmos/query.d.ts +13 -2
- package/dist/Store/Cosmos/query.d.ts.map +1 -1
- package/dist/Store/Cosmos/query.js +179 -41
- package/dist/Store/Cosmos.d.ts +2 -2
- package/dist/Store/Cosmos.d.ts.map +1 -1
- package/dist/Store/Cosmos.js +343 -244
- package/dist/Store/Disk.d.ts +3 -3
- package/dist/Store/Disk.d.ts.map +1 -1
- package/dist/Store/Disk.js +76 -36
- package/dist/Store/Memory.d.ts +7 -4
- package/dist/Store/Memory.d.ts.map +1 -1
- package/dist/Store/Memory.js +327 -62
- package/dist/Store/SQL/Pg.d.ts +4 -0
- package/dist/Store/SQL/Pg.d.ts.map +1 -0
- package/dist/Store/SQL/Pg.js +233 -0
- package/dist/Store/SQL/query.d.ts +49 -0
- package/dist/Store/SQL/query.d.ts.map +1 -0
- package/dist/Store/SQL/query.js +527 -0
- package/dist/Store/SQL.d.ts +21 -0
- package/dist/Store/SQL.d.ts.map +1 -0
- package/dist/Store/SQL.js +450 -0
- package/dist/Store/codeFilter.d.ts +2 -2
- package/dist/Store/codeFilter.d.ts.map +1 -1
- package/dist/Store/codeFilter.js +6 -3
- package/dist/Store/index.d.ts +6 -3
- package/dist/Store/index.d.ts.map +1 -1
- package/dist/Store/index.js +18 -4
- package/dist/Store/service.d.ts +32 -8
- package/dist/Store/service.d.ts.map +1 -1
- package/dist/Store/service.js +25 -6
- package/dist/Store/utils.d.ts +3 -2
- package/dist/Store/utils.d.ts.map +1 -1
- package/dist/Store/utils.js +5 -5
- package/dist/Store.d.ts +1 -1
- package/dist/adapters/SQL/Model.d.ts +32 -43
- package/dist/adapters/SQL/Model.d.ts.map +1 -1
- package/dist/adapters/SQL/Model.js +30 -39
- package/dist/adapters/SQL.d.ts +1 -1
- package/dist/adapters/ServiceBus.d.ts +14 -11
- package/dist/adapters/ServiceBus.d.ts.map +1 -1
- package/dist/adapters/ServiceBus.js +30 -21
- package/dist/adapters/cosmos-client.d.ts +5 -3
- package/dist/adapters/cosmos-client.d.ts.map +1 -1
- package/dist/adapters/cosmos-client.js +6 -4
- package/dist/adapters/index.d.ts +8 -2
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +8 -2
- package/dist/adapters/logger.d.ts +2 -2
- package/dist/adapters/logger.d.ts.map +1 -1
- package/dist/adapters/memQueue.d.ts +5 -3
- package/dist/adapters/memQueue.d.ts.map +1 -1
- package/dist/adapters/memQueue.js +6 -5
- package/dist/adapters/mongo-client.d.ts +4 -3
- package/dist/adapters/mongo-client.d.ts.map +1 -1
- package/dist/adapters/mongo-client.js +5 -3
- package/dist/adapters/redis-client.d.ts +6 -3
- package/dist/adapters/redis-client.d.ts.map +1 -1
- package/dist/adapters/redis-client.js +7 -3
- package/dist/api/ContextProvider.d.ts +12 -9
- package/dist/api/ContextProvider.d.ts.map +1 -1
- package/dist/api/ContextProvider.js +9 -7
- package/dist/api/codec.d.ts +1 -1
- package/dist/api/internal/RequestContextMiddleware.d.ts +3 -3
- package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
- package/dist/api/internal/RequestContextMiddleware.js +11 -7
- package/dist/api/internal/auth.d.ts +45 -7
- package/dist/api/internal/auth.d.ts.map +1 -1
- package/dist/api/internal/auth.js +162 -29
- package/dist/api/internal/events.d.ts +6 -4
- package/dist/api/internal/events.d.ts.map +1 -1
- package/dist/api/internal/events.js +16 -9
- package/dist/api/internal/health.d.ts +1 -1
- package/dist/api/layerUtils.d.ts +15 -7
- package/dist/api/layerUtils.d.ts.map +1 -1
- package/dist/api/layerUtils.js +7 -6
- package/dist/api/middlewares.d.ts +1 -1
- package/dist/api/reportError.d.ts +2 -2
- package/dist/api/reportError.d.ts.map +1 -1
- package/dist/api/reportError.js +3 -2
- package/dist/api/routing/middleware/RouterMiddleware.d.ts +5 -4
- package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.d.ts +42 -3
- package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware/middleware.js +53 -17
- package/dist/api/routing/middleware.d.ts +1 -2
- package/dist/api/routing/middleware.d.ts.map +1 -1
- package/dist/api/routing/middleware.js +1 -2
- package/dist/api/routing/schema/jwt.d.ts +1 -1
- package/dist/api/routing/schema/jwt.d.ts.map +1 -1
- package/dist/api/routing/schema/jwt.js +3 -2
- package/dist/api/routing/tsort.d.ts +1 -1
- package/dist/api/routing/tsort.d.ts.map +1 -1
- package/dist/api/routing/utils.d.ts +4 -4
- package/dist/api/routing/utils.d.ts.map +1 -1
- package/dist/api/routing/utils.js +3 -2
- package/dist/api/routing.d.ts +84 -38
- package/dist/api/routing.d.ts.map +1 -1
- package/dist/api/routing.js +115 -45
- package/dist/api/setupRequest.d.ts +10 -6
- package/dist/api/setupRequest.d.ts.map +1 -1
- package/dist/api/setupRequest.js +19 -11
- package/dist/api/util.d.ts +1 -1
- package/dist/arbs.d.ts +2 -2
- package/dist/arbs.d.ts.map +1 -1
- package/dist/arbs.js +5 -3
- package/dist/errorReporter.d.ts +7 -5
- package/dist/errorReporter.d.ts.map +1 -1
- package/dist/errorReporter.js +22 -26
- package/dist/errors.d.ts +1 -1
- package/dist/fileUtil.d.ts +2 -2
- package/dist/fileUtil.d.ts.map +1 -1
- package/dist/fileUtil.js +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/logger/jsonLogger.d.ts +2 -2
- package/dist/logger/jsonLogger.d.ts.map +1 -1
- package/dist/logger/jsonLogger.js +4 -2
- package/dist/logger/logFmtLogger.d.ts +2 -2
- package/dist/logger/logFmtLogger.d.ts.map +1 -1
- package/dist/logger/logFmtLogger.js +2 -2
- package/dist/logger/shared.d.ts +2 -2
- package/dist/logger/shared.d.ts.map +1 -1
- package/dist/logger/shared.js +3 -3
- package/dist/logger.d.ts +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/otel.d.ts +75 -0
- package/dist/otel.d.ts.map +1 -0
- package/dist/otel.js +65 -0
- package/dist/rateLimit.d.ts +12 -4
- package/dist/rateLimit.d.ts.map +1 -1
- package/dist/rateLimit.js +7 -12
- package/dist/test.d.ts +3 -3
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +2 -2
- package/dist/vitest.d.ts +1 -1
- package/examples/query.ts +46 -38
- package/package.json +46 -37
- package/src/CUPS.ts +15 -11
- package/src/Emailer/Sendgrid.ts +65 -57
- package/src/Emailer/fake.ts +2 -2
- package/src/Emailer/service.ts +13 -3
- package/src/MainFiberSet.ts +12 -10
- package/src/Model/Repository/Registry.ts +34 -0
- package/src/Model/Repository/ext.ts +103 -11
- package/src/Model/Repository/internal/internal.ts +266 -151
- package/src/Model/Repository/legacy.ts +3 -1
- package/src/Model/Repository/makeRepo.ts +15 -10
- package/src/Model/Repository/service.ts +35 -23
- package/src/Model/Repository/validation.ts +5 -5
- package/src/Model/Repository.ts +1 -0
- package/src/Model/dsl.ts +5 -4
- package/src/Model/filter/types/path/eager.ts +1 -2
- package/src/Model/query/dsl.ts +456 -20
- package/src/Model/query/new-kid-interpreter.ts +281 -7
- package/src/Model.ts +1 -0
- package/src/QueueMaker/SQLQueue.ts +150 -153
- package/src/QueueMaker/errors.ts +3 -1
- package/src/QueueMaker/memQueue.ts +111 -105
- package/src/QueueMaker/sbqueue.ts +76 -88
- package/src/QueueMaker/service.ts +3 -1
- package/src/RequestContext.ts +15 -16
- package/src/RequestFiberSet.ts +12 -7
- package/src/Store/ContextMapContainer.ts +46 -3
- package/src/Store/Cosmos/query.ts +214 -50
- package/src/Store/Cosmos.ts +491 -350
- package/src/Store/Disk.ts +106 -66
- package/src/Store/Memory.ts +365 -91
- package/src/Store/SQL/Pg.ts +364 -0
- package/src/Store/SQL/query.ts +603 -0
- package/src/Store/SQL.ts +736 -0
- package/src/Store/codeFilter.ts +5 -2
- package/src/Store/index.ts +20 -3
- package/src/Store/service.ts +51 -10
- package/src/Store/utils.ts +25 -23
- package/src/adapters/SQL/Model.ts +42 -41
- package/src/adapters/ServiceBus.ts +131 -121
- package/src/adapters/cosmos-client.ts +5 -3
- package/src/adapters/index.ts +7 -0
- package/src/adapters/memQueue.ts +5 -4
- package/src/adapters/mongo-client.ts +4 -2
- package/src/adapters/redis-client.ts +6 -2
- package/src/api/ContextProvider.ts +19 -16
- package/src/api/internal/RequestContextMiddleware.ts +17 -6
- package/src/api/internal/auth.ts +248 -44
- package/src/api/internal/events.ts +19 -10
- package/src/api/layerUtils.ts +13 -9
- package/src/api/reportError.ts +2 -1
- package/src/api/routing/middleware/RouterMiddleware.ts +5 -4
- package/src/api/routing/middleware/middleware.ts +60 -15
- package/src/api/routing/middleware.ts +0 -2
- package/src/api/routing/schema/jwt.ts +2 -1
- package/src/api/routing/utils.ts +2 -1
- package/src/api/routing.ts +309 -139
- package/src/api/setupRequest.ts +35 -12
- package/src/arbs.ts +5 -3
- package/src/errorReporter.ts +65 -75
- package/src/fileUtil.ts +1 -1
- package/src/logger/jsonLogger.ts +3 -1
- package/src/logger/logFmtLogger.ts +1 -1
- package/src/logger/shared.ts +3 -2
- package/src/otel.ts +152 -0
- package/src/rateLimit.ts +34 -23
- package/src/test.ts +2 -2
- package/test/auth.test.ts +101 -0
- package/test/contextProvider.test.ts +14 -11
- package/test/controller.test.ts +25 -29
- package/test/cosmos-query.test.ts +159 -0
- package/test/dist/auth.test.d.ts.map +1 -0
- package/test/dist/contextProvider.test.d.ts.map +1 -1
- package/test/dist/controller.test.d.ts.map +1 -1
- package/test/dist/cosmos-query.test.d.ts.map +1 -0
- package/test/dist/date-query.test.d.ts.map +1 -0
- package/test/dist/fixtures.d.ts +30 -12
- package/test/dist/fixtures.d.ts.map +1 -1
- package/test/dist/fixtures.js +17 -10
- package/test/dist/query.test.d.ts.map +1 -1
- package/test/dist/rawQuery.test.d.ts.map +1 -1
- package/test/dist/repository-ext.test.d.ts.map +1 -0
- package/test/dist/requires.test.d.ts.map +1 -1
- package/test/dist/router-generator.test.d.ts.map +1 -0
- package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
- package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
- package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
- package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
- package/test/dist/sql-store.test.d.ts.map +1 -0
- package/test/fixtures.ts +16 -9
- package/test/layerUtils.test.ts +1 -1
- package/test/query.test.ts +901 -38
- package/test/rawQuery.test.ts +338 -20
- package/test/repository-ext.test.ts +62 -0
- package/test/requires.test.ts +10 -5
- package/test/router-generator.test.ts +187 -0
- package/test/routing-interruptibility.test.ts +66 -0
- package/test/rpc-e2e-invalidation.test.ts +256 -0
- package/test/rpc-multi-middleware.test.ts +84 -9
- package/test/rpc-stream-fullstack.test.ts +304 -0
- package/test/sql-store.test.ts +1711 -0
- package/test/validateSample.test.ts +17 -12
- package/tsconfig.examples.json +1 -1
- package/tsconfig.json +0 -1
- package/tsconfig.json.bak +2 -2
- package/tsconfig.src.json +35 -35
- package/tsconfig.test.json +2 -2
- package/dist/Operations.d.ts +0 -55
- package/dist/Operations.d.ts.map +0 -1
- package/dist/Operations.js +0 -102
- package/dist/OperationsRepo.d.ts +0 -41
- package/dist/OperationsRepo.d.ts.map +0 -1
- package/dist/OperationsRepo.js +0 -14
- package/eslint.config.mjs +0 -24
- package/src/Operations.ts +0 -235
- package/src/OperationsRepo.ts +0 -16
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
3
|
-
import
|
|
3
|
+
import * as Array from "effect-app/Array"
|
|
4
|
+
import type { NonEmptyReadonlyArray } from "effect-app/Array"
|
|
5
|
+
import * as Effect from "effect-app/Effect"
|
|
4
6
|
import { assertUnreachable } from "effect-app/utils"
|
|
5
7
|
import { InfraLogger } from "../../logger.js"
|
|
6
8
|
import type { FilterR, FilterResult, Ops } from "../../Model/filter/filterApi.js"
|
|
9
|
+
import type { AggregateIrExpression, ComputedProjectionIrExpression, ComputedProjectionMathIrExpression } from "../../Model/query.js"
|
|
7
10
|
import { isRelationCheck } from "../codeFilter.js"
|
|
8
11
|
import type { SupportedValues } from "../service.js"
|
|
9
12
|
|
|
@@ -40,12 +43,26 @@ export function buildWhereCosmosQuery3(
|
|
|
40
43
|
filter: readonly FilterResult[],
|
|
41
44
|
name: string,
|
|
42
45
|
defaultValues: Record<string, unknown>,
|
|
43
|
-
select?: NonEmptyReadonlyArray<
|
|
46
|
+
select?: NonEmptyReadonlyArray<
|
|
47
|
+
string | {
|
|
48
|
+
key: string
|
|
49
|
+
subKeys: readonly string[]
|
|
50
|
+
} | {
|
|
51
|
+
key: string
|
|
52
|
+
computed: ComputedProjectionIrExpression
|
|
53
|
+
} | {
|
|
54
|
+
key: string
|
|
55
|
+
path: string
|
|
56
|
+
} | {
|
|
57
|
+
key: string
|
|
58
|
+
aggregate: AggregateIrExpression
|
|
59
|
+
}
|
|
60
|
+
>,
|
|
44
61
|
order?: NonEmptyReadonlyArray<{ key: string; direction: "ASC" | "DESC" }>,
|
|
45
62
|
skip?: number,
|
|
46
63
|
limit?: number
|
|
47
64
|
) {
|
|
48
|
-
const statement = (x: FilterR, i: number
|
|
65
|
+
const statement = (x: FilterR, i: number) => {
|
|
49
66
|
if (x.path === idKey) {
|
|
50
67
|
x = { ...x, path: "id" }
|
|
51
68
|
}
|
|
@@ -60,8 +77,6 @@ export function buildWhereCosmosQuery3(
|
|
|
60
77
|
|
|
61
78
|
const v = "@v" + i
|
|
62
79
|
|
|
63
|
-
const realValue = values[i]
|
|
64
|
-
|
|
65
80
|
switch (x.op) {
|
|
66
81
|
case "in":
|
|
67
82
|
return `ARRAY_CONTAINS(${v}, ${k})`
|
|
@@ -74,14 +89,22 @@ export function buildWhereCosmosQuery3(
|
|
|
74
89
|
return `(NOT ARRAY_CONTAINS(${k}, ${v}))`
|
|
75
90
|
|
|
76
91
|
case "includes-any":
|
|
77
|
-
return `ARRAY_CONTAINS_ANY(${k}, ${
|
|
92
|
+
return `ARRAY_CONTAINS_ANY(${k}, ${
|
|
93
|
+
(x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
|
|
94
|
+
})`
|
|
78
95
|
case "notIncludes-any":
|
|
79
|
-
return `(NOT ARRAY_CONTAINS_ANY(${k}, ${
|
|
96
|
+
return `(NOT ARRAY_CONTAINS_ANY(${k}, ${
|
|
97
|
+
(x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
|
|
98
|
+
}))`
|
|
80
99
|
|
|
81
100
|
case "includes-all":
|
|
82
|
-
return `ARRAY_CONTAINS_ALL(${k}, ${
|
|
101
|
+
return `ARRAY_CONTAINS_ALL(${k}, ${
|
|
102
|
+
(x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
|
|
103
|
+
})`
|
|
83
104
|
case "notIncludes-all":
|
|
84
|
-
return `(NOT ARRAY_CONTAINS_ALL(${k}, ${
|
|
105
|
+
return `(NOT ARRAY_CONTAINS_ALL(${k}, ${
|
|
106
|
+
(x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
|
|
107
|
+
}))`
|
|
85
108
|
|
|
86
109
|
case "contains":
|
|
87
110
|
return `CONTAINS(${k}, ${v}, true)`
|
|
@@ -165,7 +188,7 @@ export function buildWhereCosmosQuery3(
|
|
|
165
188
|
: _
|
|
166
189
|
: _
|
|
167
190
|
|
|
168
|
-
const print = (state: readonly FilterResult[],
|
|
191
|
+
const print = (state: readonly FilterResult[], isRelation: string | null, every: boolean) => {
|
|
169
192
|
let s = ""
|
|
170
193
|
let l = 0
|
|
171
194
|
const printN = (n: number) => {
|
|
@@ -174,13 +197,13 @@ export function buildWhereCosmosQuery3(
|
|
|
174
197
|
for (const e of state) {
|
|
175
198
|
switch (e.t) {
|
|
176
199
|
case "where":
|
|
177
|
-
s += statement(e, i
|
|
200
|
+
s += statement(e, i++)
|
|
178
201
|
break
|
|
179
202
|
case "or":
|
|
180
|
-
s += ` OR ${statement(e, i
|
|
203
|
+
s += ` OR ${statement(e, i++)}`
|
|
181
204
|
break
|
|
182
205
|
case "and":
|
|
183
|
-
s += ` AND ${statement(e, i
|
|
206
|
+
s += ` AND ${statement(e, i++)}`
|
|
184
207
|
break
|
|
185
208
|
case "or-scope": {
|
|
186
209
|
++l
|
|
@@ -189,7 +212,7 @@ export function buildWhereCosmosQuery3(
|
|
|
189
212
|
if (rel) {
|
|
190
213
|
const rel = (e.result[0]! as { path: string }).path.split(".-1.")[0]
|
|
191
214
|
s += isRelation
|
|
192
|
-
? ` OR (\n${printN(l + 1)}${print(e.result,
|
|
215
|
+
? ` OR (\n${printN(l + 1)}${print(e.result, rel, every)}\n${printN(l)})`
|
|
193
216
|
: ` OR (\n${printN(l + 1)}${
|
|
194
217
|
every ? "NOT " : ""
|
|
195
218
|
}EXISTS(SELECT VALUE ${rel} FROM ${rel} IN f.${rel} WHERE ${
|
|
@@ -197,13 +220,12 @@ export function buildWhereCosmosQuery3(
|
|
|
197
220
|
e
|
|
198
221
|
.result
|
|
199
222
|
.map(flip(every)),
|
|
200
|
-
values,
|
|
201
223
|
rel,
|
|
202
224
|
every
|
|
203
225
|
)
|
|
204
226
|
}))`
|
|
205
227
|
} else {
|
|
206
|
-
s += ` OR (\n${printN(l + 1)}${print(e.result,
|
|
228
|
+
s += ` OR (\n${printN(l + 1)}${print(e.result, null, every)}\n${printN(l)})`
|
|
207
229
|
}
|
|
208
230
|
--l
|
|
209
231
|
break
|
|
@@ -215,14 +237,14 @@ export function buildWhereCosmosQuery3(
|
|
|
215
237
|
if (rel) {
|
|
216
238
|
const rel = (e.result[0]! as { path: string }).path.split(".-1.")[0]
|
|
217
239
|
s += isRelation
|
|
218
|
-
? ` AND (\n${printN(l + 1)}${print(e.result,
|
|
240
|
+
? ` AND (\n${printN(l + 1)}${print(e.result, rel, every)}\n${printN(l)})`
|
|
219
241
|
: ` AND (\n${printN(l + 1)}${
|
|
220
242
|
every ? "NOT " : ""
|
|
221
243
|
}EXISTS(SELECT VALUE ${rel} FROM ${rel} IN f.${rel} WHERE ${
|
|
222
|
-
print(e.result.map(flip(every)),
|
|
244
|
+
print(e.result.map(flip(every)), rel, every)
|
|
223
245
|
}))`
|
|
224
246
|
} else {
|
|
225
|
-
s += ` AND (\n${printN(l + 1)}${print(e.result,
|
|
247
|
+
s += ` AND (\n${printN(l + 1)}${print(e.result, null, every)}\n${printN(l)})`
|
|
226
248
|
}
|
|
227
249
|
--l
|
|
228
250
|
break
|
|
@@ -234,12 +256,12 @@ export function buildWhereCosmosQuery3(
|
|
|
234
256
|
if (rel) {
|
|
235
257
|
const rel = (e.result[0]! as { path: string }).path.split(".-1.")[0]
|
|
236
258
|
s += isRelation
|
|
237
|
-
? `(\n${printN(l + 1)}${print(e.result,
|
|
259
|
+
? `(\n${printN(l + 1)}${print(e.result, rel, every)}\n${printN(l)})`
|
|
238
260
|
: `(\n${printN(l + 1)}${every ? "NOT " : ""}EXISTS(SELECT VALUE ${rel} FROM ${rel} IN f.${rel} WHERE ${
|
|
239
|
-
print(e.result.map(flip(every)),
|
|
261
|
+
print(e.result.map(flip(every)), rel, every)
|
|
240
262
|
}))`
|
|
241
263
|
} else {
|
|
242
|
-
s += `(\n${printN(l + 1)}${print(e.result,
|
|
264
|
+
s += `(\n${printN(l + 1)}${print(e.result, null, every)}\n${printN(l)})`
|
|
243
265
|
}
|
|
244
266
|
// ;--l
|
|
245
267
|
break
|
|
@@ -272,40 +294,182 @@ export function buildWhereCosmosQuery3(
|
|
|
272
294
|
? getValues(_.result)
|
|
273
295
|
: [_]
|
|
274
296
|
)
|
|
275
|
-
const
|
|
297
|
+
const computedFilters = select
|
|
298
|
+
? select.flatMap((_) =>
|
|
299
|
+
typeof _ === "object" && "computed" in _ && "filter" in _.computed ? getValues(_.computed.filter) : []
|
|
300
|
+
)
|
|
301
|
+
: []
|
|
302
|
+
const aggregateFilters = select
|
|
303
|
+
? select.flatMap((_) =>
|
|
304
|
+
typeof _ === "object" && "aggregate" in _ && "filter" in _.aggregate ? getValues(_.aggregate.filter) : []
|
|
305
|
+
)
|
|
306
|
+
: []
|
|
307
|
+
const values = [...computedFilters, ...aggregateFilters, ...getValues(filter)]
|
|
308
|
+
|
|
309
|
+
const hasAggregates = select
|
|
310
|
+
? select.some((s) => typeof s === "object" && s !== null && "aggregate" in s)
|
|
311
|
+
: false
|
|
312
|
+
|
|
313
|
+
const aggregateSelectExpr = (key: string, agg: AggregateIrExpression): string => {
|
|
314
|
+
switch (agg._tag) {
|
|
315
|
+
case "agg-count":
|
|
316
|
+
return `COUNT(1) AS ${key}`
|
|
317
|
+
case "agg-count-when": {
|
|
318
|
+
if (agg.filter.length === 0) return `COUNT(1) AS ${key}`
|
|
319
|
+
const cond = print(agg.filter, null, false)
|
|
320
|
+
// Cosmos supports SUM(IIF(cond, 1, 0)) as a conditional count
|
|
321
|
+
return `SUM(IIF(${cond}, 1, 0)) AS ${key}`
|
|
322
|
+
}
|
|
323
|
+
case "agg-sum": {
|
|
324
|
+
const fieldRef = dottedToAccess(`f.${agg.field}`)
|
|
325
|
+
return `SUM(${fieldRef}) AS ${key}`
|
|
326
|
+
}
|
|
327
|
+
case "agg-min": {
|
|
328
|
+
const fieldRef = dottedToAccess(`f.${agg.field}`)
|
|
329
|
+
return `MIN(${fieldRef}) AS ${key}`
|
|
330
|
+
}
|
|
331
|
+
case "agg-max": {
|
|
332
|
+
const fieldRef = dottedToAccess(`f.${agg.field}`)
|
|
333
|
+
return `MAX(${fieldRef}) AS ${key}`
|
|
334
|
+
}
|
|
335
|
+
default:
|
|
336
|
+
return assertUnreachable(agg)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const computedSelectExpr = (key: string, computed: ComputedProjectionIrExpression) => {
|
|
341
|
+
const relationPath = computed.path
|
|
342
|
+
const relationAlias = relationPath
|
|
343
|
+
const relationSource = dottedToAccess(`f.${relationPath}`)
|
|
344
|
+
const compileExpr = (expression: ComputedProjectionMathIrExpression): string => {
|
|
345
|
+
switch (expression._tag) {
|
|
346
|
+
case "field":
|
|
347
|
+
return dottedToAccess(`${relationAlias}.${expression.field}`)
|
|
348
|
+
case "mul":
|
|
349
|
+
return `(${compileExpr(expression.left)} * ${compileExpr(expression.right)})`
|
|
350
|
+
default:
|
|
351
|
+
return assertUnreachable(expression)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
const factorExpr = (unitExpr: string, toBase: string, factors: Readonly<Record<string, number>>) => {
|
|
355
|
+
const entries = Object.entries(factors).filter(([, factor]) => Number.isFinite(factor))
|
|
356
|
+
return entries.reduceRight<string>(
|
|
357
|
+
(acc, [unit, factor]) => `IIF(${unitExpr} = ${JSON.stringify(unit)}, ${factor}, ${acc})`,
|
|
358
|
+
`IIF(${unitExpr} = ${JSON.stringify(toBase)}, 1, 0)`
|
|
359
|
+
)
|
|
360
|
+
}
|
|
361
|
+
const filter = "filter" in computed ? computed.filter : []
|
|
362
|
+
// Print filter once — `print` mutates the outer `i` parameter counter, so
|
|
363
|
+
// re-walking the same filter would double-bump it and desync @v indices.
|
|
364
|
+
const filterSql = filter.length > 0 ? print(filter, relationPath, false) : ""
|
|
365
|
+
const where = filterSql ? ` WHERE ${filterSql}` : ""
|
|
366
|
+
switch (computed._tag) {
|
|
367
|
+
case "relation-count":
|
|
368
|
+
return `(SELECT VALUE COUNT(1) FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
|
|
369
|
+
case "relation-any":
|
|
370
|
+
return `EXISTS(SELECT VALUE ${relationAlias} FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
|
|
371
|
+
case "relation-every": {
|
|
372
|
+
// ∀x.P(x) ≡ ¬∃x.¬P(x). Cosmos has no NOT(...) on EXISTS subqueries directly,
|
|
373
|
+
// but we can flip via NOT EXISTS(... WHERE NOT (filter)).
|
|
374
|
+
if (filter.length === 0) return `true AS ${key}`
|
|
375
|
+
return `NOT EXISTS(SELECT VALUE ${relationAlias} FROM ${relationAlias} IN ${relationSource} WHERE NOT (${filterSql})) AS ${key}`
|
|
376
|
+
}
|
|
377
|
+
case "relation-distinct-count": {
|
|
378
|
+
const fieldRef = dottedToAccess(`${relationAlias}.${computed.field}`)
|
|
379
|
+
return `(SELECT VALUE COUNT(1) FROM (SELECT DISTINCT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where})) AS ${key}`
|
|
380
|
+
}
|
|
381
|
+
case "relation-sum": {
|
|
382
|
+
const fieldRef = dottedToAccess(`${relationAlias}.${computed.field}`)
|
|
383
|
+
return `(SELECT VALUE SUM(${fieldRef}) FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
|
|
384
|
+
}
|
|
385
|
+
case "relation-sum-expr": {
|
|
386
|
+
const expression = compileExpr(computed.expression)
|
|
387
|
+
return `(SELECT VALUE SUM(${expression}) FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
|
|
388
|
+
}
|
|
389
|
+
case "relation-sum-expr-by": {
|
|
390
|
+
const unitRef = dottedToAccess(`${relationAlias}.${computed.unit}`)
|
|
391
|
+
const expression = compileExpr(computed.expression)
|
|
392
|
+
return `ARRAY(SELECT VALUE { "unit": ${unitRef}, "total": SUM(${expression}) } FROM ${relationAlias} IN ${relationSource}${where} GROUP BY ${unitRef}) AS ${key}`
|
|
393
|
+
}
|
|
394
|
+
case "relation-sum-expr-normalized": {
|
|
395
|
+
const unitRef = dottedToAccess(`${relationAlias}.${computed.unit}`)
|
|
396
|
+
const expression = compileExpr(computed.expression)
|
|
397
|
+
const factor = factorExpr(unitRef, computed.toBase, computed.factors)
|
|
398
|
+
return `(SELECT VALUE SUM((${expression}) * (${factor})) FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
|
|
399
|
+
}
|
|
400
|
+
case "relation-collect": {
|
|
401
|
+
const fieldRef = dottedToAccess(`${relationAlias}.${computed.field}`)
|
|
402
|
+
if (computed.distinct) {
|
|
403
|
+
return `ARRAY(SELECT DISTINCT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
|
|
404
|
+
}
|
|
405
|
+
return `ARRAY(SELECT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
|
|
406
|
+
}
|
|
407
|
+
case "relation-length":
|
|
408
|
+
return `ARRAY_LENGTH(${relationSource}) AS ${key}`
|
|
409
|
+
case "relation-collect-fields": {
|
|
410
|
+
const subqueries = computed.fields.map((field) => {
|
|
411
|
+
const fieldRef = dottedToAccess(`${relationAlias}.${field}`)
|
|
412
|
+
return computed.distinct
|
|
413
|
+
? `ARRAY(SELECT DISTINCT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where})`
|
|
414
|
+
: `ARRAY(SELECT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where})`
|
|
415
|
+
})
|
|
416
|
+
const combined = computed.distinct
|
|
417
|
+
? subqueries.reduce((acc, sq) => `SetUnion(${acc}, ${sq})`)
|
|
418
|
+
: subqueries.reduce((acc, sq) => `ARRAY_CONCAT(${acc}, ${sq})`)
|
|
419
|
+
return `${combined} AS ${key}`
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const buildSelectList = (): string => {
|
|
425
|
+
if (!select) return "f"
|
|
426
|
+
return select
|
|
427
|
+
.map((s) => {
|
|
428
|
+
if (typeof s === "string") {
|
|
429
|
+
return dottedToAccess(s === idKey ? "f.id" : `f.${s}`)
|
|
430
|
+
}
|
|
431
|
+
if ("computed" in s) return computedSelectExpr(s.key, s.computed)
|
|
432
|
+
if ("aggregate" in s) return aggregateSelectExpr(s.key, s.aggregate)
|
|
433
|
+
if ("path" in s) return `${dottedToAccess(`f.${s.path}`)} AS ${s.key}`
|
|
434
|
+
// subKeys
|
|
435
|
+
return `ARRAY (SELECT ${s.subKeys.map((_) => dottedToAccess(`t.${_}`)).join(",")}
|
|
436
|
+
FROM t in ${dottedToAccess(`f.${s.key}`)}) AS ${s.key}`
|
|
437
|
+
})
|
|
438
|
+
.join(", ")
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const groupByClause = hasAggregates && select
|
|
442
|
+
? (() => {
|
|
443
|
+
const groupByExprs = select
|
|
444
|
+
.filter((s): s is { key: string; path: string } =>
|
|
445
|
+
typeof s === "object" && s !== null && "path" in s && !("aggregate" in s)
|
|
446
|
+
)
|
|
447
|
+
.map((s) => dottedToAccess(`f.${s.path}`))
|
|
448
|
+
return groupByExprs.length > 0 ? `GROUP BY ${groupByExprs.join(", ")}` : ""
|
|
449
|
+
})()
|
|
450
|
+
: ""
|
|
451
|
+
|
|
452
|
+
const orderExpr = (key: string) => hasAggregates ? key : dottedToAccess(`f.${key}`)
|
|
453
|
+
|
|
276
454
|
// with joins, you should use DISTINCT
|
|
277
455
|
// or you can end up with duplicates
|
|
278
456
|
return {
|
|
279
457
|
query: `
|
|
280
|
-
SELECT ${
|
|
281
|
-
select
|
|
282
|
-
? `${
|
|
283
|
-
select
|
|
284
|
-
.map((s) =>
|
|
285
|
-
typeof s === "string"
|
|
286
|
-
? dottedToAccess(s === idKey ? "f.id" : `f.${s}`) // x["y"} vs x.y, helps with reserved keywords like "value"
|
|
287
|
-
: `ARRAY (SELECT ${s.subKeys.map((_) => dottedToAccess(`t.${_}`)).join(",")}
|
|
288
|
-
FROM t in ${dottedToAccess(`f.${s.key}`)}) AS ${s.key}`
|
|
289
|
-
)
|
|
290
|
-
.join(", ")
|
|
291
|
-
}`
|
|
292
|
-
: "f"
|
|
293
|
-
}
|
|
458
|
+
SELECT ${buildSelectList()}
|
|
294
459
|
FROM ${name} f
|
|
295
460
|
|
|
296
|
-
${filter.length ? `WHERE (${print(filter,
|
|
297
|
-
${
|
|
461
|
+
${filter.length ? `WHERE (${print(filter, null, false)})` : ""}
|
|
462
|
+
${groupByClause}
|
|
463
|
+
${order ? `ORDER BY ${order.map((_) => `${orderExpr(_.key)} ${_.direction}`).join(", ")}` : ""}
|
|
298
464
|
${skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""}`,
|
|
299
|
-
parameters:
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
)
|
|
309
|
-
]
|
|
465
|
+
parameters: values
|
|
466
|
+
.flatMap((x, i) =>
|
|
467
|
+
[{
|
|
468
|
+
name: `@v${i}`,
|
|
469
|
+
value: x.value as any
|
|
470
|
+
}]
|
|
471
|
+
// TODO: only for arrays that are used with _ANY or _ALL
|
|
472
|
+
.concat(Array.isArray(x.value) ? x.value.map((_, i2) => ({ name: `@v${i}__${i2}`, value: _ as any })) : [])
|
|
473
|
+
)
|
|
310
474
|
}
|
|
311
475
|
}
|