@effect-app/infra 4.0.0-beta.98 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (486) hide show
  1. package/CHANGELOG.md +2891 -0
  2. package/_check.sh +1 -1
  3. package/dist/CUPS.d.ts +28 -9
  4. package/dist/CUPS.d.ts.map +1 -1
  5. package/dist/CUPS.js +35 -14
  6. package/dist/ClusterCosmos.d.ts +67 -0
  7. package/dist/ClusterCosmos.d.ts.map +1 -0
  8. package/dist/ClusterCosmos.js +588 -0
  9. package/dist/ClusterServiceBus.d.ts +67 -0
  10. package/dist/ClusterServiceBus.d.ts.map +1 -0
  11. package/dist/ClusterServiceBus.js +84 -0
  12. package/dist/{api/ContextProvider.d.ts → ContextProvider.d.ts} +7 -4
  13. package/dist/ContextProvider.d.ts.map +1 -0
  14. package/dist/ContextProvider.js +40 -0
  15. package/dist/Emailer/Sendgrid.d.ts +110 -146
  16. package/dist/Emailer/Sendgrid.d.ts.map +1 -1
  17. package/dist/Emailer/Sendgrid.js +24 -19
  18. package/dist/Emailer/fake.d.ts +1 -1
  19. package/dist/Emailer/fake.d.ts.map +1 -1
  20. package/dist/Emailer/fake.js +4 -4
  21. package/dist/MainFiberSet.d.ts +11 -7
  22. package/dist/MainFiberSet.d.ts.map +1 -1
  23. package/dist/MainFiberSet.js +22 -6
  24. package/dist/QueueMaker/errors.d.ts +3 -1
  25. package/dist/QueueMaker/errors.d.ts.map +1 -1
  26. package/dist/QueueMaker/errors.js +4 -2
  27. package/dist/{adapters/SQL → SQL}/Model.d.ts +34 -45
  28. package/dist/SQL/Model.d.ts.map +1 -0
  29. package/dist/SQL/Model.js +469 -0
  30. package/dist/SQL.d.ts.map +1 -0
  31. package/dist/{adapters/SQL.js → SQL.js} +1 -1
  32. package/dist/Store/Cosmos/query.d.ts +16 -4
  33. package/dist/Store/Cosmos/query.d.ts.map +1 -1
  34. package/dist/Store/Cosmos/query.js +238 -42
  35. package/dist/Store/Cosmos.d.ts +2 -2
  36. package/dist/Store/Cosmos.d.ts.map +1 -1
  37. package/dist/Store/Cosmos.js +394 -319
  38. package/dist/Store/Disk.d.ts +4 -4
  39. package/dist/Store/Disk.d.ts.map +1 -1
  40. package/dist/Store/Disk.js +91 -39
  41. package/dist/Store/Memory.d.ts +7 -10
  42. package/dist/Store/Memory.d.ts.map +1 -1
  43. package/dist/Store/Memory.js +348 -78
  44. package/dist/Store/SQL/Pg.d.ts +2 -2
  45. package/dist/Store/SQL/Pg.d.ts.map +1 -1
  46. package/dist/Store/SQL/Pg.js +229 -154
  47. package/dist/Store/SQL/query.d.ts +19 -3
  48. package/dist/Store/SQL/query.d.ts.map +1 -1
  49. package/dist/Store/SQL/query.js +306 -12
  50. package/dist/Store/SQL.d.ts +22 -5
  51. package/dist/Store/SQL.d.ts.map +1 -1
  52. package/dist/Store/SQL.js +369 -98
  53. package/dist/Store/codeFilter.d.ts +4 -4
  54. package/dist/Store/codeFilter.d.ts.map +1 -1
  55. package/dist/Store/codeFilter.js +71 -22
  56. package/dist/Store/index.d.ts +6 -4
  57. package/dist/Store/index.d.ts.map +1 -1
  58. package/dist/Store/index.js +9 -6
  59. package/dist/Store/jsonDocument.d.ts +67 -0
  60. package/dist/Store/jsonDocument.d.ts.map +1 -0
  61. package/dist/Store/jsonDocument.js +107 -0
  62. package/dist/Store/utils.d.ts +21 -2
  63. package/dist/Store/utils.d.ts.map +1 -1
  64. package/dist/Store/utils.js +253 -10
  65. package/dist/WorkflowEngineCosmos.d.ts +30 -0
  66. package/dist/WorkflowEngineCosmos.d.ts.map +1 -0
  67. package/dist/WorkflowEngineCosmos.js +542 -0
  68. package/dist/WorkflowEngineSqlite.d.ts +24 -0
  69. package/dist/WorkflowEngineSqlite.d.ts.map +1 -0
  70. package/dist/WorkflowEngineSqlite.js +550 -0
  71. package/dist/arbs.d.ts +6 -3
  72. package/dist/arbs.d.ts.map +1 -1
  73. package/dist/arbs.js +20 -4
  74. package/dist/codec.d.ts.map +1 -0
  75. package/dist/codec.js +5 -0
  76. package/dist/cosmos-client.d.ts +40 -0
  77. package/dist/cosmos-client.d.ts.map +1 -0
  78. package/dist/cosmos-client.js +41 -0
  79. package/dist/errorReporter.d.ts +6 -4
  80. package/dist/errorReporter.d.ts.map +1 -1
  81. package/dist/errorReporter.js +23 -27
  82. package/dist/fileUtil.d.ts +1 -1
  83. package/dist/fileUtil.d.ts.map +1 -1
  84. package/dist/fileUtil.js +2 -2
  85. package/dist/index.d.ts +2 -1
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +3 -2
  88. package/dist/internal/RequestContextMiddleware.d.ts +5 -0
  89. package/dist/internal/RequestContextMiddleware.d.ts.map +1 -0
  90. package/dist/internal/RequestContextMiddleware.js +45 -0
  91. package/dist/internal/auth.d.ts +53 -0
  92. package/dist/internal/auth.d.ts.map +1 -0
  93. package/dist/internal/auth.js +180 -0
  94. package/dist/internal/events.d.ts +11 -0
  95. package/dist/internal/events.d.ts.map +1 -0
  96. package/dist/internal/events.js +49 -0
  97. package/dist/{api/internal → internal}/health.d.ts +1 -1
  98. package/dist/internal/health.d.ts.map +1 -0
  99. package/dist/internal/health.js +5 -0
  100. package/dist/{api/layerUtils.d.ts → layerUtils.d.ts} +10 -2
  101. package/dist/layerUtils.d.ts.map +1 -0
  102. package/dist/layerUtils.js +17 -0
  103. package/dist/logger/jsonLogger.d.ts +1 -1
  104. package/dist/logger/jsonLogger.d.ts.map +1 -1
  105. package/dist/logger/jsonLogger.js +5 -3
  106. package/dist/logger/logFmtLogger.d.ts +1 -1
  107. package/dist/logger/logFmtLogger.d.ts.map +1 -1
  108. package/dist/logger/logFmtLogger.js +3 -3
  109. package/dist/logger/shared.d.ts +2 -2
  110. package/dist/logger/shared.d.ts.map +1 -1
  111. package/dist/logger/shared.js +6 -6
  112. package/dist/logger.d.ts.map +1 -1
  113. package/dist/middlewares.d.ts.map +1 -0
  114. package/dist/{api/middlewares.js → middlewares.js} +1 -1
  115. package/dist/{adapters/mongo-client.d.ts → mongo-client.d.ts} +2 -1
  116. package/dist/mongo-client.d.ts.map +1 -0
  117. package/dist/mongo-client.js +15 -0
  118. package/dist/otel.d.ts +75 -0
  119. package/dist/otel.d.ts.map +1 -0
  120. package/dist/otel.js +84 -0
  121. package/dist/rateLimit.d.ts +11 -3
  122. package/dist/rateLimit.d.ts.map +1 -1
  123. package/dist/rateLimit.js +7 -12
  124. package/dist/{adapters/redis-client.d.ts → redis-client.d.ts} +4 -1
  125. package/dist/redis-client.d.ts.map +1 -0
  126. package/dist/redis-client.js +98 -0
  127. package/dist/{api/reportError.d.ts → reportError.d.ts} +1 -1
  128. package/dist/reportError.d.ts.map +1 -0
  129. package/dist/reportError.js +28 -0
  130. package/dist/{api/routing → routing}/middleware/RouterMiddleware.d.ts +2 -1
  131. package/dist/routing/middleware/RouterMiddleware.d.ts.map +1 -0
  132. package/dist/{api/routing → routing}/middleware/RouterMiddleware.js +1 -1
  133. package/dist/{api/routing → routing}/middleware/middleware.d.ts +11 -6
  134. package/dist/routing/middleware/middleware.d.ts.map +1 -0
  135. package/dist/routing/middleware/middleware.js +152 -0
  136. package/dist/{api/routing → routing}/middleware.d.ts +0 -1
  137. package/dist/routing/middleware.d.ts.map +1 -0
  138. package/dist/{api/routing → routing}/middleware.js +1 -2
  139. package/dist/routing/schema/jwt.d.ts.map +1 -0
  140. package/dist/routing/schema/jwt.js +12 -0
  141. package/dist/routing/tsort.d.ts.map +1 -0
  142. package/dist/routing/tsort.js +51 -0
  143. package/dist/{api/routing → routing}/utils.d.ts +3 -3
  144. package/dist/routing/utils.d.ts.map +1 -0
  145. package/dist/routing/utils.js +45 -0
  146. package/dist/routing.d.ts +182 -0
  147. package/dist/routing.d.ts.map +1 -0
  148. package/dist/routing.js +256 -0
  149. package/dist/test.d.ts +2 -2
  150. package/dist/test.d.ts.map +1 -1
  151. package/dist/test.js +5 -5
  152. package/dist/util.d.ts.map +1 -0
  153. package/dist/util.js +14 -0
  154. package/docs/cluster-storage.md +26 -0
  155. package/docs/workflow-engine.md +262 -0
  156. package/examples/query.ts +23 -19
  157. package/package.json +36 -364
  158. package/src/CUPS.ts +53 -14
  159. package/src/ClusterCosmos.ts +1170 -0
  160. package/src/ClusterServiceBus.ts +244 -0
  161. package/src/{api/ContextProvider.ts → ContextProvider.ts} +10 -7
  162. package/src/Emailer/Sendgrid.ts +83 -60
  163. package/src/Emailer/fake.ts +4 -4
  164. package/src/MainFiberSet.ts +31 -12
  165. package/src/QueueMaker/errors.ts +3 -1
  166. package/src/{adapters/SQL → SQL}/Model.ts +48 -47
  167. package/src/SQL.ts +1 -0
  168. package/src/Store/Cosmos/query.ts +275 -55
  169. package/src/Store/Cosmos.ts +597 -515
  170. package/src/Store/Disk.ts +145 -71
  171. package/src/Store/Memory.ts +420 -115
  172. package/src/Store/SQL/Pg.ts +352 -268
  173. package/src/Store/SQL/query.ts +366 -20
  174. package/src/Store/SQL.ts +742 -293
  175. package/src/Store/codeFilter.ts +78 -28
  176. package/src/Store/index.ts +18 -13
  177. package/src/Store/jsonDocument.ts +143 -0
  178. package/src/Store/utils.ts +307 -30
  179. package/src/WorkflowEngineCosmos.ts +749 -0
  180. package/src/WorkflowEngineSqlite.ts +813 -0
  181. package/src/arbs.ts +25 -5
  182. package/src/cosmos-client.ts +72 -0
  183. package/src/errorReporter.ts +68 -78
  184. package/src/fileUtil.ts +1 -1
  185. package/src/index.ts +2 -1
  186. package/src/{api/internal → internal}/RequestContextMiddleware.ts +23 -6
  187. package/src/internal/auth.ts +272 -0
  188. package/src/{api/internal → internal}/events.ts +18 -9
  189. package/src/{api/layerUtils.ts → layerUtils.ts} +7 -3
  190. package/src/logger/jsonLogger.ts +5 -3
  191. package/src/logger/logFmtLogger.ts +3 -3
  192. package/src/logger/shared.ts +6 -5
  193. package/src/middlewares.ts +10 -0
  194. package/src/{adapters/mongo-client.ts → mongo-client.ts} +3 -1
  195. package/src/otel.ts +177 -0
  196. package/src/rateLimit.ts +35 -24
  197. package/src/{adapters/redis-client.ts → redis-client.ts} +6 -2
  198. package/src/{api/reportError.ts → reportError.ts} +3 -2
  199. package/src/{api/routing → routing}/middleware/RouterMiddleware.ts +2 -1
  200. package/src/{api/routing → routing}/middleware/middleware.ts +75 -50
  201. package/src/routing/middleware.ts +4 -0
  202. package/src/{api/routing → routing}/schema/jwt.ts +2 -2
  203. package/src/{api/routing → routing}/utils.ts +2 -1
  204. package/src/routing.ts +823 -0
  205. package/src/test.ts +6 -6
  206. package/src/vitest.ts +1 -1
  207. package/test/arbs-magnitude.test.ts +33 -0
  208. package/test/arbs.test.ts +41 -0
  209. package/test/auth.test.ts +101 -0
  210. package/test/cluster-cosmos.test.ts +634 -0
  211. package/test/cluster-servicebus.test.ts +180 -0
  212. package/test/cluster-sqlite.test.ts +207 -0
  213. package/test/contextProvider.test.ts +11 -8
  214. package/test/controller.test.ts +23 -28
  215. package/test/cosmos-container-throughput.test.ts +80 -0
  216. package/test/cosmos-query.test.ts +368 -0
  217. package/test/dist/arbs-magnitude.test.d.ts.map +1 -0
  218. package/test/dist/arbs.test.d.ts.map +1 -0
  219. package/test/dist/auth.test.d.ts.map +1 -0
  220. package/test/dist/cluster-cosmos.test.d.ts.map +1 -0
  221. package/test/dist/cluster-servicebus.test.d.ts.map +1 -0
  222. package/test/dist/cluster-sqlite.test.d.ts.map +1 -0
  223. package/test/dist/contextProvider.test.d.ts.map +1 -1
  224. package/test/dist/controller.test.d.ts.map +1 -1
  225. package/test/dist/cosmos-container-throughput.test.d.ts.map +1 -0
  226. package/test/dist/cosmos-query.test.d.ts.map +1 -0
  227. package/test/dist/fixtures.d.ts +17 -9
  228. package/test/dist/fixtures.d.ts.map +1 -1
  229. package/test/dist/fixtures.js +8 -3
  230. package/test/dist/json-lower.test.d.ts.map +1 -0
  231. package/test/dist/query.test.d.ts.map +1 -1
  232. package/test/dist/rawQuery.test.d.ts.map +1 -1
  233. package/test/dist/repository-ext.test.d.ts.map +1 -0
  234. package/test/dist/repository-legacy-document.test.d.ts.map +1 -0
  235. package/test/dist/requires.test.d.ts.map +1 -1
  236. package/test/dist/router-generator.test.d.ts.map +1 -0
  237. package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
  238. package/test/dist/rpc-context-map-streaming.test.d.ts.map +1 -0
  239. package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
  240. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  241. package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
  242. package/test/dist/workflow-engine-cosmos.test.d.ts.map +1 -0
  243. package/test/dist/workflow-engine-sqlite.test.d.ts.map +1 -0
  244. package/test/fixtures.ts +7 -2
  245. package/test/json-lower.test.ts +129 -0
  246. package/test/layerUtils.test.ts +2 -2
  247. package/test/query.test.ts +1232 -42
  248. package/test/rawQuery.test.ts +432 -7
  249. package/test/repository-ext.test.ts +456 -0
  250. package/test/repository-legacy-document.test.ts +394 -0
  251. package/test/requires.test.ts +7 -3
  252. package/test/router-generator.test.ts +187 -0
  253. package/test/routing-interruptibility.test.ts +66 -0
  254. package/test/rpc-context-map-streaming.test.ts +265 -0
  255. package/test/rpc-e2e-invalidation.test.ts +421 -0
  256. package/test/rpc-multi-middleware.test.ts +17 -11
  257. package/test/rpc-stream-fullstack.test.ts +307 -0
  258. package/test/sql-store.test.ts +1202 -47
  259. package/test/validateSample.test.ts +70 -42
  260. package/test/workflow-engine-cosmos.test.ts +345 -0
  261. package/test/workflow-engine-sqlite.test.ts +297 -0
  262. package/tsconfig.examples.json +1 -1
  263. package/tsconfig.json +9 -1
  264. package/tsconfig.src.json +35 -35
  265. package/tsconfig.test.json +2 -2
  266. package/dist/Emailer/service.d.ts +0 -55
  267. package/dist/Emailer/service.d.ts.map +0 -1
  268. package/dist/Emailer/service.js +0 -6
  269. package/dist/Emailer.d.ts +0 -2
  270. package/dist/Emailer.d.ts.map +0 -1
  271. package/dist/Emailer.js +0 -2
  272. package/dist/Model/Repository/ext.d.ts +0 -41
  273. package/dist/Model/Repository/ext.d.ts.map +0 -1
  274. package/dist/Model/Repository/ext.js +0 -65
  275. package/dist/Model/Repository/internal/internal.d.ts +0 -59
  276. package/dist/Model/Repository/internal/internal.d.ts.map +0 -1
  277. package/dist/Model/Repository/internal/internal.js +0 -320
  278. package/dist/Model/Repository/legacy.d.ts +0 -19
  279. package/dist/Model/Repository/legacy.d.ts.map +0 -1
  280. package/dist/Model/Repository/legacy.js +0 -2
  281. package/dist/Model/Repository/makeRepo.d.ts +0 -49
  282. package/dist/Model/Repository/makeRepo.d.ts.map +0 -1
  283. package/dist/Model/Repository/makeRepo.js +0 -24
  284. package/dist/Model/Repository/service.d.ts +0 -89
  285. package/dist/Model/Repository/service.d.ts.map +0 -1
  286. package/dist/Model/Repository/service.js +0 -2
  287. package/dist/Model/Repository/validation.d.ts +0 -43
  288. package/dist/Model/Repository/validation.d.ts.map +0 -1
  289. package/dist/Model/Repository/validation.js +0 -32
  290. package/dist/Model/Repository.d.ts +0 -6
  291. package/dist/Model/Repository.d.ts.map +0 -1
  292. package/dist/Model/Repository.js +0 -6
  293. package/dist/Model/dsl.d.ts +0 -32
  294. package/dist/Model/dsl.d.ts.map +0 -1
  295. package/dist/Model/dsl.js +0 -44
  296. package/dist/Model/filter/filterApi.d.ts +0 -30
  297. package/dist/Model/filter/filterApi.d.ts.map +0 -1
  298. package/dist/Model/filter/filterApi.js +0 -2
  299. package/dist/Model/filter/types/errors.d.ts +0 -29
  300. package/dist/Model/filter/types/errors.d.ts.map +0 -1
  301. package/dist/Model/filter/types/errors.js +0 -2
  302. package/dist/Model/filter/types/fields.d.ts +0 -15
  303. package/dist/Model/filter/types/fields.d.ts.map +0 -1
  304. package/dist/Model/filter/types/fields.js +0 -2
  305. package/dist/Model/filter/types/path/common.d.ts +0 -316
  306. package/dist/Model/filter/types/path/common.d.ts.map +0 -1
  307. package/dist/Model/filter/types/path/common.js +0 -2
  308. package/dist/Model/filter/types/path/eager.d.ts +0 -95
  309. package/dist/Model/filter/types/path/eager.d.ts.map +0 -1
  310. package/dist/Model/filter/types/path/eager.js +0 -31
  311. package/dist/Model/filter/types/path/index.d.ts +0 -4
  312. package/dist/Model/filter/types/path/index.d.ts.map +0 -1
  313. package/dist/Model/filter/types/path/index.js +0 -3
  314. package/dist/Model/filter/types/utils.d.ts +0 -79
  315. package/dist/Model/filter/types/utils.d.ts.map +0 -1
  316. package/dist/Model/filter/types/utils.js +0 -2
  317. package/dist/Model/filter/types/validator.d.ts +0 -30
  318. package/dist/Model/filter/types/validator.d.ts.map +0 -1
  319. package/dist/Model/filter/types/validator.js +0 -2
  320. package/dist/Model/filter/types.d.ts +0 -5
  321. package/dist/Model/filter/types.d.ts.map +0 -1
  322. package/dist/Model/filter/types.js +0 -7
  323. package/dist/Model/query/dsl.d.ts +0 -248
  324. package/dist/Model/query/dsl.d.ts.map +0 -1
  325. package/dist/Model/query/dsl.js +0 -104
  326. package/dist/Model/query/new-kid-interpreter.d.ts +0 -28
  327. package/dist/Model/query/new-kid-interpreter.d.ts.map +0 -1
  328. package/dist/Model/query/new-kid-interpreter.js +0 -165
  329. package/dist/Model/query.d.ts +0 -15
  330. package/dist/Model/query.d.ts.map +0 -1
  331. package/dist/Model/query.js +0 -3
  332. package/dist/Model.d.ts +0 -4
  333. package/dist/Model.d.ts.map +0 -1
  334. package/dist/Model.js +0 -4
  335. package/dist/Operations.d.ts +0 -55
  336. package/dist/Operations.d.ts.map +0 -1
  337. package/dist/Operations.js +0 -102
  338. package/dist/OperationsRepo.d.ts +0 -41
  339. package/dist/OperationsRepo.d.ts.map +0 -1
  340. package/dist/OperationsRepo.js +0 -14
  341. package/dist/QueueMaker/SQLQueue.d.ts +0 -14
  342. package/dist/QueueMaker/SQLQueue.d.ts.map +0 -1
  343. package/dist/QueueMaker/SQLQueue.js +0 -132
  344. package/dist/QueueMaker/memQueue.d.ts +0 -11
  345. package/dist/QueueMaker/memQueue.d.ts.map +0 -1
  346. package/dist/QueueMaker/memQueue.js +0 -76
  347. package/dist/QueueMaker/sbqueue.d.ts +0 -12
  348. package/dist/QueueMaker/sbqueue.d.ts.map +0 -1
  349. package/dist/QueueMaker/sbqueue.js +0 -91
  350. package/dist/QueueMaker/service.d.ts +0 -11
  351. package/dist/QueueMaker/service.d.ts.map +0 -1
  352. package/dist/QueueMaker/service.js +0 -4
  353. package/dist/RequestContext.d.ts +0 -68
  354. package/dist/RequestContext.d.ts.map +0 -1
  355. package/dist/RequestContext.js +0 -49
  356. package/dist/RequestFiberSet.d.ts +0 -36
  357. package/dist/RequestFiberSet.d.ts.map +0 -1
  358. package/dist/RequestFiberSet.js +0 -78
  359. package/dist/Store/ContextMapContainer.d.ts +0 -25
  360. package/dist/Store/ContextMapContainer.d.ts.map +0 -1
  361. package/dist/Store/ContextMapContainer.js +0 -77
  362. package/dist/Store/service.d.ts +0 -111
  363. package/dist/Store/service.d.ts.map +0 -1
  364. package/dist/Store/service.js +0 -79
  365. package/dist/Store.d.ts +0 -2
  366. package/dist/Store.d.ts.map +0 -1
  367. package/dist/Store.js +0 -2
  368. package/dist/adapters/SQL/Model.d.ts.map +0 -1
  369. package/dist/adapters/SQL/Model.js +0 -478
  370. package/dist/adapters/SQL.d.ts.map +0 -1
  371. package/dist/adapters/ServiceBus.d.ts +0 -58
  372. package/dist/adapters/ServiceBus.d.ts.map +0 -1
  373. package/dist/adapters/ServiceBus.js +0 -99
  374. package/dist/adapters/cosmos-client.d.ts +0 -14
  375. package/dist/adapters/cosmos-client.d.ts.map +0 -1
  376. package/dist/adapters/cosmos-client.js +0 -9
  377. package/dist/adapters/index.d.ts +0 -2
  378. package/dist/adapters/index.d.ts.map +0 -1
  379. package/dist/adapters/index.js +0 -2
  380. package/dist/adapters/logger.d.ts +0 -9
  381. package/dist/adapters/logger.d.ts.map +0 -1
  382. package/dist/adapters/logger.js +0 -3
  383. package/dist/adapters/memQueue.d.ts +0 -13
  384. package/dist/adapters/memQueue.d.ts.map +0 -1
  385. package/dist/adapters/memQueue.js +0 -20
  386. package/dist/adapters/mongo-client.d.ts.map +0 -1
  387. package/dist/adapters/mongo-client.js +0 -13
  388. package/dist/adapters/redis-client.d.ts.map +0 -1
  389. package/dist/adapters/redis-client.js +0 -94
  390. package/dist/api/ContextProvider.d.ts.map +0 -1
  391. package/dist/api/ContextProvider.js +0 -38
  392. package/dist/api/codec.d.ts.map +0 -1
  393. package/dist/api/codec.js +0 -5
  394. package/dist/api/internal/RequestContextMiddleware.d.ts +0 -5
  395. package/dist/api/internal/RequestContextMiddleware.d.ts.map +0 -1
  396. package/dist/api/internal/RequestContextMiddleware.js +0 -35
  397. package/dist/api/internal/auth.d.ts +0 -15
  398. package/dist/api/internal/auth.d.ts.map +0 -1
  399. package/dist/api/internal/auth.js +0 -47
  400. package/dist/api/internal/events.d.ts +0 -9
  401. package/dist/api/internal/events.d.ts.map +0 -1
  402. package/dist/api/internal/events.js +0 -42
  403. package/dist/api/internal/health.d.ts.map +0 -1
  404. package/dist/api/internal/health.js +0 -5
  405. package/dist/api/layerUtils.d.ts.map +0 -1
  406. package/dist/api/layerUtils.js +0 -16
  407. package/dist/api/middlewares.d.ts.map +0 -1
  408. package/dist/api/reportError.d.ts.map +0 -1
  409. package/dist/api/reportError.js +0 -27
  410. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +0 -1
  411. package/dist/api/routing/middleware/middleware.d.ts.map +0 -1
  412. package/dist/api/routing/middleware/middleware.js +0 -130
  413. package/dist/api/routing/middleware.d.ts.map +0 -1
  414. package/dist/api/routing/schema/jwt.d.ts.map +0 -1
  415. package/dist/api/routing/schema/jwt.js +0 -12
  416. package/dist/api/routing/tsort.d.ts.map +0 -1
  417. package/dist/api/routing/tsort.js +0 -51
  418. package/dist/api/routing/utils.d.ts.map +0 -1
  419. package/dist/api/routing/utils.js +0 -44
  420. package/dist/api/routing.d.ts +0 -134
  421. package/dist/api/routing.d.ts.map +0 -1
  422. package/dist/api/routing.js +0 -167
  423. package/dist/api/setupRequest.d.ts +0 -15
  424. package/dist/api/setupRequest.d.ts.map +0 -1
  425. package/dist/api/setupRequest.js +0 -49
  426. package/dist/api/util.d.ts.map +0 -1
  427. package/dist/api/util.js +0 -14
  428. package/eslint.config.mjs +0 -24
  429. package/src/Emailer/service.ts +0 -52
  430. package/src/Emailer.ts +0 -1
  431. package/src/Model/Repository/ext.ts +0 -283
  432. package/src/Model/Repository/internal/internal.ts +0 -580
  433. package/src/Model/Repository/legacy.ts +0 -27
  434. package/src/Model/Repository/makeRepo.ts +0 -139
  435. package/src/Model/Repository/service.ts +0 -627
  436. package/src/Model/Repository/validation.ts +0 -31
  437. package/src/Model/Repository.ts +0 -5
  438. package/src/Model/dsl.ts +0 -128
  439. package/src/Model/filter/filterApi.ts +0 -60
  440. package/src/Model/filter/types/errors.ts +0 -47
  441. package/src/Model/filter/types/fields.ts +0 -50
  442. package/src/Model/filter/types/path/common.ts +0 -404
  443. package/src/Model/filter/types/path/eager.ts +0 -298
  444. package/src/Model/filter/types/path/index.ts +0 -4
  445. package/src/Model/filter/types/utils.ts +0 -128
  446. package/src/Model/filter/types/validator.ts +0 -46
  447. package/src/Model/filter/types.ts +0 -6
  448. package/src/Model/query/dsl.ts +0 -2110
  449. package/src/Model/query/new-kid-interpreter.ts +0 -210
  450. package/src/Model/query.ts +0 -13
  451. package/src/Model.ts +0 -3
  452. package/src/Operations.ts +0 -235
  453. package/src/OperationsRepo.ts +0 -16
  454. package/src/QueueMaker/SQLQueue.ts +0 -190
  455. package/src/QueueMaker/memQueue.ts +0 -130
  456. package/src/QueueMaker/sbqueue.ts +0 -137
  457. package/src/QueueMaker/service.ts +0 -17
  458. package/src/RequestContext.ts +0 -63
  459. package/src/RequestFiberSet.ts +0 -105
  460. package/src/Store/ContextMapContainer.ts +0 -116
  461. package/src/Store/index.test.ts.bak +0 -112
  462. package/src/Store/service.ts +0 -193
  463. package/src/Store.ts +0 -1
  464. package/src/adapters/SQL.ts +0 -1
  465. package/src/adapters/ServiceBus.ts +0 -209
  466. package/src/adapters/cosmos-client.ts +0 -16
  467. package/src/adapters/index.ts +0 -0
  468. package/src/adapters/logger.ts +0 -3
  469. package/src/adapters/memQueue.ts +0 -21
  470. package/src/api/internal/auth.ts +0 -68
  471. package/src/api/middlewares.ts +0 -10
  472. package/src/api/routing/middleware.ts +0 -6
  473. package/src/api/routing.ts +0 -598
  474. package/src/api/setupRequest.ts +0 -104
  475. package/test/dist/date-query.test.d.ts.map +0 -1
  476. package/tsconfig.json.bak +0 -12
  477. /package/dist/{adapters/SQL.d.ts → SQL.d.ts} +0 -0
  478. /package/dist/{api/codec.d.ts → codec.d.ts} +0 -0
  479. /package/dist/{api/middlewares.d.ts → middlewares.d.ts} +0 -0
  480. /package/dist/{api/routing → routing}/schema/jwt.d.ts +0 -0
  481. /package/dist/{api/routing → routing}/tsort.d.ts +0 -0
  482. /package/dist/{api/util.d.ts → util.d.ts} +0 -0
  483. /package/src/{api/codec.ts → codec.ts} +0 -0
  484. /package/src/{api/internal → internal}/health.ts +0 -0
  485. /package/src/{api/routing → routing}/tsort.ts +0 -0
  486. /package/src/{api/util.ts → util.ts} +0 -0
@@ -1,9 +1,12 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { Effect, type NonEmptyReadonlyArray } from "effect-app"
2
+ import type { NonEmptyReadonlyArray } from "effect-app/Array"
3
+ import * as Effect from "effect-app/Effect"
4
+ import type { FilterR, FilterResult } from "effect-app/Model/filter/filterApi"
5
+ import type { AggregateIrExpression, ComputedProjectionIrExpression, ComputedProjectionMathIrExpression } from "effect-app/Model/query"
3
6
  import { assertUnreachable } from "effect-app/utils"
4
- import { InfraLogger } from "../../logger.js"
5
- import type { FilterR, FilterResult } from "../../Model/filter/filterApi.js"
6
- import { isRelationCheck } from "../codeFilter.js"
7
+ import { InfraLogger } from "../../logger.ts"
8
+ import { isRelationCheck } from "../codeFilter.ts"
9
+ import { jsonifyFilter, type JsonLower } from "../utils.ts"
7
10
 
8
11
  export interface SQLDialect {
9
12
  readonly jsonExtract: (path: string) => string
@@ -15,6 +18,9 @@ export interface SQLDialect {
15
18
  readonly jsonArrayNotContainsAny: (arrPath: string, valPlaceholders: readonly string[]) => string
16
19
  readonly jsonArrayContainsAll: (arrPath: string, valPlaceholders: readonly string[]) => string
17
20
  readonly jsonArrayNotContainsAll: (arrPath: string, valPlaceholders: readonly string[]) => string
21
+ readonly jsonMapHasKey: (arrPath: string, valPlaceholder: string) => string
22
+ readonly jsonMapHasValue: (arrPath: string, valPlaceholder: string) => string
23
+ readonly jsonMapHasPair: (arrPath: string, valPlaceholder: string) => string
18
24
  readonly caseInsensitiveLike: (expr: string, valPlaceholder: string) => string
19
25
  readonly caseInsensitiveNotLike: (expr: string, valPlaceholder: string) => string
20
26
  readonly jsonColumnType: "JSON" | "JSONB"
@@ -22,11 +28,13 @@ export interface SQLDialect {
22
28
  readonly jsonEachFrom: (arrPath: string, alias: string) => string
23
29
  readonly jsonExtractElement: (alias: string, subPath: string) => string
24
30
  readonly serializeJsonValue: (v: unknown) => unknown
31
+ readonly serializeScalar: (v: unknown) => unknown
25
32
  }
26
33
 
27
34
  export const sqliteDialect: SQLDialect = {
28
35
  jsonExtract: (path) => `json_extract(data, '$.${path}')`,
29
- jsonExtractJson: (path) => `json_quote(json_extract(data, '$.${path}'))`,
36
+ jsonExtractJson: (path) =>
37
+ `CASE json_type(data, '$.${path}') WHEN 'true' THEN 'true' WHEN 'false' THEN 'false' ELSE json_quote(json_extract(data, '$.${path}')) END`,
30
38
  placeholder: (_index) => "?",
31
39
  jsonArrayContains: (arrPath, val) => `EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE value = ${val})`,
32
40
  jsonArrayNotContains: (arrPath, val) =>
@@ -41,13 +49,21 @@ export const sqliteDialect: SQLDialect = {
41
49
  `NOT (${
42
50
  vals.map((v) => `EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE value = ${v})`).join(" AND ")
43
51
  })`,
52
+ jsonMapHasKey: (arrPath, val) =>
53
+ `EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE json_extract(value, '$[0]') = ${val})`,
54
+ jsonMapHasValue: (arrPath, val) =>
55
+ `EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE json_extract(value, '$[1]') = ${val})`,
56
+ jsonMapHasPair: (arrPath, val) => `EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE value = ${val})`,
44
57
  caseInsensitiveLike: (expr, val) => `LOWER(${expr}) LIKE LOWER(${val})`,
45
58
  caseInsensitiveNotLike: (expr, val) => `LOWER(${expr}) NOT LIKE LOWER(${val})`,
46
59
  jsonColumnType: "JSON",
47
60
  arrayLength: (path) => `json_array_length(data, '$.${path}')`,
48
61
  jsonEachFrom: (arrPath, alias) => `json_each(data, '$.${arrPath}') AS ${alias}`,
49
62
  jsonExtractElement: (alias, subPath) => `json_extract(${alias}.value, '$.${subPath}')`,
50
- serializeJsonValue: (v) => v
63
+ serializeJsonValue: (v) => v,
64
+ // SQLite stores JSON booleans as integers (0/1) and better-sqlite3 refuses
65
+ // to bind JS booleans, so coerce them to integers for WHERE params.
66
+ serializeScalar: (v) => typeof v === "boolean" ? (v ? 1 : 0) : v
51
67
  }
52
68
 
53
69
  export const pgDialect: SQLDialect = {
@@ -105,6 +121,27 @@ export const pgDialect: SQLDialect = {
105
121
  : `data${parts.map((p) => `->'${p}'`).join("")}`
106
122
  return `NOT (${vals.map((v) => `${jsonPath} @> ${v}::jsonb`).join(" AND ")})`
107
123
  },
124
+ jsonMapHasKey: (arrPath, val) => {
125
+ const parts = arrPath.split(".")
126
+ const jsonPath = parts.length === 1
127
+ ? `data->'${parts[0]}'`
128
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
129
+ return `EXISTS(SELECT 1 FROM jsonb_array_elements(${jsonPath}) e WHERE e->0 = ${val}::jsonb)`
130
+ },
131
+ jsonMapHasValue: (arrPath, val) => {
132
+ const parts = arrPath.split(".")
133
+ const jsonPath = parts.length === 1
134
+ ? `data->'${parts[0]}'`
135
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
136
+ return `EXISTS(SELECT 1 FROM jsonb_array_elements(${jsonPath}) e WHERE e->1 = ${val}::jsonb)`
137
+ },
138
+ jsonMapHasPair: (arrPath, val) => {
139
+ const parts = arrPath.split(".")
140
+ const jsonPath = parts.length === 1
141
+ ? `data->'${parts[0]}'`
142
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
143
+ return `${jsonPath} @> jsonb_build_array(${val}::jsonb)`
144
+ },
108
145
  caseInsensitiveLike: (expr, val) => `${expr} ILIKE ${val}`,
109
146
  caseInsensitiveNotLike: (expr, val) => `${expr} NOT ILIKE ${val}`,
110
147
  jsonColumnType: "JSONB",
@@ -122,7 +159,9 @@ export const pgDialect: SQLDialect = {
122
159
  const last = parts.pop()!
123
160
  return `${alias}${parts.map((p) => `->'${p}'`).join("")}->>'${last}'`
124
161
  },
125
- serializeJsonValue: (v) => JSON.stringify(v)
162
+ serializeJsonValue: (v) => JSON.stringify(v),
163
+ // PG's ->> operator yields text, so compare booleans as 'true'/'false' text.
164
+ serializeScalar: (v) => typeof v === "boolean" ? (v ? "true" : "false") : v
126
165
  }
127
166
 
128
167
  export function logQuery(q: { sql: string; params: unknown[] }) {
@@ -140,22 +179,51 @@ const dottedToJsonPath = (path: string) =>
140
179
  .filter((p) => p !== "-1")
141
180
  .join(".")
142
181
 
182
+ const mapItemParam = (dialect: SQLDialect, value: unknown) =>
183
+ dialect.jsonColumnType === "JSONB" ? dialect.serializeJsonValue(value) : value
184
+
185
+ const mapPairParam = (dialect: SQLDialect, value: unknown) => {
186
+ const encoded = dialect.serializeJsonValue(value)
187
+ return typeof encoded === "string" ? encoded : JSON.stringify(value)
188
+ }
189
+
190
+ const sqlStringLiteral = (value: string) => `'${value.replaceAll("'", "''")}'`
191
+
143
192
  export function buildWhereSQLQuery(
144
193
  dialect: SQLDialect,
145
194
  idKey: PropertyKey,
146
195
  filter: readonly FilterResult[],
147
196
  tableName: string,
148
197
  defaultValues: Record<string, unknown>,
149
- select?: NonEmptyReadonlyArray<string | { key: string; subKeys: readonly string[] }>,
198
+ select?: NonEmptyReadonlyArray<
199
+ string | {
200
+ key: string
201
+ subKeys: readonly string[]
202
+ } | {
203
+ key: string
204
+ computed: ComputedProjectionIrExpression
205
+ } | {
206
+ key: string
207
+ path: string
208
+ } | {
209
+ key: string
210
+ aggregate: AggregateIrExpression
211
+ }
212
+ >,
150
213
  order?: NonEmptyReadonlyArray<{ key: string; direction: "ASC" | "DESC" }>,
151
214
  skip?: number,
152
- limit?: number
215
+ limit?: number,
216
+ namespace?: string,
217
+ json?: JsonLower
153
218
  ) {
219
+ // defaultValues are already JSON-lowered at store construction; a second
220
+ // schema encode of an ISO Date string throws "Expected a valid Date".
221
+ filter = (json?.jsonifyFilter ?? jsonifyFilter)(filter)
154
222
  const params: unknown[] = []
155
223
  let paramIndex = 1
156
224
 
157
225
  const addParam = (value: unknown): string => {
158
- params.push(value)
226
+ params.push(dialect.serializeScalar(value))
159
227
  return dialect.placeholder(paramIndex++)
160
228
  }
161
229
 
@@ -188,7 +256,7 @@ export function buildWhereSQLQuery(
188
256
 
189
257
  switch (x.op) {
190
258
  case "in": {
191
- const vals = x.value as unknown as readonly unknown[]
259
+ const vals = x.value as readonly unknown[]
192
260
  const hasNull = vals.some((v) => v == null)
193
261
  const nonNullVals = vals.filter((v) => v != null)
194
262
  const parts: string[] = []
@@ -200,7 +268,7 @@ export function buildWhereSQLQuery(
200
268
  return parts.length > 1 ? `(${parts.join(" OR ")})` : parts[0] ?? "1=0"
201
269
  }
202
270
  case "notIn": {
203
- const vals = x.value as unknown as readonly unknown[]
271
+ const vals = x.value as readonly unknown[]
204
272
  const hasNull = vals.some((v) => v == null)
205
273
  const nonNullVals = vals.filter((v) => v != null)
206
274
  const parts: string[] = []
@@ -225,30 +293,133 @@ export function buildWhereSQLQuery(
225
293
 
226
294
  case "includes-any": {
227
295
  const arrPath = dottedToJsonPath(resolvedPath)
228
- const vals = x.value as unknown as readonly unknown[]
296
+ const vals = x.value as readonly unknown[]
229
297
  const placeholders = vals.map((v) => addParam(dialect.serializeJsonValue(v)))
230
298
  return dialect.jsonArrayContainsAny(arrPath, placeholders)
231
299
  }
232
300
  case "notIncludes-any": {
233
301
  const arrPath = dottedToJsonPath(resolvedPath)
234
- const vals = x.value as unknown as readonly unknown[]
302
+ const vals = x.value as readonly unknown[]
235
303
  const placeholders = vals.map((v) => addParam(dialect.serializeJsonValue(v)))
236
304
  return dialect.jsonArrayNotContainsAny(arrPath, placeholders)
237
305
  }
238
306
 
239
307
  case "includes-all": {
240
308
  const arrPath = dottedToJsonPath(resolvedPath)
241
- const vals = x.value as unknown as readonly unknown[]
309
+ const vals = x.value as readonly unknown[]
242
310
  const placeholders = vals.map((v) => addParam(dialect.serializeJsonValue(v)))
243
311
  return dialect.jsonArrayContainsAll(arrPath, placeholders)
244
312
  }
245
313
  case "notIncludes-all": {
246
314
  const arrPath = dottedToJsonPath(resolvedPath)
247
- const vals = x.value as unknown as readonly unknown[]
315
+ const vals = x.value as readonly unknown[]
248
316
  const placeholders = vals.map((v) => addParam(dialect.serializeJsonValue(v)))
249
317
  return dialect.jsonArrayNotContainsAll(arrPath, placeholders)
250
318
  }
251
319
 
320
+ case "hasKey": {
321
+ const arrPath = dottedToJsonPath(resolvedPath)
322
+ const v = addParam(mapItemParam(dialect, x.value))
323
+ return dialect.jsonMapHasKey(arrPath, v)
324
+ }
325
+ case "notHasKey": {
326
+ const arrPath = dottedToJsonPath(resolvedPath)
327
+ const v = addParam(mapItemParam(dialect, x.value))
328
+ return `NOT (${dialect.jsonMapHasKey(arrPath, v)})`
329
+ }
330
+ case "hasValue": {
331
+ const arrPath = dottedToJsonPath(resolvedPath)
332
+ const v = addParam(mapItemParam(dialect, x.value))
333
+ return dialect.jsonMapHasValue(arrPath, v)
334
+ }
335
+ case "notHasValue": {
336
+ const arrPath = dottedToJsonPath(resolvedPath)
337
+ const v = addParam(mapItemParam(dialect, x.value))
338
+ return `NOT (${dialect.jsonMapHasValue(arrPath, v)})`
339
+ }
340
+ case "hasKeyValue": {
341
+ const arrPath = dottedToJsonPath(resolvedPath)
342
+ const v = addParam(mapPairParam(dialect, x.value))
343
+ return dialect.jsonMapHasPair(arrPath, v)
344
+ }
345
+ case "notHasKeyValue": {
346
+ const arrPath = dottedToJsonPath(resolvedPath)
347
+ const v = addParam(mapPairParam(dialect, x.value))
348
+ return `NOT (${dialect.jsonMapHasPair(arrPath, v)})`
349
+ }
350
+ case "hasKey-any": {
351
+ const arrPath = dottedToJsonPath(resolvedPath)
352
+ const vals = x.value as readonly unknown[]
353
+ const parts = vals.map((val) => dialect.jsonMapHasKey(arrPath, addParam(mapItemParam(dialect, val))))
354
+ return `(${parts.join(" OR ")})`
355
+ }
356
+ case "notHasKey-any": {
357
+ const arrPath = dottedToJsonPath(resolvedPath)
358
+ const vals = x.value as readonly unknown[]
359
+ const parts = vals.map((val) => dialect.jsonMapHasKey(arrPath, addParam(mapItemParam(dialect, val))))
360
+ return `NOT (${parts.join(" OR ")})`
361
+ }
362
+ case "hasKey-all": {
363
+ const arrPath = dottedToJsonPath(resolvedPath)
364
+ const vals = x.value as readonly unknown[]
365
+ return vals.map((val) => dialect.jsonMapHasKey(arrPath, addParam(mapItemParam(dialect, val)))).join(" AND ")
366
+ }
367
+ case "notHasKey-all": {
368
+ const arrPath = dottedToJsonPath(resolvedPath)
369
+ const vals = x.value as readonly unknown[]
370
+ return `NOT (${
371
+ vals.map((val) => dialect.jsonMapHasKey(arrPath, addParam(mapItemParam(dialect, val)))).join(" AND ")
372
+ })`
373
+ }
374
+ case "hasValue-any": {
375
+ const arrPath = dottedToJsonPath(resolvedPath)
376
+ const vals = x.value as readonly unknown[]
377
+ const parts = vals.map((val) => dialect.jsonMapHasValue(arrPath, addParam(mapItemParam(dialect, val))))
378
+ return `(${parts.join(" OR ")})`
379
+ }
380
+ case "notHasValue-any": {
381
+ const arrPath = dottedToJsonPath(resolvedPath)
382
+ const vals = x.value as readonly unknown[]
383
+ const parts = vals.map((val) => dialect.jsonMapHasValue(arrPath, addParam(mapItemParam(dialect, val))))
384
+ return `NOT (${parts.join(" OR ")})`
385
+ }
386
+ case "hasValue-all": {
387
+ const arrPath = dottedToJsonPath(resolvedPath)
388
+ const vals = x.value as readonly unknown[]
389
+ return vals.map((val) => dialect.jsonMapHasValue(arrPath, addParam(mapItemParam(dialect, val)))).join(" AND ")
390
+ }
391
+ case "notHasValue-all": {
392
+ const arrPath = dottedToJsonPath(resolvedPath)
393
+ const vals = x.value as readonly unknown[]
394
+ return `NOT (${
395
+ vals.map((val) => dialect.jsonMapHasValue(arrPath, addParam(mapItemParam(dialect, val)))).join(" AND ")
396
+ })`
397
+ }
398
+ case "hasKeyValue-any": {
399
+ const arrPath = dottedToJsonPath(resolvedPath)
400
+ const vals = x.value as readonly unknown[]
401
+ const parts = vals.map((val) => dialect.jsonMapHasPair(arrPath, addParam(mapPairParam(dialect, val))))
402
+ return `(${parts.join(" OR ")})`
403
+ }
404
+ case "notHasKeyValue-any": {
405
+ const arrPath = dottedToJsonPath(resolvedPath)
406
+ const vals = x.value as readonly unknown[]
407
+ const parts = vals.map((val) => dialect.jsonMapHasPair(arrPath, addParam(mapPairParam(dialect, val))))
408
+ return `NOT (${parts.join(" OR ")})`
409
+ }
410
+ case "hasKeyValue-all": {
411
+ const arrPath = dottedToJsonPath(resolvedPath)
412
+ const vals = x.value as readonly unknown[]
413
+ return vals.map((val) => dialect.jsonMapHasPair(arrPath, addParam(mapPairParam(dialect, val)))).join(" AND ")
414
+ }
415
+ case "notHasKeyValue-all": {
416
+ const arrPath = dottedToJsonPath(resolvedPath)
417
+ const vals = x.value as readonly unknown[]
418
+ return `NOT (${
419
+ vals.map((val) => dialect.jsonMapHasPair(arrPath, addParam(mapPairParam(dialect, val)))).join(" AND ")
420
+ })`
421
+ }
422
+
252
423
  case "contains": {
253
424
  const v = addParam(`%${x.value}%`)
254
425
  return dialect.caseInsensitiveLike(k, v)
@@ -371,6 +542,136 @@ export function buildWhereSQLQuery(
371
542
  return s
372
543
  }
373
544
 
545
+ const computedSelectExpr = (key: string, computed: ComputedProjectionIrExpression): string => {
546
+ const relationPath = dottedToJsonPath(computed.path)
547
+ const relationAlias = `_${computed.path}`
548
+ const relationFrom = dialect.jsonEachFrom(relationPath, relationAlias)
549
+ const toNumber = (expr: string) =>
550
+ dialect.jsonColumnType === "JSON" ? `CAST(${expr} AS REAL)` : `(${expr})::numeric`
551
+ const compileExpr = (expression: ComputedProjectionMathIrExpression): string => {
552
+ switch (expression._tag) {
553
+ case "field":
554
+ return toNumber(dialect.jsonExtractElement(relationAlias, expression.field))
555
+ case "mul":
556
+ return `(${compileExpr(expression.left)} * ${compileExpr(expression.right)})`
557
+ default:
558
+ return assertUnreachable(expression)
559
+ }
560
+ }
561
+ const factorCaseExpr = (unitExpr: string, toBase: string, factors: Readonly<Record<string, number>>) => {
562
+ const entries = Object.entries(factors).filter(([, factor]) => Number.isFinite(factor))
563
+ const cases = entries.map(([unit, factor]) => ` WHEN ${sqlStringLiteral(unit)} THEN ${factor}`).join("")
564
+ return `CASE ${unitExpr} WHEN ${sqlStringLiteral(toBase)} THEN 1${cases} ELSE NULL END`
565
+ }
566
+ const filter = "filter" in computed ? computed.filter : []
567
+ const whereClause = () =>
568
+ filter.length > 0
569
+ ? ` WHERE ${print(filter, computed.path, false)}`
570
+ : ""
571
+ const boolExpr = (sqlExpr: string) =>
572
+ dialect.jsonColumnType === "JSON"
573
+ ? `CASE WHEN ${sqlExpr} THEN 'true' ELSE 'false' END AS "${key}"`
574
+ : `${sqlExpr} AS "${key}"`
575
+ switch (computed._tag) {
576
+ case "relation-count":
577
+ return `(SELECT COUNT(1) FROM ${relationFrom}${whereClause()}) AS "${key}"`
578
+ case "relation-any":
579
+ return boolExpr(`EXISTS(SELECT 1 FROM ${relationFrom}${whereClause()})`)
580
+ case "relation-every":
581
+ // ∀x.P(x) ≡ ¬∃x.¬P(x). When no filter, no element exists that violates ⊤ → true.
582
+ return boolExpr(
583
+ filter.length === 0
584
+ ? `1=1`
585
+ : `NOT EXISTS(SELECT 1 FROM ${relationFrom} WHERE NOT (${print(filter, computed.path, false)}))`
586
+ )
587
+ case "relation-distinct-count": {
588
+ const fieldExtract = dialect.jsonExtractElement(relationAlias, computed.field)
589
+ return `(SELECT COUNT(DISTINCT ${fieldExtract}) FROM ${relationFrom}${whereClause()}) AS "${key}"`
590
+ }
591
+ case "relation-sum": {
592
+ const fieldExtract = dialect.jsonExtractElement(relationAlias, computed.field)
593
+ return `(SELECT COALESCE(SUM(${toNumber(fieldExtract)}), 0) FROM ${relationFrom}${whereClause()}) AS "${key}"`
594
+ }
595
+ case "relation-sum-expr": {
596
+ const expression = compileExpr(computed.expression)
597
+ return `(SELECT COALESCE(SUM(${expression}), 0) FROM ${relationFrom}${whereClause()}) AS "${key}"`
598
+ }
599
+ case "relation-sum-expr-by": {
600
+ const expression = compileExpr(computed.expression)
601
+ const unitExpr = dialect.jsonExtractElement(relationAlias, computed.unit)
602
+ if (dialect.jsonColumnType === "JSON") {
603
+ return `(SELECT COALESCE(json_group_array(json_object('unit', __unit, 'total', __total)), json_array()) FROM (SELECT ${unitExpr} AS __unit, COALESCE(SUM(${expression}), 0) AS __total FROM ${relationFrom}${whereClause()} GROUP BY ${unitExpr})) AS "${key}"`
604
+ }
605
+ return `(SELECT COALESCE(jsonb_agg(jsonb_build_object('unit', __unit, 'total', __total)), '[]'::jsonb) FROM (SELECT ${unitExpr} AS __unit, COALESCE(SUM(${expression}), 0) AS __total FROM ${relationFrom}${whereClause()} GROUP BY ${unitExpr}) __grouped) AS "${key}"`
606
+ }
607
+ case "relation-sum-expr-normalized": {
608
+ const expression = compileExpr(computed.expression)
609
+ const unitExpr = dialect.jsonExtractElement(relationAlias, computed.unit)
610
+ const factorExpr = factorCaseExpr(unitExpr, computed.toBase, computed.factors)
611
+ return `(SELECT COALESCE(SUM((${expression}) * (${factorExpr})), 0) FROM ${relationFrom}${whereClause()}) AS "${key}"`
612
+ }
613
+ case "relation-collect": {
614
+ const fieldExtract = dialect.jsonExtractElement(relationAlias, computed.field)
615
+ if (dialect.jsonColumnType === "JSON") {
616
+ // sqlite: json_group_array does not accept DISTINCT; emulate via inner DISTINCT subquery
617
+ if (computed.distinct) {
618
+ return `(SELECT COALESCE(json_group_array(__v), json_array()) FROM (SELECT DISTINCT ${fieldExtract} AS __v FROM ${relationFrom}${whereClause()})) AS "${key}"`
619
+ }
620
+ return `(SELECT COALESCE(json_group_array(${fieldExtract}), json_array()) FROM ${relationFrom}${whereClause()}) AS "${key}"`
621
+ }
622
+ const aggArg = computed.distinct ? `DISTINCT ${fieldExtract}` : fieldExtract
623
+ return `(SELECT COALESCE(jsonb_agg(${aggArg}), '[]'::jsonb) FROM ${relationFrom}${whereClause()}) AS "${key}"`
624
+ }
625
+ case "relation-length": {
626
+ const arrPath = dottedToJsonPath(computed.path)
627
+ return `${dialect.arrayLength(arrPath)} AS "${key}"`
628
+ }
629
+ case "relation-collect-fields": {
630
+ const branches = computed.fields.map((field) => {
631
+ const fieldExtract = dialect.jsonExtractElement(relationAlias, field)
632
+ return `SELECT ${fieldExtract} AS __v FROM ${relationFrom}${whereClause()}`
633
+ })
634
+ const unionQuery = branches.join(" UNION ALL ")
635
+ if (dialect.jsonColumnType === "JSON") {
636
+ if (computed.distinct) {
637
+ return `(SELECT COALESCE(json_group_array(__v), json_array()) FROM (SELECT DISTINCT __v FROM (${unionQuery}))) AS "${key}"`
638
+ }
639
+ return `(SELECT COALESCE(json_group_array(__v), json_array()) FROM (${unionQuery})) AS "${key}"`
640
+ }
641
+ if (computed.distinct) {
642
+ return `(SELECT COALESCE(jsonb_agg(__v), '[]'::jsonb) FROM (SELECT DISTINCT __v FROM (${unionQuery}) inner_q) outer_q) AS "${key}"`
643
+ }
644
+ return `(SELECT COALESCE(jsonb_agg(__v), '[]'::jsonb) FROM (${unionQuery}) t) AS "${key}"`
645
+ }
646
+ default:
647
+ return assertUnreachable(computed)
648
+ }
649
+ }
650
+
651
+ const aggregateSelectExpr = (key: string, agg: AggregateIrExpression): string => {
652
+ switch (agg._tag) {
653
+ case "agg-count":
654
+ return `COUNT(1) AS "${key}"`
655
+ case "agg-count-when": {
656
+ if (agg.filter.length === 0) return `COUNT(1) AS "${key}"`
657
+ const cond = print([{ t: "where-scope", result: agg.filter, relation: "some" }], null, false)
658
+ return `COUNT(CASE WHEN ${cond} THEN 1 END) AS "${key}"`
659
+ }
660
+ case "agg-sum":
661
+ return `COALESCE(SUM(${fieldExpr(agg.field)}), 0) AS "${key}"`
662
+ case "agg-min":
663
+ return `MIN(${fieldExpr(agg.field)}) AS "${key}"`
664
+ case "agg-max":
665
+ return `MAX(${fieldExpr(agg.field)}) AS "${key}"`
666
+ default:
667
+ return assertUnreachable(agg)
668
+ }
669
+ }
670
+
671
+ const hasAggregates = select
672
+ ? select.some((s) => typeof s === "object" && s !== null && "aggregate" in s)
673
+ : false
674
+
374
675
  const getSelectExpr = (): string => {
375
676
  if (!select) return "id, _etag, data"
376
677
  const fields = select.map((s) => {
@@ -379,24 +680,69 @@ export function buildWhereSQLQuery(
379
680
  if (s === "_etag") return `_etag`
380
681
  return `${dialect.jsonExtractJson(s)} AS "${s}"`
381
682
  }
683
+ if ("computed" in s) {
684
+ return computedSelectExpr(s.key, s.computed)
685
+ }
686
+ if ("aggregate" in s) {
687
+ return aggregateSelectExpr(s.key, s.aggregate)
688
+ }
689
+ if ("path" in s) {
690
+ // Group-by fields: extract as scalar (not JSON-encoded) so grouping works and values compare as plain strings/numbers
691
+ return `${fieldExpr(dottedToJsonPath(s.path))} AS "${s.key}"`
692
+ }
382
693
  return `${dialect.jsonExtractJson(s.key)} AS "${s.key}"`
383
694
  })
384
695
  return fields.join(", ")
385
696
  }
386
697
 
387
- const whereClause = filter.length
388
- ? `WHERE ${print([{ t: "where-scope", result: filter, relation: "some" }], null, false)}`
698
+ // Order matters: projection params must be emitted BEFORE user-filter
699
+ // params so positional `?` placeholders in SQLite match `params[]` order.
700
+ const selectExpr = getSelectExpr()
701
+
702
+ const namespaceClause = namespace !== undefined
703
+ ? `_namespace = ${addParam(namespace)}`
704
+ : ""
705
+ const userWhere = filter.length
706
+ ? print([{ t: "where-scope", result: filter, relation: "some" }], null, false)
707
+ : ""
708
+ const whereClause = namespaceClause && userWhere
709
+ ? `WHERE ${namespaceClause} AND ${userWhere}`
710
+ : namespaceClause
711
+ ? `WHERE ${namespaceClause}`
712
+ : userWhere
713
+ ? `WHERE ${userWhere}`
714
+ : ""
715
+
716
+ const groupByClause = hasAggregates && select
717
+ ? (() => {
718
+ const groupByExprs = select
719
+ .filter((s): s is string | { key: string; path: string } =>
720
+ typeof s === "string" || (typeof s === "object" && s !== null && "path" in s)
721
+ )
722
+ .map((s) => typeof s === "string" ? fieldExpr(s) : fieldExpr(dottedToJsonPath(s.path)))
723
+ return groupByExprs.length > 0 ? `GROUP BY ${groupByExprs.join(", ")}` : ""
724
+ })()
389
725
  : ""
390
726
 
391
727
  const orderClause = order
392
- ? `ORDER BY ${order.map((_) => `${fieldExpr(_.key)} ${_.direction}`).join(", ")}`
728
+ ? `ORDER BY ${
729
+ order
730
+ .map((_) =>
731
+ hasAggregates
732
+ ? `"${_.key}" ${_.direction}`
733
+ : `${fieldExpr(_.key)} ${_.direction}`
734
+ )
735
+ .join(", ")
736
+ }`
393
737
  : ""
394
738
 
395
739
  const limitClause = limit !== undefined || skip !== undefined
396
740
  ? `LIMIT ${addParam(limit ?? 999999)} OFFSET ${addParam(skip ?? 0)}`
397
741
  : ""
398
742
 
399
- const sql = `SELECT ${getSelectExpr()} FROM "${tableName}" ${whereClause} ${orderClause} ${limitClause}`.trim()
743
+ const sql = `SELECT ${selectExpr} FROM "${tableName}" ${whereClause} ${groupByClause} ${orderClause} ${limitClause}`
744
+ .replace(/\s+/g, " ")
745
+ .trim()
400
746
 
401
747
  return { sql, params }
402
748
  }