@effect-app/infra 4.0.0-beta.22 → 4.0.0-beta.221

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.
Files changed (337) hide show
  1. package/CHANGELOG.md +1648 -0
  2. package/_check.sh +1 -1
  3. package/dist/CUPS.d.ts +12 -7
  4. package/dist/CUPS.d.ts.map +1 -1
  5. package/dist/CUPS.js +16 -12
  6. package/dist/Emailer/Sendgrid.d.ts +15 -15
  7. package/dist/Emailer/Sendgrid.d.ts.map +1 -1
  8. package/dist/Emailer/Sendgrid.js +20 -16
  9. package/dist/Emailer/fake.d.ts +1 -1
  10. package/dist/Emailer/fake.js +2 -2
  11. package/dist/Emailer/service.d.ts +13 -4
  12. package/dist/Emailer/service.d.ts.map +1 -1
  13. package/dist/Emailer/service.js +4 -3
  14. package/dist/Emailer.d.ts +1 -1
  15. package/dist/MainFiberSet.d.ts +12 -9
  16. package/dist/MainFiberSet.d.ts.map +1 -1
  17. package/dist/MainFiberSet.js +7 -3
  18. package/dist/Model/Repository/Registry.d.ts +21 -0
  19. package/dist/Model/Repository/Registry.d.ts.map +1 -0
  20. package/dist/Model/Repository/Registry.js +18 -0
  21. package/dist/Model/Repository/ext.d.ts +35 -16
  22. package/dist/Model/Repository/ext.d.ts.map +1 -1
  23. package/dist/Model/Repository/ext.js +60 -3
  24. package/dist/Model/Repository/internal/internal.d.ts +9 -6
  25. package/dist/Model/Repository/internal/internal.d.ts.map +1 -1
  26. package/dist/Model/Repository/internal/internal.js +115 -51
  27. package/dist/Model/Repository/legacy.d.ts +4 -2
  28. package/dist/Model/Repository/legacy.d.ts.map +1 -1
  29. package/dist/Model/Repository/makeRepo.d.ts +10 -6
  30. package/dist/Model/Repository/makeRepo.d.ts.map +1 -1
  31. package/dist/Model/Repository/makeRepo.js +5 -2
  32. package/dist/Model/Repository/service.d.ts +32 -24
  33. package/dist/Model/Repository/service.d.ts.map +1 -1
  34. package/dist/Model/Repository/validation.d.ts +47 -18
  35. package/dist/Model/Repository/validation.d.ts.map +1 -1
  36. package/dist/Model/Repository/validation.js +6 -6
  37. package/dist/Model/Repository.d.ts +2 -1
  38. package/dist/Model/Repository.d.ts.map +1 -1
  39. package/dist/Model/Repository.js +2 -1
  40. package/dist/Model/dsl.d.ts +6 -5
  41. package/dist/Model/dsl.d.ts.map +1 -1
  42. package/dist/Model/dsl.js +2 -3
  43. package/dist/Model/filter/filterApi.d.ts +5 -5
  44. package/dist/Model/filter/filterApi.d.ts.map +1 -1
  45. package/dist/Model/filter/types/errors.d.ts +1 -1
  46. package/dist/Model/filter/types/fields.d.ts +1 -1
  47. package/dist/Model/filter/types/path/common.d.ts +1 -1
  48. package/dist/Model/filter/types/path/eager.d.ts +1 -1
  49. package/dist/Model/filter/types/path/eager.d.ts.map +1 -1
  50. package/dist/Model/filter/types/path/eager.js +1 -1
  51. package/dist/Model/filter/types/path/index.d.ts +1 -1
  52. package/dist/Model/filter/types/utils.d.ts +1 -1
  53. package/dist/Model/filter/types/validator.d.ts +1 -1
  54. package/dist/Model/filter/types.d.ts +1 -1
  55. package/dist/Model/query/dsl.d.ts +142 -17
  56. package/dist/Model/query/dsl.d.ts.map +1 -1
  57. package/dist/Model/query/dsl.js +190 -5
  58. package/dist/Model/query/new-kid-interpreter.d.ts +77 -8
  59. package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -1
  60. package/dist/Model/query/new-kid-interpreter.js +127 -6
  61. package/dist/Model/query.d.ts +1 -1
  62. package/dist/Model.d.ts +2 -1
  63. package/dist/Model.d.ts.map +1 -1
  64. package/dist/Model.js +2 -1
  65. package/dist/QueueMaker/SQLQueue.d.ts +7 -8
  66. package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
  67. package/dist/QueueMaker/SQLQueue.js +135 -117
  68. package/dist/QueueMaker/errors.d.ts +5 -3
  69. package/dist/QueueMaker/errors.d.ts.map +1 -1
  70. package/dist/QueueMaker/errors.js +4 -2
  71. package/dist/QueueMaker/memQueue.d.ts +9 -5
  72. package/dist/QueueMaker/memQueue.d.ts.map +1 -1
  73. package/dist/QueueMaker/memQueue.js +81 -65
  74. package/dist/QueueMaker/sbqueue.d.ts +8 -4
  75. package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
  76. package/dist/QueueMaker/sbqueue.js +57 -55
  77. package/dist/QueueMaker/service.d.ts +4 -2
  78. package/dist/QueueMaker/service.d.ts.map +1 -1
  79. package/dist/QueueMaker/service.js +1 -1
  80. package/dist/RequestContext.d.ts +75 -35
  81. package/dist/RequestContext.d.ts.map +1 -1
  82. package/dist/RequestContext.js +14 -14
  83. package/dist/RequestFiberSet.d.ts +10 -7
  84. package/dist/RequestFiberSet.d.ts.map +1 -1
  85. package/dist/RequestFiberSet.js +8 -3
  86. package/dist/Store/ContextMapContainer.d.ts +22 -3
  87. package/dist/Store/ContextMapContainer.d.ts.map +1 -1
  88. package/dist/Store/ContextMapContainer.js +17 -3
  89. package/dist/Store/Cosmos/query.d.ts +7 -2
  90. package/dist/Store/Cosmos/query.d.ts.map +1 -1
  91. package/dist/Store/Cosmos/query.js +115 -35
  92. package/dist/Store/Cosmos.d.ts +2 -2
  93. package/dist/Store/Cosmos.d.ts.map +1 -1
  94. package/dist/Store/Cosmos.js +343 -244
  95. package/dist/Store/Disk.d.ts +3 -3
  96. package/dist/Store/Disk.d.ts.map +1 -1
  97. package/dist/Store/Disk.js +76 -36
  98. package/dist/Store/Memory.d.ts +7 -4
  99. package/dist/Store/Memory.d.ts.map +1 -1
  100. package/dist/Store/Memory.js +251 -58
  101. package/dist/Store/SQL/Pg.d.ts +4 -0
  102. package/dist/Store/SQL/Pg.d.ts.map +1 -0
  103. package/dist/Store/SQL/Pg.js +233 -0
  104. package/dist/Store/SQL/query.d.ts +43 -0
  105. package/dist/Store/SQL/query.d.ts.map +1 -0
  106. package/dist/Store/SQL/query.js +478 -0
  107. package/dist/Store/SQL.d.ts +21 -0
  108. package/dist/Store/SQL.d.ts.map +1 -0
  109. package/dist/Store/SQL.js +450 -0
  110. package/dist/Store/codeFilter.d.ts +2 -2
  111. package/dist/Store/codeFilter.d.ts.map +1 -1
  112. package/dist/Store/codeFilter.js +6 -3
  113. package/dist/Store/index.d.ts +6 -3
  114. package/dist/Store/index.d.ts.map +1 -1
  115. package/dist/Store/index.js +18 -4
  116. package/dist/Store/service.d.ts +26 -8
  117. package/dist/Store/service.d.ts.map +1 -1
  118. package/dist/Store/service.js +25 -6
  119. package/dist/Store/utils.d.ts +3 -2
  120. package/dist/Store/utils.d.ts.map +1 -1
  121. package/dist/Store/utils.js +5 -5
  122. package/dist/Store.d.ts +1 -1
  123. package/dist/adapters/SQL/Model.d.ts +32 -43
  124. package/dist/adapters/SQL/Model.d.ts.map +1 -1
  125. package/dist/adapters/SQL/Model.js +30 -39
  126. package/dist/adapters/SQL.d.ts +1 -1
  127. package/dist/adapters/ServiceBus.d.ts +14 -11
  128. package/dist/adapters/ServiceBus.d.ts.map +1 -1
  129. package/dist/adapters/ServiceBus.js +30 -21
  130. package/dist/adapters/cosmos-client.d.ts +5 -3
  131. package/dist/adapters/cosmos-client.d.ts.map +1 -1
  132. package/dist/adapters/cosmos-client.js +5 -3
  133. package/dist/adapters/index.d.ts +8 -2
  134. package/dist/adapters/index.d.ts.map +1 -1
  135. package/dist/adapters/index.js +8 -2
  136. package/dist/adapters/logger.d.ts +2 -2
  137. package/dist/adapters/logger.d.ts.map +1 -1
  138. package/dist/adapters/memQueue.d.ts +5 -3
  139. package/dist/adapters/memQueue.d.ts.map +1 -1
  140. package/dist/adapters/memQueue.js +6 -5
  141. package/dist/adapters/mongo-client.d.ts +4 -3
  142. package/dist/adapters/mongo-client.d.ts.map +1 -1
  143. package/dist/adapters/mongo-client.js +5 -3
  144. package/dist/adapters/redis-client.d.ts +6 -3
  145. package/dist/adapters/redis-client.d.ts.map +1 -1
  146. package/dist/adapters/redis-client.js +7 -3
  147. package/dist/api/ContextProvider.d.ts +12 -8
  148. package/dist/api/ContextProvider.d.ts.map +1 -1
  149. package/dist/api/ContextProvider.js +9 -7
  150. package/dist/api/codec.d.ts +1 -1
  151. package/dist/api/internal/RequestContextMiddleware.d.ts +3 -3
  152. package/dist/api/internal/RequestContextMiddleware.d.ts.map +1 -1
  153. package/dist/api/internal/RequestContextMiddleware.js +10 -6
  154. package/dist/api/internal/auth.d.ts +45 -7
  155. package/dist/api/internal/auth.d.ts.map +1 -1
  156. package/dist/api/internal/auth.js +162 -29
  157. package/dist/api/internal/events.d.ts +6 -4
  158. package/dist/api/internal/events.d.ts.map +1 -1
  159. package/dist/api/internal/events.js +16 -9
  160. package/dist/api/internal/health.d.ts +1 -1
  161. package/dist/api/layerUtils.d.ts +10 -6
  162. package/dist/api/layerUtils.d.ts.map +1 -1
  163. package/dist/api/layerUtils.js +7 -6
  164. package/dist/api/middlewares.d.ts +1 -1
  165. package/dist/api/reportError.d.ts +2 -2
  166. package/dist/api/reportError.d.ts.map +1 -1
  167. package/dist/api/reportError.js +3 -2
  168. package/dist/api/routing/middleware/RouterMiddleware.d.ts +5 -4
  169. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +1 -1
  170. package/dist/api/routing/middleware/middleware.d.ts +42 -3
  171. package/dist/api/routing/middleware/middleware.d.ts.map +1 -1
  172. package/dist/api/routing/middleware/middleware.js +53 -17
  173. package/dist/api/routing/middleware.d.ts +1 -2
  174. package/dist/api/routing/middleware.d.ts.map +1 -1
  175. package/dist/api/routing/middleware.js +1 -2
  176. package/dist/api/routing/schema/jwt.d.ts +1 -1
  177. package/dist/api/routing/schema/jwt.d.ts.map +1 -1
  178. package/dist/api/routing/schema/jwt.js +3 -2
  179. package/dist/api/routing/tsort.d.ts +1 -1
  180. package/dist/api/routing/tsort.d.ts.map +1 -1
  181. package/dist/api/routing/utils.d.ts +4 -4
  182. package/dist/api/routing/utils.d.ts.map +1 -1
  183. package/dist/api/routing/utils.js +3 -2
  184. package/dist/api/routing.d.ts +84 -37
  185. package/dist/api/routing.d.ts.map +1 -1
  186. package/dist/api/routing.js +115 -45
  187. package/dist/api/setupRequest.d.ts +10 -6
  188. package/dist/api/setupRequest.d.ts.map +1 -1
  189. package/dist/api/setupRequest.js +15 -7
  190. package/dist/api/util.d.ts +1 -1
  191. package/dist/arbs.d.ts +2 -2
  192. package/dist/arbs.d.ts.map +1 -1
  193. package/dist/arbs.js +5 -3
  194. package/dist/errorReporter.d.ts +7 -5
  195. package/dist/errorReporter.d.ts.map +1 -1
  196. package/dist/errorReporter.js +22 -26
  197. package/dist/errors.d.ts +1 -1
  198. package/dist/fileUtil.d.ts +2 -2
  199. package/dist/fileUtil.d.ts.map +1 -1
  200. package/dist/fileUtil.js +2 -2
  201. package/dist/index.d.ts +1 -1
  202. package/dist/logger/jsonLogger.d.ts +2 -2
  203. package/dist/logger/jsonLogger.d.ts.map +1 -1
  204. package/dist/logger/jsonLogger.js +4 -2
  205. package/dist/logger/logFmtLogger.d.ts +2 -2
  206. package/dist/logger/logFmtLogger.d.ts.map +1 -1
  207. package/dist/logger/logFmtLogger.js +2 -2
  208. package/dist/logger/shared.d.ts +2 -2
  209. package/dist/logger/shared.d.ts.map +1 -1
  210. package/dist/logger/shared.js +3 -3
  211. package/dist/logger.d.ts +1 -1
  212. package/dist/logger.d.ts.map +1 -1
  213. package/dist/otel.d.ts +75 -0
  214. package/dist/otel.d.ts.map +1 -0
  215. package/dist/otel.js +65 -0
  216. package/dist/rateLimit.d.ts +12 -4
  217. package/dist/rateLimit.d.ts.map +1 -1
  218. package/dist/rateLimit.js +7 -12
  219. package/dist/test.d.ts +3 -3
  220. package/dist/test.d.ts.map +1 -1
  221. package/dist/test.js +2 -2
  222. package/dist/vitest.d.ts +1 -1
  223. package/examples/query.ts +46 -38
  224. package/package.json +46 -37
  225. package/src/CUPS.ts +15 -11
  226. package/src/Emailer/Sendgrid.ts +21 -15
  227. package/src/Emailer/fake.ts +1 -1
  228. package/src/Emailer/service.ts +13 -3
  229. package/src/MainFiberSet.ts +9 -6
  230. package/src/Model/Repository/Registry.ts +34 -0
  231. package/src/Model/Repository/ext.ts +103 -11
  232. package/src/Model/Repository/internal/internal.ts +231 -149
  233. package/src/Model/Repository/legacy.ts +3 -1
  234. package/src/Model/Repository/makeRepo.ts +15 -10
  235. package/src/Model/Repository/service.ts +35 -23
  236. package/src/Model/Repository/validation.ts +5 -5
  237. package/src/Model/Repository.ts +1 -0
  238. package/src/Model/dsl.ts +5 -4
  239. package/src/Model/filter/types/path/eager.ts +1 -2
  240. package/src/Model/query/dsl.ts +353 -19
  241. package/src/Model/query/new-kid-interpreter.ts +211 -6
  242. package/src/Model.ts +1 -0
  243. package/src/QueueMaker/SQLQueue.ts +150 -153
  244. package/src/QueueMaker/errors.ts +3 -1
  245. package/src/QueueMaker/memQueue.ts +111 -105
  246. package/src/QueueMaker/sbqueue.ts +76 -88
  247. package/src/QueueMaker/service.ts +3 -1
  248. package/src/RequestContext.ts +15 -16
  249. package/src/RequestFiberSet.ts +8 -2
  250. package/src/Store/ContextMapContainer.ts +45 -2
  251. package/src/Store/Cosmos/query.ts +143 -44
  252. package/src/Store/Cosmos.ts +491 -350
  253. package/src/Store/Disk.ts +106 -66
  254. package/src/Store/Memory.ts +285 -87
  255. package/src/Store/SQL/Pg.ts +364 -0
  256. package/src/Store/SQL/query.ts +540 -0
  257. package/src/Store/SQL.ts +736 -0
  258. package/src/Store/codeFilter.ts +5 -2
  259. package/src/Store/index.ts +20 -3
  260. package/src/Store/service.ts +45 -10
  261. package/src/Store/utils.ts +25 -23
  262. package/src/adapters/SQL/Model.ts +42 -41
  263. package/src/adapters/ServiceBus.ts +131 -121
  264. package/src/adapters/cosmos-client.ts +4 -2
  265. package/src/adapters/index.ts +7 -0
  266. package/src/adapters/memQueue.ts +5 -4
  267. package/src/adapters/mongo-client.ts +4 -2
  268. package/src/adapters/redis-client.ts +6 -2
  269. package/src/api/ContextProvider.ts +17 -13
  270. package/src/api/internal/RequestContextMiddleware.ts +16 -5
  271. package/src/api/internal/auth.ts +248 -44
  272. package/src/api/internal/events.ts +19 -10
  273. package/src/api/layerUtils.ts +12 -8
  274. package/src/api/reportError.ts +2 -1
  275. package/src/api/routing/middleware/RouterMiddleware.ts +5 -4
  276. package/src/api/routing/middleware/middleware.ts +60 -15
  277. package/src/api/routing/middleware.ts +0 -2
  278. package/src/api/routing/schema/jwt.ts +2 -1
  279. package/src/api/routing/utils.ts +2 -1
  280. package/src/api/routing.ts +304 -131
  281. package/src/api/setupRequest.ts +31 -8
  282. package/src/arbs.ts +5 -3
  283. package/src/errorReporter.ts +65 -75
  284. package/src/fileUtil.ts +1 -1
  285. package/src/logger/jsonLogger.ts +3 -1
  286. package/src/logger/logFmtLogger.ts +1 -1
  287. package/src/logger/shared.ts +3 -2
  288. package/src/otel.ts +152 -0
  289. package/src/rateLimit.ts +34 -23
  290. package/src/test.ts +2 -2
  291. package/test/auth.test.ts +101 -0
  292. package/test/contextProvider.test.ts +14 -11
  293. package/test/controller.test.ts +25 -29
  294. package/test/dist/auth.test.d.ts.map +1 -0
  295. package/test/dist/contextProvider.test.d.ts.map +1 -1
  296. package/test/dist/controller.test.d.ts.map +1 -1
  297. package/test/dist/date-query.test.d.ts.map +1 -0
  298. package/test/dist/fixtures.d.ts +30 -12
  299. package/test/dist/fixtures.d.ts.map +1 -1
  300. package/test/dist/fixtures.js +17 -10
  301. package/test/dist/query.test.d.ts.map +1 -1
  302. package/test/dist/rawQuery.test.d.ts.map +1 -1
  303. package/test/dist/repository-ext.test.d.ts.map +1 -0
  304. package/test/dist/requires.test.d.ts.map +1 -1
  305. package/test/dist/router-generator.test.d.ts.map +1 -0
  306. package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
  307. package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
  308. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  309. package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
  310. package/test/dist/sql-store.test.d.ts.map +1 -0
  311. package/test/fixtures.ts +16 -9
  312. package/test/layerUtils.test.ts +1 -1
  313. package/test/query.test.ts +819 -38
  314. package/test/rawQuery.test.ts +312 -20
  315. package/test/repository-ext.test.ts +62 -0
  316. package/test/requires.test.ts +10 -5
  317. package/test/router-generator.test.ts +187 -0
  318. package/test/routing-interruptibility.test.ts +66 -0
  319. package/test/rpc-e2e-invalidation.test.ts +256 -0
  320. package/test/rpc-multi-middleware.test.ts +84 -9
  321. package/test/rpc-stream-fullstack.test.ts +304 -0
  322. package/test/sql-store.test.ts +1592 -0
  323. package/test/validateSample.test.ts +17 -12
  324. package/tsconfig.examples.json +1 -1
  325. package/tsconfig.json +0 -1
  326. package/tsconfig.json.bak +2 -2
  327. package/tsconfig.src.json +35 -35
  328. package/tsconfig.test.json +2 -2
  329. package/dist/Operations.d.ts +0 -55
  330. package/dist/Operations.d.ts.map +0 -1
  331. package/dist/Operations.js +0 -102
  332. package/dist/OperationsRepo.d.ts +0 -41
  333. package/dist/OperationsRepo.d.ts.map +0 -1
  334. package/dist/OperationsRepo.js +0 -14
  335. package/eslint.config.mjs +0 -24
  336. package/src/Operations.ts +0 -235
  337. 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 { Array, Effect, type NonEmptyReadonlyArray } from "effect-app"
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 { 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,20 @@ export function buildWhereCosmosQuery3(
40
43
  filter: readonly FilterResult[],
41
44
  name: string,
42
45
  defaultValues: Record<string, unknown>,
43
- select?: NonEmptyReadonlyArray<string | { key: string; subKeys: readonly string[] }>,
46
+ select?: NonEmptyReadonlyArray<
47
+ string | {
48
+ key: string
49
+ subKeys: readonly string[]
50
+ } | {
51
+ key: string
52
+ computed: ComputedProjectionIrExpression
53
+ }
54
+ >,
44
55
  order?: NonEmptyReadonlyArray<{ key: string; direction: "ASC" | "DESC" }>,
45
56
  skip?: number,
46
57
  limit?: number
47
58
  ) {
48
- const statement = (x: FilterR, i: number, values: any[]) => {
59
+ const statement = (x: FilterR, i: number) => {
49
60
  if (x.path === idKey) {
50
61
  x = { ...x, path: "id" }
51
62
  }
@@ -60,8 +71,6 @@ export function buildWhereCosmosQuery3(
60
71
 
61
72
  const v = "@v" + i
62
73
 
63
- const realValue = values[i]
64
-
65
74
  switch (x.op) {
66
75
  case "in":
67
76
  return `ARRAY_CONTAINS(${v}, ${k})`
@@ -74,14 +83,22 @@ export function buildWhereCosmosQuery3(
74
83
  return `(NOT ARRAY_CONTAINS(${k}, ${v}))`
75
84
 
76
85
  case "includes-any":
77
- return `ARRAY_CONTAINS_ANY(${k}, ${(realValue as any[]).map((_, i) => `${v}__${i}`).join(", ")})`
86
+ return `ARRAY_CONTAINS_ANY(${k}, ${
87
+ (x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
88
+ })`
78
89
  case "notIncludes-any":
79
- return `(NOT ARRAY_CONTAINS_ANY(${k}, ${(realValue as any[]).map((_, i) => `${v}__${i}`).join(", ")}))`
90
+ return `(NOT ARRAY_CONTAINS_ANY(${k}, ${
91
+ (x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
92
+ }))`
80
93
 
81
94
  case "includes-all":
82
- return `ARRAY_CONTAINS_ALL(${k}, ${(realValue as any[]).map((_, i) => `${v}__${i}`).join(", ")})`
95
+ return `ARRAY_CONTAINS_ALL(${k}, ${
96
+ (x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
97
+ })`
83
98
  case "notIncludes-all":
84
- return `(NOT ARRAY_CONTAINS_ALL(${k}, ${(realValue as any[]).map((_, i) => `${v}__${i}`).join(", ")}))`
99
+ return `(NOT ARRAY_CONTAINS_ALL(${k}, ${
100
+ (x.value as unknown as readonly unknown[]).map((_, i) => `${v}__${i}`).join(", ")
101
+ }))`
85
102
 
86
103
  case "contains":
87
104
  return `CONTAINS(${k}, ${v}, true)`
@@ -165,7 +182,7 @@ export function buildWhereCosmosQuery3(
165
182
  : _
166
183
  : _
167
184
 
168
- const print = (state: readonly FilterResult[], values: any[], isRelation: string | null, every: boolean) => {
185
+ const print = (state: readonly FilterResult[], isRelation: string | null, every: boolean) => {
169
186
  let s = ""
170
187
  let l = 0
171
188
  const printN = (n: number) => {
@@ -174,13 +191,13 @@ export function buildWhereCosmosQuery3(
174
191
  for (const e of state) {
175
192
  switch (e.t) {
176
193
  case "where":
177
- s += statement(e, i++, values)
194
+ s += statement(e, i++)
178
195
  break
179
196
  case "or":
180
- s += ` OR ${statement(e, i++, values)}`
197
+ s += ` OR ${statement(e, i++)}`
181
198
  break
182
199
  case "and":
183
- s += ` AND ${statement(e, i++, values)}`
200
+ s += ` AND ${statement(e, i++)}`
184
201
  break
185
202
  case "or-scope": {
186
203
  ++l
@@ -189,7 +206,7 @@ export function buildWhereCosmosQuery3(
189
206
  if (rel) {
190
207
  const rel = (e.result[0]! as { path: string }).path.split(".-1.")[0]
191
208
  s += isRelation
192
- ? ` OR (\n${printN(l + 1)}${print(e.result, values, rel, every)}\n${printN(l)})`
209
+ ? ` OR (\n${printN(l + 1)}${print(e.result, rel, every)}\n${printN(l)})`
193
210
  : ` OR (\n${printN(l + 1)}${
194
211
  every ? "NOT " : ""
195
212
  }EXISTS(SELECT VALUE ${rel} FROM ${rel} IN f.${rel} WHERE ${
@@ -197,13 +214,12 @@ export function buildWhereCosmosQuery3(
197
214
  e
198
215
  .result
199
216
  .map(flip(every)),
200
- values,
201
217
  rel,
202
218
  every
203
219
  )
204
220
  }))`
205
221
  } else {
206
- s += ` OR (\n${printN(l + 1)}${print(e.result, values, null, every)}\n${printN(l)})`
222
+ s += ` OR (\n${printN(l + 1)}${print(e.result, null, every)}\n${printN(l)})`
207
223
  }
208
224
  --l
209
225
  break
@@ -215,14 +231,14 @@ export function buildWhereCosmosQuery3(
215
231
  if (rel) {
216
232
  const rel = (e.result[0]! as { path: string }).path.split(".-1.")[0]
217
233
  s += isRelation
218
- ? ` AND (\n${printN(l + 1)}${print(e.result, values, rel, every)}\n${printN(l)})`
234
+ ? ` AND (\n${printN(l + 1)}${print(e.result, rel, every)}\n${printN(l)})`
219
235
  : ` AND (\n${printN(l + 1)}${
220
236
  every ? "NOT " : ""
221
237
  }EXISTS(SELECT VALUE ${rel} FROM ${rel} IN f.${rel} WHERE ${
222
- print(e.result.map(flip(every)), values, rel, every)
238
+ print(e.result.map(flip(every)), rel, every)
223
239
  }))`
224
240
  } else {
225
- s += ` AND (\n${printN(l + 1)}${print(e.result, values, null, every)}\n${printN(l)})`
241
+ s += ` AND (\n${printN(l + 1)}${print(e.result, null, every)}\n${printN(l)})`
226
242
  }
227
243
  --l
228
244
  break
@@ -234,12 +250,12 @@ export function buildWhereCosmosQuery3(
234
250
  if (rel) {
235
251
  const rel = (e.result[0]! as { path: string }).path.split(".-1.")[0]
236
252
  s += isRelation
237
- ? `(\n${printN(l + 1)}${print(e.result, values, rel, every)}\n${printN(l)})`
253
+ ? `(\n${printN(l + 1)}${print(e.result, rel, every)}\n${printN(l)})`
238
254
  : `(\n${printN(l + 1)}${every ? "NOT " : ""}EXISTS(SELECT VALUE ${rel} FROM ${rel} IN f.${rel} WHERE ${
239
- print(e.result.map(flip(every)), values, rel, every)
255
+ print(e.result.map(flip(every)), rel, every)
240
256
  }))`
241
257
  } else {
242
- s += `(\n${printN(l + 1)}${print(e.result, values, null, every)}\n${printN(l)})`
258
+ s += `(\n${printN(l + 1)}${print(e.result, null, every)}\n${printN(l)})`
243
259
  }
244
260
  // ;--l
245
261
  break
@@ -272,40 +288,123 @@ export function buildWhereCosmosQuery3(
272
288
  ? getValues(_.result)
273
289
  : [_]
274
290
  )
275
- const values = getValues(filter)
291
+ const computedFilters = select
292
+ ? select.flatMap((_) => typeof _ === "object" && "computed" in _ ? getValues(_.computed.filter) : [])
293
+ : []
294
+ const values = [...computedFilters, ...getValues(filter)]
295
+
296
+ const computedSelectExpr = (key: string, computed: ComputedProjectionIrExpression) => {
297
+ const relationPath = computed.path
298
+ const relationAlias = relationPath
299
+ const relationSource = dottedToAccess(`f.${relationPath}`)
300
+ const compileExpr = (expression: ComputedProjectionMathIrExpression): string => {
301
+ switch (expression._tag) {
302
+ case "field":
303
+ return dottedToAccess(`${relationAlias}.${expression.field}`)
304
+ case "mul":
305
+ return `(${compileExpr(expression.left)} * ${compileExpr(expression.right)})`
306
+ default:
307
+ return assertUnreachable(expression)
308
+ }
309
+ }
310
+ const factorExpr = (unitExpr: string, toBase: string, factors: Readonly<Record<string, number>>) => {
311
+ const entries = Object.entries(factors).filter(([, factor]) => Number.isFinite(factor))
312
+ return entries.reduceRight<string>(
313
+ (acc, [unit, factor]) => `IIF(${unitExpr} = ${JSON.stringify(unit)}, ${factor}, ${acc})`,
314
+ `IIF(${unitExpr} = ${JSON.stringify(toBase)}, 1, 0)`
315
+ )
316
+ }
317
+ const where = computed.filter.length > 0
318
+ ? ` WHERE ${print(computed.filter, relationPath, false)}`
319
+ : ""
320
+ switch (computed._tag) {
321
+ case "relation-count":
322
+ return `(SELECT VALUE COUNT(1) FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
323
+ case "relation-any":
324
+ return `EXISTS(SELECT VALUE ${relationAlias} FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
325
+ case "relation-every": {
326
+ // ∀x.P(x) ≡ ¬∃x.¬P(x). Cosmos has no NOT(...) on EXISTS subqueries directly,
327
+ // but we can flip via NOT EXISTS(... WHERE NOT (filter)).
328
+ if (computed.filter.length === 0) return `true AS ${key}`
329
+ return `NOT EXISTS(SELECT VALUE ${relationAlias} FROM ${relationAlias} IN ${relationSource} WHERE NOT (${
330
+ print(computed.filter, relationPath, false)
331
+ })) AS ${key}`
332
+ }
333
+ case "relation-distinct-count": {
334
+ const fieldRef = dottedToAccess(`${relationAlias}.${computed.field}`)
335
+ return `(SELECT VALUE COUNT(1) FROM (SELECT DISTINCT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where})) AS ${key}`
336
+ }
337
+ case "relation-sum": {
338
+ const fieldRef = dottedToAccess(`${relationAlias}.${computed.field}`)
339
+ return `(SELECT VALUE SUM(${fieldRef}) FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
340
+ }
341
+ case "relation-sum-expr": {
342
+ const expression = compileExpr(computed.expression)
343
+ return `(SELECT VALUE SUM(${expression}) FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
344
+ }
345
+ case "relation-sum-expr-by": {
346
+ const unitRef = dottedToAccess(`${relationAlias}.${computed.unit}`)
347
+ const expression = compileExpr(computed.expression)
348
+ return `ARRAY(SELECT VALUE { "unit": ${unitRef}, "total": SUM(${expression}) } FROM ${relationAlias} IN ${relationSource}${where} GROUP BY ${unitRef}) AS ${key}`
349
+ }
350
+ case "relation-sum-expr-normalized": {
351
+ const unitRef = dottedToAccess(`${relationAlias}.${computed.unit}`)
352
+ const expression = compileExpr(computed.expression)
353
+ const factor = factorExpr(unitRef, computed.toBase, computed.factors)
354
+ return `(SELECT VALUE SUM((${expression}) * (${factor})) FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
355
+ }
356
+ case "relation-collect": {
357
+ const fieldRef = dottedToAccess(`${relationAlias}.${computed.field}`)
358
+ if (computed.distinct) {
359
+ return `ARRAY(SELECT DISTINCT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
360
+ }
361
+ return `ARRAY(SELECT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where}) AS ${key}`
362
+ }
363
+ case "relation-collect-fields": {
364
+ const subqueries = computed.fields.map((field) => {
365
+ const fieldRef = dottedToAccess(`${relationAlias}.${field}`)
366
+ return computed.distinct
367
+ ? `ARRAY(SELECT DISTINCT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where})`
368
+ : `ARRAY(SELECT VALUE ${fieldRef} FROM ${relationAlias} IN ${relationSource}${where})`
369
+ })
370
+ const combined = computed.distinct
371
+ ? subqueries.reduce((acc, sq) => `SetUnion(${acc}, ${sq})`)
372
+ : subqueries.reduce((acc, sq) => `ARRAY_CONCAT(${acc}, ${sq})`)
373
+ return `${combined} AS ${key}`
374
+ }
375
+ }
376
+ }
276
377
  // with joins, you should use DISTINCT
277
378
  // or you can end up with duplicates
278
379
  return {
279
380
  query: `
280
381
  SELECT ${
281
382
  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(",")}
383
+ ? select
384
+ .map((s) =>
385
+ typeof s === "string"
386
+ ? dottedToAccess(s === idKey ? "f.id" : `f.${s}`) // x["y"} vs x.y, helps with reserved keywords like "value"
387
+ : "computed" in s
388
+ ? computedSelectExpr(s.key, s.computed)
389
+ : `ARRAY (SELECT ${s.subKeys.map((_) => dottedToAccess(`t.${_}`)).join(",")}
288
390
  FROM t in ${dottedToAccess(`f.${s.key}`)}) AS ${s.key}`
289
- )
290
- .join(", ")
291
- }`
391
+ )
392
+ .join(", ")
292
393
  : "f"
293
394
  }
294
395
  FROM ${name} f
295
396
 
296
- ${filter.length ? `WHERE (${print(filter, values.map((_) => _.value), null, false)})` : ""}
397
+ ${filter.length ? `WHERE (${print(filter, null, false)})` : ""}
297
398
  ${order ? `ORDER BY ${order.map((_) => `${dottedToAccess(`f.${_.key}`)} ${_.direction}`).join(", ")}` : ""}
298
399
  ${skip !== undefined || limit !== undefined ? `OFFSET ${skip ?? 0} LIMIT ${limit ?? 999999}` : ""}`,
299
- parameters: [
300
- ...values
301
- .flatMap((x, i) =>
302
- [{
303
- name: `@v${i}`,
304
- value: x.value as any
305
- }]
306
- // TODO: only for arrays that are used with _ANY or _ALL
307
- .concat(Array.isArray(x.value) ? x.value.map((_, i2) => ({ name: `@v${i}__${i2}`, value: _ as any })) : [])
308
- )
309
- ]
400
+ parameters: values
401
+ .flatMap((x, i) =>
402
+ [{
403
+ name: `@v${i}`,
404
+ value: x.value as any
405
+ }]
406
+ // TODO: only for arrays that are used with _ANY or _ALL
407
+ .concat(Array.isArray(x.value) ? x.value.map((_, i2) => ({ name: `@v${i}__${i2}`, value: _ as any })) : [])
408
+ )
310
409
  }
311
410
  }