@effect-app/infra 4.0.0-beta.24 → 4.0.0-beta.241

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 (342) hide show
  1. package/CHANGELOG.md +1818 -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 +21 -17
  9. package/dist/Emailer/fake.d.ts +1 -1
  10. package/dist/Emailer/fake.js +3 -3
  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 +10 -6
  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 +141 -59
  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 +5 -5
  55. package/dist/Model/query/dsl.d.ts +216 -18
  56. package/dist/Model/query/dsl.d.ts.map +1 -1
  57. package/dist/Model/query/dsl.js +240 -5
  58. package/dist/Model/query/new-kid-interpreter.d.ts +116 -8
  59. package/dist/Model/query/new-kid-interpreter.d.ts.map +1 -1
  60. package/dist/Model/query/new-kid-interpreter.js +177 -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 +12 -7
  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 +18 -4
  89. package/dist/Store/Cosmos/query.d.ts +13 -2
  90. package/dist/Store/Cosmos/query.d.ts.map +1 -1
  91. package/dist/Store/Cosmos/query.js +179 -41
  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 +327 -62
  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 +49 -0
  105. package/dist/Store/SQL/query.d.ts.map +1 -0
  106. package/dist/Store/SQL/query.js +527 -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 +39 -9
  117. package/dist/Store/service.d.ts.map +1 -1
  118. package/dist/Store/service.js +31 -7
  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 +6 -4
  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 +1 -1
  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 -9
  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 +18 -7
  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 +18 -11
  160. package/dist/api/internal/health.d.ts +1 -1
  161. package/dist/api/layerUtils.d.ts +15 -7
  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 +3 -4
  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 -38
  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 +13 -6
  188. package/dist/api/setupRequest.d.ts.map +1 -1
  189. package/dist/api/setupRequest.js +37 -11
  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 +2 -2
  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 +65 -57
  227. package/src/Emailer/fake.ts +2 -2
  228. package/src/Emailer/service.ts +13 -3
  229. package/src/MainFiberSet.ts +12 -10
  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 +266 -151
  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/filter/types.ts +4 -4
  241. package/src/Model/query/dsl.ts +456 -20
  242. package/src/Model/query/new-kid-interpreter.ts +281 -7
  243. package/src/Model.ts +1 -0
  244. package/src/QueueMaker/SQLQueue.ts +150 -153
  245. package/src/QueueMaker/errors.ts +3 -1
  246. package/src/QueueMaker/memQueue.ts +111 -105
  247. package/src/QueueMaker/sbqueue.ts +76 -88
  248. package/src/QueueMaker/service.ts +3 -1
  249. package/src/RequestContext.ts +15 -16
  250. package/src/RequestFiberSet.ts +12 -7
  251. package/src/Store/ContextMapContainer.ts +46 -3
  252. package/src/Store/Cosmos/query.ts +214 -50
  253. package/src/Store/Cosmos.ts +491 -350
  254. package/src/Store/Disk.ts +106 -66
  255. package/src/Store/Memory.ts +365 -91
  256. package/src/Store/SQL/Pg.ts +364 -0
  257. package/src/Store/SQL/query.ts +603 -0
  258. package/src/Store/SQL.ts +736 -0
  259. package/src/Store/codeFilter.ts +5 -2
  260. package/src/Store/index.ts +20 -3
  261. package/src/Store/service.ts +60 -11
  262. package/src/Store/utils.ts +25 -23
  263. package/src/adapters/SQL/Model.ts +42 -41
  264. package/src/adapters/ServiceBus.ts +131 -121
  265. package/src/adapters/cosmos-client.ts +5 -3
  266. package/src/adapters/index.ts +7 -0
  267. package/src/adapters/memQueue.ts +5 -4
  268. package/src/adapters/mongo-client.ts +4 -2
  269. package/src/adapters/redis-client.ts +6 -2
  270. package/src/api/ContextProvider.ts +19 -16
  271. package/src/api/internal/RequestContextMiddleware.ts +24 -6
  272. package/src/api/internal/auth.ts +248 -44
  273. package/src/api/internal/events.ts +21 -12
  274. package/src/api/layerUtils.ts +13 -9
  275. package/src/api/reportError.ts +2 -1
  276. package/src/api/routing/middleware/RouterMiddleware.ts +5 -4
  277. package/src/api/routing/middleware/middleware.ts +60 -15
  278. package/src/api/routing/middleware.ts +2 -4
  279. package/src/api/routing/schema/jwt.ts +2 -1
  280. package/src/api/routing/utils.ts +2 -1
  281. package/src/api/routing.ts +309 -139
  282. package/src/api/setupRequest.ts +63 -12
  283. package/src/arbs.ts +5 -3
  284. package/src/errorReporter.ts +65 -75
  285. package/src/fileUtil.ts +1 -1
  286. package/src/logger/jsonLogger.ts +3 -1
  287. package/src/logger/logFmtLogger.ts +1 -1
  288. package/src/logger/shared.ts +3 -2
  289. package/src/otel.ts +152 -0
  290. package/src/rateLimit.ts +34 -23
  291. package/src/test.ts +2 -2
  292. package/test/auth.test.ts +101 -0
  293. package/test/contextProvider.test.ts +14 -11
  294. package/test/controller.test.ts +25 -29
  295. package/test/cosmos-query.test.ts +159 -0
  296. package/test/dist/auth.test.d.ts.map +1 -0
  297. package/test/dist/contextProvider.test.d.ts.map +1 -1
  298. package/test/dist/controller.test.d.ts.map +1 -1
  299. package/test/dist/cosmos-query.test.d.ts.map +1 -0
  300. package/test/dist/date-query.test.d.ts.map +1 -0
  301. package/test/dist/fixtures.d.ts +30 -12
  302. package/test/dist/fixtures.d.ts.map +1 -1
  303. package/test/dist/fixtures.js +17 -10
  304. package/test/dist/query.test.d.ts.map +1 -1
  305. package/test/dist/rawQuery.test.d.ts.map +1 -1
  306. package/test/dist/repository-ext.test.d.ts.map +1 -0
  307. package/test/dist/requires.test.d.ts.map +1 -1
  308. package/test/dist/router-generator.test.d.ts.map +1 -0
  309. package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
  310. package/test/dist/rpc-context-map-streaming.test.d.ts.map +1 -0
  311. package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
  312. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  313. package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
  314. package/test/dist/sql-store.test.d.ts.map +1 -0
  315. package/test/fixtures.ts +16 -9
  316. package/test/layerUtils.test.ts +1 -1
  317. package/test/query.test.ts +901 -38
  318. package/test/rawQuery.test.ts +338 -20
  319. package/test/repository-ext.test.ts +62 -0
  320. package/test/requires.test.ts +10 -5
  321. package/test/router-generator.test.ts +187 -0
  322. package/test/routing-interruptibility.test.ts +66 -0
  323. package/test/rpc-context-map-streaming.test.ts +262 -0
  324. package/test/rpc-e2e-invalidation.test.ts +256 -0
  325. package/test/rpc-multi-middleware.test.ts +84 -9
  326. package/test/rpc-stream-fullstack.test.ts +304 -0
  327. package/test/sql-store.test.ts +1711 -0
  328. package/test/validateSample.test.ts +17 -12
  329. package/tsconfig.examples.json +1 -1
  330. package/tsconfig.json +2 -1
  331. package/tsconfig.json.bak +2 -2
  332. package/tsconfig.src.json +35 -35
  333. package/tsconfig.test.json +2 -2
  334. package/dist/Operations.d.ts +0 -55
  335. package/dist/Operations.d.ts.map +0 -1
  336. package/dist/Operations.js +0 -102
  337. package/dist/OperationsRepo.d.ts +0 -41
  338. package/dist/OperationsRepo.d.ts.map +0 -1
  339. package/dist/OperationsRepo.js +0 -14
  340. package/eslint.config.mjs +0 -24
  341. package/src/Operations.ts +0 -235
  342. package/src/OperationsRepo.ts +0 -16
@@ -1,13 +1,109 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
3
- import { Array, identity, Match, Option, pipe, S } from "effect-app"
3
+ import * as Array from "effect-app/Array"
4
4
  import { toNonEmptyArray } from "effect-app/Array"
5
+ import * as Option from "effect-app/Option"
6
+ import * as S from "effect-app/Schema"
5
7
  import { dropUndefinedT } from "effect-app/utils"
8
+ import { identity, pipe } from "effect/Function"
9
+ import * as Match from "effect/Match"
10
+ import * as SchemaAST from "effect/SchemaAST"
6
11
  import type { FilterResult } from "../filter/filterApi.js"
7
12
  import type { FieldValues } from "../filter/types.js"
8
13
  import type { FieldPath } from "../filter/types/path/eager.js"
9
14
  import { make, type Q, type QAll } from "../query/dsl.js"
10
15
 
16
+ export type AggregateIrExpression =
17
+ | { readonly _tag: "agg-count" }
18
+ | { readonly _tag: "agg-count-when"; readonly filter: readonly FilterResult[] }
19
+ | { readonly _tag: "agg-sum"; readonly field: string }
20
+ | { readonly _tag: "agg-min"; readonly field: string }
21
+ | { readonly _tag: "agg-max"; readonly field: string }
22
+
23
+ export type AggregateIrItem =
24
+ | AggregateIrExpression
25
+ | { readonly _tag: "agg-field"; readonly path: string }
26
+
27
+ export type ComputedProjectionMathIrExpression =
28
+ | {
29
+ readonly _tag: "field"
30
+ readonly field: string
31
+ }
32
+ | {
33
+ readonly _tag: "mul"
34
+ readonly left: ComputedProjectionMathIrExpression
35
+ readonly right: ComputedProjectionMathIrExpression
36
+ }
37
+
38
+ export type ComputedProjectionIrExpression =
39
+ | {
40
+ readonly _tag: "relation-count"
41
+ readonly path: string
42
+ readonly filter: readonly FilterResult[]
43
+ }
44
+ | {
45
+ readonly _tag: "relation-any"
46
+ readonly path: string
47
+ readonly filter: readonly FilterResult[]
48
+ }
49
+ | {
50
+ readonly _tag: "relation-every"
51
+ readonly path: string
52
+ readonly filter: readonly FilterResult[]
53
+ }
54
+ | {
55
+ readonly _tag: "relation-distinct-count"
56
+ readonly path: string
57
+ readonly field: string
58
+ readonly filter: readonly FilterResult[]
59
+ }
60
+ | {
61
+ readonly _tag: "relation-sum"
62
+ readonly path: string
63
+ readonly field: string
64
+ readonly filter: readonly FilterResult[]
65
+ }
66
+ | {
67
+ readonly _tag: "relation-sum-expr"
68
+ readonly path: string
69
+ readonly expression: ComputedProjectionMathIrExpression
70
+ readonly filter: readonly FilterResult[]
71
+ }
72
+ | {
73
+ readonly _tag: "relation-sum-expr-by"
74
+ readonly path: string
75
+ readonly expression: ComputedProjectionMathIrExpression
76
+ readonly unit: string
77
+ readonly filter: readonly FilterResult[]
78
+ }
79
+ | {
80
+ readonly _tag: "relation-sum-expr-normalized"
81
+ readonly path: string
82
+ readonly expression: ComputedProjectionMathIrExpression
83
+ readonly unit: string
84
+ readonly toBase: string
85
+ readonly factors: Readonly<Record<string, number>>
86
+ readonly filter: readonly FilterResult[]
87
+ }
88
+ | {
89
+ readonly _tag: "relation-collect"
90
+ readonly path: string
91
+ readonly field: string
92
+ readonly distinct: boolean
93
+ readonly filter: readonly FilterResult[]
94
+ }
95
+ | {
96
+ readonly _tag: "relation-collect-fields"
97
+ readonly path: string
98
+ readonly fields: readonly string[]
99
+ readonly distinct: boolean
100
+ readonly filter: readonly FilterResult[]
101
+ }
102
+ | {
103
+ readonly _tag: "relation-length"
104
+ readonly path: string
105
+ }
106
+
11
107
  type Result<TFieldValues extends FieldValues, A = TFieldValues, R = never> = {
12
108
  filter: FilterResult[]
13
109
  schema: S.Codec<A, TFieldValues, R> | undefined
@@ -15,7 +111,9 @@ type Result<TFieldValues extends FieldValues, A = TFieldValues, R = never> = {
15
111
  skip: number | undefined
16
112
  order: { key: FieldPath<TFieldValues>; direction: "ASC" | "DESC" }[]
17
113
  ttype: "one" | "many" | "count" | undefined
18
- mode: "collect" | "project" | "transform" | undefined
114
+ mode: "collect" | "project" | "transform" | "aggregate" | undefined
115
+ computed: Record<string, ComputedProjectionIrExpression> | undefined
116
+ aggregateMap: Record<string, AggregateIrItem> | undefined
19
117
  }
20
118
 
21
119
  const interpret = <
@@ -33,7 +131,9 @@ const interpret = <
33
131
  skip: undefined,
34
132
  order: [],
35
133
  ttype: undefined,
36
- mode: undefined
134
+ mode: undefined,
135
+ computed: undefined,
136
+ aggregateMap: undefined
37
137
  }
38
138
 
39
139
  const upd = (
@@ -46,6 +146,8 @@ const interpret = <
46
146
  if (v.ttype !== undefined) data.ttype = v.ttype
47
147
  if (v.schema !== undefined) data.schema = v.schema
48
148
  if (v.mode !== undefined) data.mode = v.mode
149
+ if (v.computed !== undefined) data.computed = v.computed
150
+ if (v.aggregateMap !== undefined) data.aggregateMap = v.aggregateMap
49
151
  }
50
152
 
51
153
  const applyPath = (path: string) => (_: FilterResult): FilterResult =>
@@ -135,8 +237,112 @@ const interpret = <
135
237
  },
136
238
  project: (v) => {
137
239
  upd(interpret(v.current))
240
+ if (v.mode === "aggregate" && v.aggregateMap) {
241
+ data.schema = v.schema
242
+ data.mode = "aggregate"
243
+ data.aggregateMap = Object.fromEntries(
244
+ Object.entries(v.aggregateMap).map(([key, expression]) => {
245
+ switch (expression._tag) {
246
+ case "agg-field":
247
+ return [key, { _tag: "agg-field" as const, path: expression.path }]
248
+ case "agg-count":
249
+ return [key, { _tag: "agg-count" as const }]
250
+ case "agg-count-when": {
251
+ const filter = interpret(expression.operation(make())).filter
252
+ return [key, { _tag: "agg-count-when" as const, filter }]
253
+ }
254
+ case "agg-sum":
255
+ return [key, { _tag: "agg-sum" as const, field: expression.field }]
256
+ case "agg-min":
257
+ return [key, { _tag: "agg-min" as const, field: expression.field }]
258
+ case "agg-max":
259
+ return [key, { _tag: "agg-max" as const, field: expression.field }]
260
+ }
261
+ })
262
+ )
263
+ return
264
+ }
265
+ if (v.computed && v.mode === "transform") {
266
+ throw new Error("Computed projections require mode 'project' or 'collect', not 'transform'")
267
+ }
138
268
  data.schema = v.schema
139
- data.mode = v.mode
269
+ data.mode = v.computed
270
+ ? v.mode === "collect" ? "collect" : "project"
271
+ : v.mode
272
+ data.computed = v.computed
273
+ ? Object.fromEntries(
274
+ Object.entries(v.computed).map(([key, expression]) => {
275
+ const e = expression
276
+ const op = "operation" in e ? e.operation : undefined
277
+ const filter = op ? interpret(op(make())).filter.map(applyPath(e.path)) : []
278
+ switch (e._tag) {
279
+ case "relation-count":
280
+ case "relation-any":
281
+ case "relation-every":
282
+ return [key, { _tag: e._tag, path: e.path, filter } as ComputedProjectionIrExpression]
283
+ case "relation-distinct-count":
284
+ case "relation-sum":
285
+ return [
286
+ key,
287
+ { _tag: e._tag, path: e.path, field: e.field, filter } as ComputedProjectionIrExpression
288
+ ]
289
+ case "relation-sum-expr":
290
+ return [
291
+ key,
292
+ { _tag: e._tag, path: e.path, expression: e.expression, filter } as ComputedProjectionIrExpression
293
+ ]
294
+ case "relation-sum-expr-by":
295
+ return [
296
+ key,
297
+ {
298
+ _tag: e._tag,
299
+ path: e.path,
300
+ expression: e.expression,
301
+ unit: e.unit,
302
+ filter
303
+ } as ComputedProjectionIrExpression
304
+ ]
305
+ case "relation-sum-expr-normalized":
306
+ return [
307
+ key,
308
+ {
309
+ _tag: e._tag,
310
+ path: e.path,
311
+ expression: e.expression,
312
+ unit: e.unit,
313
+ toBase: e.toBase,
314
+ factors: e.factors,
315
+ filter
316
+ } as ComputedProjectionIrExpression
317
+ ]
318
+ case "relation-collect":
319
+ return [
320
+ key,
321
+ {
322
+ _tag: e._tag,
323
+ path: e.path,
324
+ field: e.field,
325
+ distinct: e.distinct,
326
+ filter
327
+ } as ComputedProjectionIrExpression
328
+ ]
329
+ case "relation-collect-fields":
330
+ return [
331
+ key,
332
+ {
333
+ _tag: e._tag,
334
+ path: e.path,
335
+ fields: e.fields,
336
+ distinct: e.distinct,
337
+ filter
338
+ } as ComputedProjectionIrExpression
339
+ ]
340
+ case "relation-length":
341
+ return [key, { _tag: e._tag, path: e.path } as ComputedProjectionIrExpression]
342
+ }
343
+ })
344
+ )
345
+ : undefined
140
346
  }
141
347
  })
142
348
  )
@@ -157,15 +363,42 @@ export const toFilter = <
157
363
  R,
158
364
  TFieldValuesRefined extends TFieldValues = TFieldValues
159
365
  >(
160
- q: QAll<TFieldValues, TFieldValuesRefined, A, R>
366
+ q: QAll<TFieldValues, TFieldValuesRefined, A, R>,
367
+ baseSchema?: S.Schema<unknown>
161
368
  ) => {
162
369
  // TODO: Native interpreter for each db adapter, instead of the intermediate "new-kid" format
163
370
  const a = interpret(q)
371
+
372
+ // Aggregate mode: build select entirely from aggregateMap (no schema-driven field list)
373
+ if (a.mode === "aggregate" && a.aggregateMap) {
374
+ const aggSelect = Object.entries(a.aggregateMap).map(([key, item]) => {
375
+ if (item._tag === "agg-field") {
376
+ return { key, path: item.path }
377
+ }
378
+ return { key, aggregate: item }
379
+ })
380
+ return dropUndefinedT({
381
+ t: null as unknown as TFieldValues,
382
+ limit: a.limit,
383
+ skip: a.skip,
384
+ select: Option.getOrUndefined(toNonEmptyArray(aggSelect)) as any,
385
+ schema: a.schema,
386
+ computed: undefined,
387
+ order: Option.getOrUndefined(toNonEmptyArray(a.order)),
388
+ ttype: a.ttype,
389
+ mode: "aggregate" as const,
390
+ filter: a.filter.length ? a.filter : undefined
391
+ })
392
+ }
393
+
164
394
  const schema = a.schema
165
- let select: (keyof TFieldValues | { key: string; subKeys: string[] })[] = []
395
+ let select: (keyof TFieldValues | { key: string; subKeys: string[] } | {
396
+ key: string
397
+ computed: ComputedProjectionIrExpression
398
+ })[] = []
166
399
  // TODO: support more complex (nested) schemas?
167
400
  if (schema) {
168
- const t = walkTransformation(schema.ast)
401
+ const t = walkTransformation(SchemaAST.toEncoded(schema.ast))
169
402
  if (S.AST.isObjects(t)) {
170
403
  select = t.propertySignatures.map((_) => _.name as string)
171
404
  for (const prop of t.propertySignatures) {
@@ -194,12 +427,53 @@ export const toFilter = <
194
427
  }
195
428
  }
196
429
  }
430
+ const computed = a.computed
431
+ const getSelectKey = (_: (typeof select)[number]) => {
432
+ if (typeof _ === "string") {
433
+ return _
434
+ }
435
+ if (typeof _ === "object" && _ !== null && "key" in _) {
436
+ return _.key
437
+ }
438
+ return String(_)
439
+ }
440
+ const schemaKeys = select.map(getSelectKey)
441
+ const nonEncodedSchemaKeys = (() => {
442
+ if (!baseSchema) {
443
+ return [] as string[]
444
+ }
445
+ const encoded = walkTransformation(SchemaAST.toEncoded(baseSchema.ast))
446
+ if (!S.AST.isObjects(encoded)) {
447
+ return [] as string[]
448
+ }
449
+ const encodedKeys = encoded.propertySignatures.map((_) => _.name as string)
450
+ return schemaKeys.filter((key) => !encodedKeys.includes(key))
451
+ })()
452
+ const missingComputedKeys = nonEncodedSchemaKeys.filter((key) => !(computed && key in computed))
453
+
454
+ if (Array.isArrayNonEmpty(missingComputedKeys)) {
455
+ throw new Error(`Missing computed projections for schema keys: ${missingComputedKeys.join(", ")}`)
456
+ }
457
+
458
+ if (computed) {
459
+ const computedKeys = Object.keys(computed)
460
+ const extraComputedKeys = computedKeys.filter((key) => !schemaKeys.includes(key))
461
+ if (Array.isArrayNonEmpty(extraComputedKeys)) {
462
+ throw new Error(`Computed projection keys must exist in projection schema: ${extraComputedKeys.join(", ")}`)
463
+ }
464
+ select = select.filter((_) => {
465
+ const key = getSelectKey(_)
466
+ return !(key in computed)
467
+ })
468
+ select.push(...Object.entries(computed).map(([key, expression]) => ({ key, computed: expression })))
469
+ }
197
470
  return dropUndefinedT({
198
471
  t: null as unknown as TFieldValues,
199
472
  limit: a.limit,
200
473
  skip: a.skip,
201
474
  select: Option.getOrUndefined(toNonEmptyArray(select)),
202
475
  schema,
476
+ computed,
203
477
  order: Option.getOrUndefined(toNonEmptyArray(a.order)),
204
478
  ttype: a.ttype,
205
479
  mode: a.mode ?? "transform",
package/src/Model.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./Model/dsl.js"
2
2
  export * as Q from "./Model/query.js"
3
3
  export { makeRepo } from "./Model/Repository.js"
4
+ export { type RegisteredRepository, RepositoryRegistry, RepositoryRegistryLive } from "./Model/Repository.js"