@effect-app/infra 4.0.0-beta.26 → 4.0.0-beta.261

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 (505) hide show
  1. package/CHANGELOG.md +1973 -0
  2. package/_check.sh +1 -1
  3. package/dist/CUPS.d.ts +30 -11
  4. package/dist/CUPS.d.ts.map +1 -1
  5. package/dist/CUPS.js +35 -14
  6. package/dist/ClusterCosmos.d.ts +64 -0
  7. package/dist/ClusterCosmos.d.ts.map +1 -0
  8. package/dist/ClusterCosmos.js +501 -0
  9. package/dist/ClusterServiceBus.d.ts +67 -0
  10. package/dist/ClusterServiceBus.d.ts.map +1 -0
  11. package/dist/ClusterServiceBus.js +82 -0
  12. package/dist/ContextProvider.d.ts +34 -0
  13. package/dist/ContextProvider.d.ts.map +1 -0
  14. package/dist/ContextProvider.js +40 -0
  15. package/dist/Emailer/Sendgrid.d.ts +111 -147
  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 +2 -2
  19. package/dist/Emailer/fake.d.ts.map +1 -1
  20. package/dist/Emailer/fake.js +4 -4
  21. package/dist/MainFiberSet.d.ts +12 -9
  22. package/dist/MainFiberSet.d.ts.map +1 -1
  23. package/dist/MainFiberSet.js +10 -6
  24. package/dist/QueueMaker/SQLQueue.d.ts +8 -9
  25. package/dist/QueueMaker/SQLQueue.d.ts.map +1 -1
  26. package/dist/QueueMaker/SQLQueue.js +138 -120
  27. package/dist/QueueMaker/errors.d.ts +5 -3
  28. package/dist/QueueMaker/errors.d.ts.map +1 -1
  29. package/dist/QueueMaker/errors.js +4 -2
  30. package/dist/QueueMaker/memQueue.d.ts +10 -6
  31. package/dist/QueueMaker/memQueue.d.ts.map +1 -1
  32. package/dist/QueueMaker/memQueue.js +84 -68
  33. package/dist/QueueMaker/sbqueue.d.ts +9 -5
  34. package/dist/QueueMaker/sbqueue.d.ts.map +1 -1
  35. package/dist/QueueMaker/sbqueue.js +60 -58
  36. package/dist/RequestFiberSet.d.ts +10 -7
  37. package/dist/RequestFiberSet.d.ts.map +1 -1
  38. package/dist/RequestFiberSet.js +13 -8
  39. package/dist/SQL/Model.d.ts +468 -0
  40. package/dist/SQL/Model.d.ts.map +1 -0
  41. package/dist/SQL/Model.js +469 -0
  42. package/dist/SQL.d.ts +2 -0
  43. package/dist/SQL.d.ts.map +1 -0
  44. package/dist/{adapters/SQL.js → SQL.js} +1 -1
  45. package/dist/ServiceBus.d.ts +61 -0
  46. package/dist/ServiceBus.d.ts.map +1 -0
  47. package/dist/ServiceBus.js +108 -0
  48. package/dist/Store/Cosmos/query.d.ts +15 -4
  49. package/dist/Store/Cosmos/query.d.ts.map +1 -1
  50. package/dist/Store/Cosmos/query.js +179 -41
  51. package/dist/Store/Cosmos.d.ts +3 -3
  52. package/dist/Store/Cosmos.d.ts.map +1 -1
  53. package/dist/Store/Cosmos.js +344 -246
  54. package/dist/Store/Disk.d.ts +5 -5
  55. package/dist/Store/Disk.d.ts.map +1 -1
  56. package/dist/Store/Disk.js +78 -38
  57. package/dist/Store/Memory.d.ts +7 -10
  58. package/dist/Store/Memory.d.ts.map +1 -1
  59. package/dist/Store/Memory.js +326 -66
  60. package/dist/Store/SQL/Pg.d.ts +4 -0
  61. package/dist/Store/SQL/Pg.d.ts.map +1 -0
  62. package/dist/Store/SQL/Pg.js +232 -0
  63. package/dist/Store/SQL/query.d.ts +49 -0
  64. package/dist/Store/SQL/query.d.ts.map +1 -0
  65. package/dist/Store/SQL/query.js +527 -0
  66. package/dist/Store/SQL.d.ts +21 -0
  67. package/dist/Store/SQL.d.ts.map +1 -0
  68. package/dist/Store/SQL.js +449 -0
  69. package/dist/Store/codeFilter.d.ts +5 -5
  70. package/dist/Store/codeFilter.d.ts.map +1 -1
  71. package/dist/Store/codeFilter.js +6 -3
  72. package/dist/Store/index.d.ts +7 -5
  73. package/dist/Store/index.d.ts.map +1 -1
  74. package/dist/Store/index.js +18 -5
  75. package/dist/Store/utils.d.ts +4 -3
  76. package/dist/Store/utils.d.ts.map +1 -1
  77. package/dist/Store/utils.js +5 -5
  78. package/dist/WorkflowEngineCosmos.d.ts +29 -0
  79. package/dist/WorkflowEngineCosmos.d.ts.map +1 -0
  80. package/dist/WorkflowEngineCosmos.js +521 -0
  81. package/dist/WorkflowEngineSqlite.d.ts +24 -0
  82. package/dist/WorkflowEngineSqlite.d.ts.map +1 -0
  83. package/dist/WorkflowEngineSqlite.js +550 -0
  84. package/dist/arbs.d.ts +2 -2
  85. package/dist/arbs.d.ts.map +1 -1
  86. package/dist/arbs.js +5 -3
  87. package/dist/codec.d.ts +5 -0
  88. package/dist/codec.d.ts.map +1 -0
  89. package/dist/codec.js +5 -0
  90. package/dist/cosmos-client.d.ts +16 -0
  91. package/dist/cosmos-client.d.ts.map +1 -0
  92. package/dist/cosmos-client.js +11 -0
  93. package/dist/errorReporter.d.ts +7 -5
  94. package/dist/errorReporter.d.ts.map +1 -1
  95. package/dist/errorReporter.js +23 -27
  96. package/dist/errors.d.ts +1 -1
  97. package/dist/fileUtil.d.ts +2 -2
  98. package/dist/fileUtil.d.ts.map +1 -1
  99. package/dist/fileUtil.js +2 -2
  100. package/dist/index.d.ts +3 -2
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +3 -2
  103. package/dist/internal/RequestContextMiddleware.d.ts +5 -0
  104. package/dist/internal/RequestContextMiddleware.d.ts.map +1 -0
  105. package/dist/internal/RequestContextMiddleware.js +45 -0
  106. package/dist/internal/auth.d.ts +53 -0
  107. package/dist/internal/auth.d.ts.map +1 -0
  108. package/dist/internal/auth.js +180 -0
  109. package/dist/internal/events.d.ts +11 -0
  110. package/dist/internal/events.d.ts.map +1 -0
  111. package/dist/internal/events.js +49 -0
  112. package/dist/internal/health.d.ts +3 -0
  113. package/dist/internal/health.d.ts.map +1 -0
  114. package/dist/internal/health.js +5 -0
  115. package/dist/layerUtils.d.ts +32 -0
  116. package/dist/layerUtils.d.ts.map +1 -0
  117. package/dist/layerUtils.js +17 -0
  118. package/dist/logger/jsonLogger.d.ts +2 -2
  119. package/dist/logger/jsonLogger.d.ts.map +1 -1
  120. package/dist/logger/jsonLogger.js +5 -3
  121. package/dist/logger/logFmtLogger.d.ts +2 -2
  122. package/dist/logger/logFmtLogger.d.ts.map +1 -1
  123. package/dist/logger/logFmtLogger.js +3 -3
  124. package/dist/logger/shared.d.ts +3 -3
  125. package/dist/logger/shared.d.ts.map +1 -1
  126. package/dist/logger/shared.js +5 -5
  127. package/dist/logger.d.ts +1 -1
  128. package/dist/logger.d.ts.map +1 -1
  129. package/dist/memQueue.d.ts +15 -0
  130. package/dist/memQueue.d.ts.map +1 -0
  131. package/dist/memQueue.js +21 -0
  132. package/dist/middlewares.d.ts +10 -0
  133. package/dist/middlewares.d.ts.map +1 -0
  134. package/dist/{api/middlewares.js → middlewares.js} +1 -1
  135. package/dist/mongo-client.d.ts +11 -0
  136. package/dist/mongo-client.d.ts.map +1 -0
  137. package/dist/mongo-client.js +15 -0
  138. package/dist/otel.d.ts +75 -0
  139. package/dist/otel.d.ts.map +1 -0
  140. package/dist/otel.js +65 -0
  141. package/dist/rateLimit.d.ts +12 -4
  142. package/dist/rateLimit.d.ts.map +1 -1
  143. package/dist/rateLimit.js +7 -12
  144. package/dist/redis-client.d.ts +42 -0
  145. package/dist/redis-client.d.ts.map +1 -0
  146. package/dist/redis-client.js +98 -0
  147. package/dist/reportError.d.ts +4 -0
  148. package/dist/reportError.d.ts.map +1 -0
  149. package/dist/reportError.js +28 -0
  150. package/dist/routing/middleware/RouterMiddleware.d.ts +16 -0
  151. package/dist/routing/middleware/RouterMiddleware.d.ts.map +1 -0
  152. package/dist/{api/routing → routing}/middleware/RouterMiddleware.js +1 -1
  153. package/dist/routing/middleware/middleware.d.ts +48 -0
  154. package/dist/routing/middleware/middleware.d.ts.map +1 -0
  155. package/dist/routing/middleware/middleware.js +128 -0
  156. package/dist/routing/middleware.d.ts +3 -0
  157. package/dist/routing/middleware.d.ts.map +1 -0
  158. package/dist/{api/routing → routing}/middleware.js +1 -2
  159. package/dist/routing/schema/jwt.d.ts +4 -0
  160. package/dist/routing/schema/jwt.d.ts.map +1 -0
  161. package/dist/routing/schema/jwt.js +13 -0
  162. package/dist/routing/tsort.d.ts +8 -0
  163. package/dist/routing/tsort.d.ts.map +1 -0
  164. package/dist/routing/tsort.js +51 -0
  165. package/dist/routing/utils.d.ts +19 -0
  166. package/dist/routing/utils.d.ts.map +1 -0
  167. package/dist/routing/utils.js +45 -0
  168. package/dist/routing.d.ts +184 -0
  169. package/dist/routing.d.ts.map +1 -0
  170. package/dist/routing.js +236 -0
  171. package/dist/test.d.ts +3 -3
  172. package/dist/test.d.ts.map +1 -1
  173. package/dist/test.js +2 -2
  174. package/dist/util.d.ts +3 -0
  175. package/dist/util.d.ts.map +1 -0
  176. package/dist/util.js +14 -0
  177. package/dist/vitest.d.ts +1 -1
  178. package/docs/cluster-storage.md +26 -0
  179. package/docs/workflow-engine.md +262 -0
  180. package/examples/query.ts +47 -39
  181. package/package.json +31 -345
  182. package/run.sh +1 -0
  183. package/src/CUPS.ts +52 -13
  184. package/src/ClusterCosmos.ts +984 -0
  185. package/src/ClusterServiceBus.ts +242 -0
  186. package/src/{api/ContextProvider.ts → ContextProvider.ts} +19 -16
  187. package/src/Emailer/Sendgrid.ts +82 -59
  188. package/src/Emailer/fake.ts +3 -3
  189. package/src/MainFiberSet.ts +12 -10
  190. package/src/QueueMaker/SQLQueue.ts +153 -156
  191. package/src/QueueMaker/errors.ts +3 -1
  192. package/src/QueueMaker/memQueue.ts +113 -107
  193. package/src/QueueMaker/sbqueue.ts +78 -90
  194. package/src/RequestFiberSet.ts +13 -8
  195. package/src/{adapters/SQL → SQL}/Model.ts +42 -41
  196. package/src/ServiceBus.ts +219 -0
  197. package/src/Store/Cosmos/query.ts +216 -52
  198. package/src/Store/Cosmos.ts +493 -353
  199. package/src/Store/Disk.ts +109 -69
  200. package/src/Store/Memory.ts +365 -96
  201. package/src/Store/SQL/Pg.ts +363 -0
  202. package/src/Store/SQL/query.ts +603 -0
  203. package/src/Store/SQL.ts +735 -0
  204. package/src/Store/codeFilter.ts +8 -5
  205. package/src/Store/index.ts +21 -6
  206. package/src/Store/utils.ts +26 -24
  207. package/src/WorkflowEngineCosmos.ts +719 -0
  208. package/src/WorkflowEngineSqlite.ts +813 -0
  209. package/src/arbs.ts +5 -3
  210. package/src/{adapters/cosmos-client.ts → cosmos-client.ts} +5 -3
  211. package/src/errorReporter.ts +66 -76
  212. package/src/fileUtil.ts +1 -1
  213. package/src/index.ts +2 -1
  214. package/src/{api/internal → internal}/RequestContextMiddleware.ts +23 -6
  215. package/src/internal/auth.ts +272 -0
  216. package/src/{api/internal → internal}/events.ts +22 -13
  217. package/src/{api/layerUtils.ts → layerUtils.ts} +14 -10
  218. package/src/logger/jsonLogger.ts +4 -2
  219. package/src/logger/logFmtLogger.ts +2 -2
  220. package/src/logger/shared.ts +5 -4
  221. package/src/{adapters/memQueue.ts → memQueue.ts} +5 -4
  222. package/src/{adapters/mongo-client.ts → mongo-client.ts} +4 -2
  223. package/src/otel.ts +152 -0
  224. package/src/rateLimit.ts +34 -23
  225. package/src/{adapters/redis-client.ts → redis-client.ts} +7 -3
  226. package/src/{api/reportError.ts → reportError.ts} +3 -2
  227. package/src/{api/routing → routing}/middleware/RouterMiddleware.ts +5 -4
  228. package/src/{api/routing → routing}/middleware/middleware.ts +62 -17
  229. package/src/routing/middleware.ts +4 -0
  230. package/src/{api/routing → routing}/schema/jwt.ts +2 -1
  231. package/src/{api/routing → routing}/utils.ts +2 -1
  232. package/src/routing.ts +768 -0
  233. package/src/test.ts +2 -2
  234. package/test/auth.test.ts +101 -0
  235. package/test/cluster-cosmos.test.ts +590 -0
  236. package/test/cluster-servicebus.test.ts +180 -0
  237. package/test/cluster-sqlite.test.ts +207 -0
  238. package/test/contextProvider.test.ts +15 -12
  239. package/test/controller.test.ts +28 -32
  240. package/test/cosmos-query.test.ts +159 -0
  241. package/test/dist/_check-agg-infer.test-d.d.ts +2 -0
  242. package/test/dist/_check-agg-infer.test-d.d.ts.map +1 -0
  243. package/test/dist/_check-agg-infer.test-d.js +19 -0
  244. package/test/dist/_check-proj-infer.test-d.d.ts +2 -0
  245. package/test/dist/_check-proj-infer.test-d.d.ts.map +1 -0
  246. package/test/dist/_check-proj-infer.test-d.js +16 -0
  247. package/test/dist/_check-tighten.test-d.d.ts +2 -0
  248. package/test/dist/_check-tighten.test-d.d.ts.map +1 -0
  249. package/test/dist/_check-tighten.test-d.js +21 -0
  250. package/test/dist/auth.test.d.ts.map +1 -0
  251. package/test/dist/cluster-cosmos.test.d.ts.map +1 -0
  252. package/test/dist/cluster-servicebus.test.d.ts.map +1 -0
  253. package/test/dist/cluster-sqlite.test.d.ts.map +1 -0
  254. package/test/dist/contextProvider.test.d.ts.map +1 -1
  255. package/test/dist/controller.test.d.ts.map +1 -1
  256. package/test/dist/cosmos-query.test.d.ts.map +1 -0
  257. package/test/dist/date-query.test.d.ts.map +1 -0
  258. package/test/dist/fixtures.d.ts +30 -12
  259. package/test/dist/fixtures.d.ts.map +1 -1
  260. package/test/dist/fixtures.js +17 -10
  261. package/test/dist/query.test.d.ts.map +1 -1
  262. package/test/dist/rawQuery.test.d.ts.map +1 -1
  263. package/test/dist/repository-ext.test.d.ts.map +1 -0
  264. package/test/dist/requires.test.d.ts.map +1 -1
  265. package/test/dist/router-generator.test.d.ts.map +1 -0
  266. package/test/dist/routing-interruptibility.test.d.ts.map +1 -0
  267. package/test/dist/rpc-context-map-streaming.test.d.ts.map +1 -0
  268. package/test/dist/rpc-e2e-invalidation.test.d.ts.map +1 -0
  269. package/test/dist/rpc-multi-middleware.test.d.ts.map +1 -1
  270. package/test/dist/rpc-stream-fullstack.test.d.ts.map +1 -0
  271. package/test/dist/sql-store.test.d.ts.map +1 -0
  272. package/test/dist/workflow-engine-cosmos.test.d.ts.map +1 -0
  273. package/test/dist/workflow-engine-sqlite.test.d.ts.map +1 -0
  274. package/test/fixtures.ts +16 -9
  275. package/test/layerUtils.test.ts +2 -2
  276. package/test/query.test.ts +905 -40
  277. package/test/rawQuery.test.ts +340 -22
  278. package/test/repository-ext.test.ts +62 -0
  279. package/test/requires.test.ts +10 -5
  280. package/test/router-generator.test.ts +187 -0
  281. package/test/routing-interruptibility.test.ts +66 -0
  282. package/test/rpc-context-map-streaming.test.ts +262 -0
  283. package/test/rpc-e2e-invalidation.test.ts +256 -0
  284. package/test/rpc-multi-middleware.test.ts +85 -10
  285. package/test/rpc-stream-fullstack.test.ts +304 -0
  286. package/test/sql-store.test.ts +1711 -0
  287. package/test/validateSample.test.ts +26 -14
  288. package/test/workflow-engine-cosmos.test.ts +354 -0
  289. package/test/workflow-engine-sqlite.test.ts +299 -0
  290. package/tsconfig.examples.json +1 -1
  291. package/tsconfig.json +2 -1
  292. package/tsconfig.json.bak +2 -2
  293. package/tsconfig.src.json +35 -35
  294. package/tsconfig.test.json +2 -2
  295. package/dist/Emailer/service.d.ts +0 -55
  296. package/dist/Emailer/service.d.ts.map +0 -1
  297. package/dist/Emailer/service.js +0 -6
  298. package/dist/Emailer.d.ts +0 -2
  299. package/dist/Emailer.d.ts.map +0 -1
  300. package/dist/Emailer.js +0 -2
  301. package/dist/Model/Repository/ext.d.ts +0 -41
  302. package/dist/Model/Repository/ext.d.ts.map +0 -1
  303. package/dist/Model/Repository/ext.js +0 -65
  304. package/dist/Model/Repository/internal/internal.d.ts +0 -59
  305. package/dist/Model/Repository/internal/internal.d.ts.map +0 -1
  306. package/dist/Model/Repository/internal/internal.js +0 -316
  307. package/dist/Model/Repository/legacy.d.ts +0 -19
  308. package/dist/Model/Repository/legacy.d.ts.map +0 -1
  309. package/dist/Model/Repository/legacy.js +0 -2
  310. package/dist/Model/Repository/makeRepo.d.ts +0 -49
  311. package/dist/Model/Repository/makeRepo.d.ts.map +0 -1
  312. package/dist/Model/Repository/makeRepo.js +0 -24
  313. package/dist/Model/Repository/service.d.ts +0 -89
  314. package/dist/Model/Repository/service.d.ts.map +0 -1
  315. package/dist/Model/Repository/service.js +0 -2
  316. package/dist/Model/Repository/validation.d.ts +0 -42
  317. package/dist/Model/Repository/validation.d.ts.map +0 -1
  318. package/dist/Model/Repository/validation.js +0 -32
  319. package/dist/Model/Repository.d.ts +0 -6
  320. package/dist/Model/Repository.d.ts.map +0 -1
  321. package/dist/Model/Repository.js +0 -6
  322. package/dist/Model/dsl.d.ts +0 -32
  323. package/dist/Model/dsl.d.ts.map +0 -1
  324. package/dist/Model/dsl.js +0 -44
  325. package/dist/Model/filter/filterApi.d.ts +0 -30
  326. package/dist/Model/filter/filterApi.d.ts.map +0 -1
  327. package/dist/Model/filter/filterApi.js +0 -2
  328. package/dist/Model/filter/types/errors.d.ts +0 -29
  329. package/dist/Model/filter/types/errors.d.ts.map +0 -1
  330. package/dist/Model/filter/types/errors.js +0 -2
  331. package/dist/Model/filter/types/fields.d.ts +0 -15
  332. package/dist/Model/filter/types/fields.d.ts.map +0 -1
  333. package/dist/Model/filter/types/fields.js +0 -2
  334. package/dist/Model/filter/types/path/common.d.ts +0 -316
  335. package/dist/Model/filter/types/path/common.d.ts.map +0 -1
  336. package/dist/Model/filter/types/path/common.js +0 -2
  337. package/dist/Model/filter/types/path/eager.d.ts +0 -95
  338. package/dist/Model/filter/types/path/eager.d.ts.map +0 -1
  339. package/dist/Model/filter/types/path/eager.js +0 -31
  340. package/dist/Model/filter/types/path/index.d.ts +0 -4
  341. package/dist/Model/filter/types/path/index.d.ts.map +0 -1
  342. package/dist/Model/filter/types/path/index.js +0 -3
  343. package/dist/Model/filter/types/utils.d.ts +0 -79
  344. package/dist/Model/filter/types/utils.d.ts.map +0 -1
  345. package/dist/Model/filter/types/utils.js +0 -2
  346. package/dist/Model/filter/types/validator.d.ts +0 -30
  347. package/dist/Model/filter/types/validator.d.ts.map +0 -1
  348. package/dist/Model/filter/types/validator.js +0 -2
  349. package/dist/Model/filter/types.d.ts +0 -5
  350. package/dist/Model/filter/types.d.ts.map +0 -1
  351. package/dist/Model/filter/types.js +0 -7
  352. package/dist/Model/query/dsl.d.ts +0 -248
  353. package/dist/Model/query/dsl.d.ts.map +0 -1
  354. package/dist/Model/query/dsl.js +0 -104
  355. package/dist/Model/query/new-kid-interpreter.d.ts +0 -28
  356. package/dist/Model/query/new-kid-interpreter.d.ts.map +0 -1
  357. package/dist/Model/query/new-kid-interpreter.js +0 -165
  358. package/dist/Model/query.d.ts +0 -15
  359. package/dist/Model/query.d.ts.map +0 -1
  360. package/dist/Model/query.js +0 -3
  361. package/dist/Model.d.ts +0 -4
  362. package/dist/Model.d.ts.map +0 -1
  363. package/dist/Model.js +0 -4
  364. package/dist/Operations.d.ts +0 -55
  365. package/dist/Operations.d.ts.map +0 -1
  366. package/dist/Operations.js +0 -102
  367. package/dist/OperationsRepo.d.ts +0 -41
  368. package/dist/OperationsRepo.d.ts.map +0 -1
  369. package/dist/OperationsRepo.js +0 -14
  370. package/dist/QueueMaker/service.d.ts +0 -11
  371. package/dist/QueueMaker/service.d.ts.map +0 -1
  372. package/dist/QueueMaker/service.js +0 -4
  373. package/dist/RequestContext.d.ts +0 -63
  374. package/dist/RequestContext.d.ts.map +0 -1
  375. package/dist/RequestContext.js +0 -49
  376. package/dist/Store/ContextMapContainer.d.ts +0 -14
  377. package/dist/Store/ContextMapContainer.d.ts.map +0 -1
  378. package/dist/Store/ContextMapContainer.js +0 -16
  379. package/dist/Store/service.d.ts +0 -108
  380. package/dist/Store/service.d.ts.map +0 -1
  381. package/dist/Store/service.js +0 -71
  382. package/dist/Store.d.ts +0 -2
  383. package/dist/Store.d.ts.map +0 -1
  384. package/dist/Store.js +0 -2
  385. package/dist/adapters/SQL/Model.d.ts +0 -479
  386. package/dist/adapters/SQL/Model.d.ts.map +0 -1
  387. package/dist/adapters/SQL/Model.js +0 -478
  388. package/dist/adapters/SQL.d.ts +0 -2
  389. package/dist/adapters/SQL.d.ts.map +0 -1
  390. package/dist/adapters/ServiceBus.d.ts +0 -58
  391. package/dist/adapters/ServiceBus.d.ts.map +0 -1
  392. package/dist/adapters/ServiceBus.js +0 -99
  393. package/dist/adapters/cosmos-client.d.ts +0 -14
  394. package/dist/adapters/cosmos-client.d.ts.map +0 -1
  395. package/dist/adapters/cosmos-client.js +0 -9
  396. package/dist/adapters/index.d.ts +0 -2
  397. package/dist/adapters/index.d.ts.map +0 -1
  398. package/dist/adapters/index.js +0 -2
  399. package/dist/adapters/logger.d.ts +0 -9
  400. package/dist/adapters/logger.d.ts.map +0 -1
  401. package/dist/adapters/logger.js +0 -3
  402. package/dist/adapters/memQueue.d.ts +0 -13
  403. package/dist/adapters/memQueue.d.ts.map +0 -1
  404. package/dist/adapters/memQueue.js +0 -20
  405. package/dist/adapters/mongo-client.d.ts +0 -10
  406. package/dist/adapters/mongo-client.d.ts.map +0 -1
  407. package/dist/adapters/mongo-client.js +0 -13
  408. package/dist/adapters/redis-client.d.ts +0 -39
  409. package/dist/adapters/redis-client.d.ts.map +0 -1
  410. package/dist/adapters/redis-client.js +0 -94
  411. package/dist/api/ContextProvider.d.ts +0 -31
  412. package/dist/api/ContextProvider.d.ts.map +0 -1
  413. package/dist/api/ContextProvider.js +0 -38
  414. package/dist/api/codec.d.ts +0 -5
  415. package/dist/api/codec.d.ts.map +0 -1
  416. package/dist/api/codec.js +0 -5
  417. package/dist/api/internal/RequestContextMiddleware.d.ts +0 -5
  418. package/dist/api/internal/RequestContextMiddleware.d.ts.map +0 -1
  419. package/dist/api/internal/RequestContextMiddleware.js +0 -35
  420. package/dist/api/internal/auth.d.ts +0 -15
  421. package/dist/api/internal/auth.d.ts.map +0 -1
  422. package/dist/api/internal/auth.js +0 -47
  423. package/dist/api/internal/events.d.ts +0 -9
  424. package/dist/api/internal/events.d.ts.map +0 -1
  425. package/dist/api/internal/events.js +0 -42
  426. package/dist/api/internal/health.d.ts +0 -3
  427. package/dist/api/internal/health.d.ts.map +0 -1
  428. package/dist/api/internal/health.js +0 -5
  429. package/dist/api/layerUtils.d.ts +0 -24
  430. package/dist/api/layerUtils.d.ts.map +0 -1
  431. package/dist/api/layerUtils.js +0 -16
  432. package/dist/api/middlewares.d.ts +0 -10
  433. package/dist/api/middlewares.d.ts.map +0 -1
  434. package/dist/api/reportError.d.ts +0 -4
  435. package/dist/api/reportError.d.ts.map +0 -1
  436. package/dist/api/reportError.js +0 -27
  437. package/dist/api/routing/middleware/RouterMiddleware.d.ts +0 -15
  438. package/dist/api/routing/middleware/RouterMiddleware.d.ts.map +0 -1
  439. package/dist/api/routing/middleware/middleware.d.ts +0 -9
  440. package/dist/api/routing/middleware/middleware.d.ts.map +0 -1
  441. package/dist/api/routing/middleware/middleware.js +0 -92
  442. package/dist/api/routing/middleware.d.ts +0 -4
  443. package/dist/api/routing/middleware.d.ts.map +0 -1
  444. package/dist/api/routing/schema/jwt.d.ts +0 -4
  445. package/dist/api/routing/schema/jwt.d.ts.map +0 -1
  446. package/dist/api/routing/schema/jwt.js +0 -12
  447. package/dist/api/routing/tsort.d.ts +0 -8
  448. package/dist/api/routing/tsort.d.ts.map +0 -1
  449. package/dist/api/routing/tsort.js +0 -51
  450. package/dist/api/routing/utils.d.ts +0 -19
  451. package/dist/api/routing/utils.d.ts.map +0 -1
  452. package/dist/api/routing/utils.js +0 -44
  453. package/dist/api/routing.d.ts +0 -138
  454. package/dist/api/routing.d.ts.map +0 -1
  455. package/dist/api/routing.js +0 -166
  456. package/dist/api/setupRequest.d.ts +0 -12
  457. package/dist/api/setupRequest.d.ts.map +0 -1
  458. package/dist/api/setupRequest.js +0 -44
  459. package/dist/api/util.d.ts +0 -3
  460. package/dist/api/util.d.ts.map +0 -1
  461. package/dist/api/util.js +0 -14
  462. package/eslint.config.mjs +0 -24
  463. package/src/Emailer/service.ts +0 -52
  464. package/src/Emailer.ts +0 -1
  465. package/src/Model/Repository/ext.ts +0 -283
  466. package/src/Model/Repository/internal/internal.ts +0 -577
  467. package/src/Model/Repository/legacy.ts +0 -27
  468. package/src/Model/Repository/makeRepo.ts +0 -139
  469. package/src/Model/Repository/service.ts +0 -627
  470. package/src/Model/Repository/validation.ts +0 -31
  471. package/src/Model/Repository.ts +0 -5
  472. package/src/Model/dsl.ts +0 -128
  473. package/src/Model/filter/filterApi.ts +0 -60
  474. package/src/Model/filter/types/errors.ts +0 -47
  475. package/src/Model/filter/types/fields.ts +0 -50
  476. package/src/Model/filter/types/path/common.ts +0 -404
  477. package/src/Model/filter/types/path/eager.ts +0 -298
  478. package/src/Model/filter/types/path/index.ts +0 -4
  479. package/src/Model/filter/types/utils.ts +0 -128
  480. package/src/Model/filter/types/validator.ts +0 -46
  481. package/src/Model/filter/types.ts +0 -6
  482. package/src/Model/query/dsl.ts +0 -2110
  483. package/src/Model/query/new-kid-interpreter.ts +0 -210
  484. package/src/Model/query.ts +0 -13
  485. package/src/Model.ts +0 -3
  486. package/src/Operations.ts +0 -235
  487. package/src/OperationsRepo.ts +0 -16
  488. package/src/QueueMaker/service.ts +0 -17
  489. package/src/RequestContext.ts +0 -63
  490. package/src/Store/ContextMapContainer.ts +0 -20
  491. package/src/Store/service.ts +0 -184
  492. package/src/Store.ts +0 -1
  493. package/src/adapters/ServiceBus.ts +0 -209
  494. package/src/adapters/index.ts +0 -0
  495. package/src/adapters/logger.ts +0 -3
  496. package/src/api/internal/auth.ts +0 -68
  497. package/src/api/routing/middleware.ts +0 -6
  498. package/src/api/routing.ts +0 -598
  499. package/src/api/setupRequest.ts +0 -84
  500. /package/src/{adapters/SQL.ts → SQL.ts} +0 -0
  501. /package/src/{api/codec.ts → codec.ts} +0 -0
  502. /package/src/{api/internal → internal}/health.ts +0 -0
  503. /package/src/{api/middlewares.ts → middlewares.ts} +0 -0
  504. /package/src/{api/routing → routing}/tsort.ts +0 -0
  505. /package/src/{api/util.ts → util.ts} +0 -0
@@ -0,0 +1,603 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
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"
6
+ import { assertUnreachable } from "effect-app/utils"
7
+ import { InfraLogger } from "../../logger.js"
8
+ import { isRelationCheck } from "../codeFilter.js"
9
+
10
+ export interface SQLDialect {
11
+ readonly jsonExtract: (path: string) => string
12
+ readonly jsonExtractJson: (path: string) => string
13
+ readonly placeholder: (index: number) => string
14
+ readonly jsonArrayContains: (arrPath: string, valPlaceholder: string) => string
15
+ readonly jsonArrayNotContains: (arrPath: string, valPlaceholder: string) => string
16
+ readonly jsonArrayContainsAny: (arrPath: string, valPlaceholders: readonly string[]) => string
17
+ readonly jsonArrayNotContainsAny: (arrPath: string, valPlaceholders: readonly string[]) => string
18
+ readonly jsonArrayContainsAll: (arrPath: string, valPlaceholders: readonly string[]) => string
19
+ readonly jsonArrayNotContainsAll: (arrPath: string, valPlaceholders: readonly string[]) => string
20
+ readonly caseInsensitiveLike: (expr: string, valPlaceholder: string) => string
21
+ readonly caseInsensitiveNotLike: (expr: string, valPlaceholder: string) => string
22
+ readonly jsonColumnType: "JSON" | "JSONB"
23
+ readonly arrayLength: (path: string) => string
24
+ readonly jsonEachFrom: (arrPath: string, alias: string) => string
25
+ readonly jsonExtractElement: (alias: string, subPath: string) => string
26
+ readonly serializeJsonValue: (v: unknown) => unknown
27
+ readonly serializeScalar: (v: unknown) => unknown
28
+ }
29
+
30
+ export const sqliteDialect: SQLDialect = {
31
+ jsonExtract: (path) => `json_extract(data, '$.${path}')`,
32
+ jsonExtractJson: (path) =>
33
+ `CASE json_type(data, '$.${path}') WHEN 'true' THEN 'true' WHEN 'false' THEN 'false' ELSE json_quote(json_extract(data, '$.${path}')) END`,
34
+ placeholder: (_index) => "?",
35
+ jsonArrayContains: (arrPath, val) => `EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE value = ${val})`,
36
+ jsonArrayNotContains: (arrPath, val) =>
37
+ `NOT EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE value = ${val})`,
38
+ jsonArrayContainsAny: (arrPath, vals) =>
39
+ `EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE value IN (${vals.join(", ")}))`,
40
+ jsonArrayNotContainsAny: (arrPath, vals) =>
41
+ `NOT EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE value IN (${vals.join(", ")}))`,
42
+ jsonArrayContainsAll: (arrPath, vals) =>
43
+ vals.map((v) => `EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE value = ${v})`).join(" AND "),
44
+ jsonArrayNotContainsAll: (arrPath, vals) =>
45
+ `NOT (${
46
+ vals.map((v) => `EXISTS(SELECT 1 FROM json_each(data, '$.${arrPath}') WHERE value = ${v})`).join(" AND ")
47
+ })`,
48
+ caseInsensitiveLike: (expr, val) => `LOWER(${expr}) LIKE LOWER(${val})`,
49
+ caseInsensitiveNotLike: (expr, val) => `LOWER(${expr}) NOT LIKE LOWER(${val})`,
50
+ jsonColumnType: "JSON",
51
+ arrayLength: (path) => `json_array_length(data, '$.${path}')`,
52
+ jsonEachFrom: (arrPath, alias) => `json_each(data, '$.${arrPath}') AS ${alias}`,
53
+ jsonExtractElement: (alias, subPath) => `json_extract(${alias}.value, '$.${subPath}')`,
54
+ serializeJsonValue: (v) => v,
55
+ // SQLite stores JSON booleans as integers (0/1) and better-sqlite3 refuses
56
+ // to bind JS booleans, so coerce them to integers for WHERE params.
57
+ serializeScalar: (v) => typeof v === "boolean" ? (v ? 1 : 0) : v
58
+ }
59
+
60
+ export const pgDialect: SQLDialect = {
61
+ jsonExtract: (path) => {
62
+ const parts = path.split(".")
63
+ if (parts.length === 1) return `data->>'${parts[0]}'`
64
+ const last = parts.pop()!
65
+ return `data${parts.map((p) => `->'${p}'`).join("")}->>'${last}'`
66
+ },
67
+ jsonExtractJson: (path) => {
68
+ const parts = path.split(".")
69
+ if (parts.length === 1) return `data->'${parts[0]}'`
70
+ return `data${parts.map((p) => `->'${p}'`).join("")}`
71
+ },
72
+ placeholder: (index) => `$${index}`,
73
+ jsonArrayContains: (arrPath, val) => {
74
+ const parts = arrPath.split(".")
75
+ const jsonPath = parts.length === 1
76
+ ? `data->'${parts[0]}'`
77
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
78
+ return `${jsonPath} @> ${val}::jsonb`
79
+ },
80
+ jsonArrayNotContains: (arrPath, val) => {
81
+ const parts = arrPath.split(".")
82
+ const jsonPath = parts.length === 1
83
+ ? `data->'${parts[0]}'`
84
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
85
+ return `NOT (${jsonPath} @> ${val}::jsonb)`
86
+ },
87
+ jsonArrayContainsAny: (arrPath, vals) => {
88
+ const parts = arrPath.split(".")
89
+ const jsonPath = parts.length === 1
90
+ ? `data->'${parts[0]}'`
91
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
92
+ return `(${vals.map((v) => `${jsonPath} @> ${v}::jsonb`).join(" OR ")})`
93
+ },
94
+ jsonArrayNotContainsAny: (arrPath, vals) => {
95
+ const parts = arrPath.split(".")
96
+ const jsonPath = parts.length === 1
97
+ ? `data->'${parts[0]}'`
98
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
99
+ return `NOT (${vals.map((v) => `${jsonPath} @> ${v}::jsonb`).join(" OR ")})`
100
+ },
101
+ jsonArrayContainsAll: (arrPath, vals) => {
102
+ const parts = arrPath.split(".")
103
+ const jsonPath = parts.length === 1
104
+ ? `data->'${parts[0]}'`
105
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
106
+ return vals.map((v) => `${jsonPath} @> ${v}::jsonb`).join(" AND ")
107
+ },
108
+ jsonArrayNotContainsAll: (arrPath, vals) => {
109
+ const parts = arrPath.split(".")
110
+ const jsonPath = parts.length === 1
111
+ ? `data->'${parts[0]}'`
112
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
113
+ return `NOT (${vals.map((v) => `${jsonPath} @> ${v}::jsonb`).join(" AND ")})`
114
+ },
115
+ caseInsensitiveLike: (expr, val) => `${expr} ILIKE ${val}`,
116
+ caseInsensitiveNotLike: (expr, val) => `${expr} NOT ILIKE ${val}`,
117
+ jsonColumnType: "JSONB",
118
+ arrayLength: (path) => `jsonb_array_length(data->'${path}')`,
119
+ jsonEachFrom: (arrPath, alias) => {
120
+ const parts = arrPath.split(".")
121
+ const jsonPath = parts.length === 1
122
+ ? `data->'${parts[0]}'`
123
+ : `data${parts.map((p) => `->'${p}'`).join("")}`
124
+ return `jsonb_array_elements(${jsonPath}) AS ${alias}`
125
+ },
126
+ jsonExtractElement: (alias, subPath) => {
127
+ const parts = subPath.split(".")
128
+ if (parts.length === 1) return `${alias}->>'${parts[0]}'`
129
+ const last = parts.pop()!
130
+ return `${alias}${parts.map((p) => `->'${p}'`).join("")}->>'${last}'`
131
+ },
132
+ serializeJsonValue: (v) => JSON.stringify(v),
133
+ // PG's ->> operator yields text, so compare booleans as 'true'/'false' text.
134
+ serializeScalar: (v) => typeof v === "boolean" ? (v ? "true" : "false") : v
135
+ }
136
+
137
+ export function logQuery(q: { sql: string; params: unknown[] }) {
138
+ return InfraLogger
139
+ .logDebug("sql query")
140
+ .pipe(Effect.annotateLogs({
141
+ query: q.sql,
142
+ parameters: JSON.stringify(q.params, undefined, 2)
143
+ }))
144
+ }
145
+
146
+ const dottedToJsonPath = (path: string) =>
147
+ path
148
+ .split(".")
149
+ .filter((p) => p !== "-1")
150
+ .join(".")
151
+
152
+ const sqlStringLiteral = (value: string) => `'${value.replaceAll("'", "''")}'`
153
+
154
+ export function buildWhereSQLQuery(
155
+ dialect: SQLDialect,
156
+ idKey: PropertyKey,
157
+ filter: readonly FilterResult[],
158
+ tableName: string,
159
+ defaultValues: Record<string, unknown>,
160
+ select?: NonEmptyReadonlyArray<
161
+ string | {
162
+ key: string
163
+ subKeys: readonly string[]
164
+ } | {
165
+ key: string
166
+ computed: ComputedProjectionIrExpression
167
+ } | {
168
+ key: string
169
+ path: string
170
+ } | {
171
+ key: string
172
+ aggregate: AggregateIrExpression
173
+ }
174
+ >,
175
+ order?: NonEmptyReadonlyArray<{ key: string; direction: "ASC" | "DESC" }>,
176
+ skip?: number,
177
+ limit?: number,
178
+ namespace?: string
179
+ ) {
180
+ const params: unknown[] = []
181
+ let paramIndex = 1
182
+
183
+ const addParam = (value: unknown): string => {
184
+ params.push(dialect.serializeScalar(value))
185
+ return dialect.placeholder(paramIndex++)
186
+ }
187
+
188
+ const fieldExpr = (path: string, relation?: string): string => {
189
+ if (path === idKey || path === "id") return "id"
190
+ if (relation && path.includes(".-1.")) {
191
+ const subPath = path.split(".-1.")[1]!
192
+ if (subPath.endsWith(".length")) {
193
+ // TODO: array length inside relation element
194
+ return dialect.jsonExtractElement(`_${relation}`, subPath.slice(0, -".length".length))
195
+ }
196
+ return dialect.jsonExtractElement(`_${relation}`, subPath)
197
+ }
198
+ if (path.endsWith(".length")) {
199
+ const arrPath = dottedToJsonPath(path.slice(0, -".length".length))
200
+ return dialect.arrayLength(arrPath)
201
+ }
202
+ const jsonPath = dottedToJsonPath(path)
203
+ const expr = dialect.jsonExtract(jsonPath)
204
+ const topKey = path.split(".")[0]
205
+ if (topKey in defaultValues) {
206
+ return `COALESCE(${expr}, ${addParam(defaultValues[topKey])})`
207
+ }
208
+ return expr
209
+ }
210
+
211
+ const statement = (x: FilterR, relation?: string): string => {
212
+ const resolvedPath = x.path === idKey ? "id" : x.path
213
+ const k = fieldExpr(resolvedPath, relation)
214
+
215
+ switch (x.op) {
216
+ case "in": {
217
+ const vals = x.value as unknown as readonly unknown[]
218
+ const hasNull = vals.some((v) => v == null)
219
+ const nonNullVals = vals.filter((v) => v != null)
220
+ const parts: string[] = []
221
+ if (nonNullVals.length > 0) {
222
+ const placeholders = nonNullVals.map((v) => addParam(v))
223
+ parts.push(`${k} IN (${placeholders.join(", ")})`)
224
+ }
225
+ if (hasNull) parts.push(`${k} IS NULL`)
226
+ return parts.length > 1 ? `(${parts.join(" OR ")})` : parts[0] ?? "1=0"
227
+ }
228
+ case "notIn": {
229
+ const vals = x.value as unknown as readonly unknown[]
230
+ const hasNull = vals.some((v) => v == null)
231
+ const nonNullVals = vals.filter((v) => v != null)
232
+ const parts: string[] = []
233
+ if (nonNullVals.length > 0) {
234
+ const placeholders = nonNullVals.map((v) => addParam(v))
235
+ parts.push(`${k} NOT IN (${placeholders.join(", ")})`)
236
+ }
237
+ if (hasNull) parts.push(`${k} IS NOT NULL`)
238
+ return parts.length > 1 ? `(${parts.join(" AND ")})` : parts[0] ?? "1=1"
239
+ }
240
+
241
+ case "includes": {
242
+ const arrPath = dottedToJsonPath(resolvedPath)
243
+ const v = addParam(x.value)
244
+ return dialect.jsonArrayContains(arrPath, v)
245
+ }
246
+ case "notIncludes": {
247
+ const arrPath = dottedToJsonPath(resolvedPath)
248
+ const v = addParam(x.value)
249
+ return dialect.jsonArrayNotContains(arrPath, v)
250
+ }
251
+
252
+ case "includes-any": {
253
+ const arrPath = dottedToJsonPath(resolvedPath)
254
+ const vals = x.value as unknown as readonly unknown[]
255
+ const placeholders = vals.map((v) => addParam(dialect.serializeJsonValue(v)))
256
+ return dialect.jsonArrayContainsAny(arrPath, placeholders)
257
+ }
258
+ case "notIncludes-any": {
259
+ const arrPath = dottedToJsonPath(resolvedPath)
260
+ const vals = x.value as unknown as readonly unknown[]
261
+ const placeholders = vals.map((v) => addParam(dialect.serializeJsonValue(v)))
262
+ return dialect.jsonArrayNotContainsAny(arrPath, placeholders)
263
+ }
264
+
265
+ case "includes-all": {
266
+ const arrPath = dottedToJsonPath(resolvedPath)
267
+ const vals = x.value as unknown as readonly unknown[]
268
+ const placeholders = vals.map((v) => addParam(dialect.serializeJsonValue(v)))
269
+ return dialect.jsonArrayContainsAll(arrPath, placeholders)
270
+ }
271
+ case "notIncludes-all": {
272
+ const arrPath = dottedToJsonPath(resolvedPath)
273
+ const vals = x.value as unknown as readonly unknown[]
274
+ const placeholders = vals.map((v) => addParam(dialect.serializeJsonValue(v)))
275
+ return dialect.jsonArrayNotContainsAll(arrPath, placeholders)
276
+ }
277
+
278
+ case "contains": {
279
+ const v = addParam(`%${x.value}%`)
280
+ return dialect.caseInsensitiveLike(k, v)
281
+ }
282
+ case "notContains": {
283
+ const v = addParam(`%${x.value}%`)
284
+ return dialect.caseInsensitiveNotLike(k, v)
285
+ }
286
+ case "startsWith": {
287
+ const v = addParam(`${x.value}%`)
288
+ return dialect.caseInsensitiveLike(k, v)
289
+ }
290
+ case "notStartsWith": {
291
+ const v = addParam(`${x.value}%`)
292
+ return dialect.caseInsensitiveNotLike(k, v)
293
+ }
294
+ case "endsWith": {
295
+ const v = addParam(`%${x.value}`)
296
+ return dialect.caseInsensitiveLike(k, v)
297
+ }
298
+ case "notEndsWith": {
299
+ const v = addParam(`%${x.value}`)
300
+ return dialect.caseInsensitiveNotLike(k, v)
301
+ }
302
+
303
+ case "lt": {
304
+ const v = addParam(x.value)
305
+ return `${k} < ${v}`
306
+ }
307
+ case "lte": {
308
+ const v = addParam(x.value)
309
+ return `${k} <= ${v}`
310
+ }
311
+ case "gt": {
312
+ const v = addParam(x.value)
313
+ return `${k} > ${v}`
314
+ }
315
+ case "gte": {
316
+ const v = addParam(x.value)
317
+ return `${k} >= ${v}`
318
+ }
319
+ case "neq": {
320
+ if (x.value === null) return `${k} IS NOT NULL`
321
+ const v = addParam(x.value)
322
+ return `${k} <> ${v}`
323
+ }
324
+ case undefined:
325
+ case "eq": {
326
+ if (x.value === null) return `${k} IS NULL`
327
+ const v = addParam(x.value)
328
+ return `${k} = ${v}`
329
+ }
330
+ default:
331
+ return assertUnreachable(x.op)
332
+ }
333
+ }
334
+
335
+ const wrapRelation = (rel: string, inner: string, every: boolean): string => {
336
+ // Optimize tautological/contradictory conditions
337
+ if (every && inner === "1=1") return "1=1"
338
+ if (!every && inner === "1=0") return "1=0"
339
+ const from = dialect.jsonEachFrom(rel, `_${rel}`)
340
+ // ∀x.P(x) ≡ ¬∃x.¬P(x), i.e. NOT EXISTS(... WHERE NOT P)
341
+ return every
342
+ ? `NOT EXISTS(SELECT 1 FROM ${from} WHERE NOT (${inner}))`
343
+ : `EXISTS(SELECT 1 FROM ${from} WHERE ${inner})`
344
+ }
345
+
346
+ const print = (state: readonly FilterResult[], isRelation: string | null, every: boolean): string => {
347
+ let s = ""
348
+ for (const e of state) {
349
+ switch (e.t) {
350
+ case "where":
351
+ s += statement(e, isRelation ?? undefined)
352
+ break
353
+ case "or":
354
+ s += ` OR ${statement(e, isRelation ?? undefined)}`
355
+ break
356
+ case "and":
357
+ s += ` AND ${statement(e, isRelation ?? undefined)}`
358
+ break
359
+ case "or-scope": {
360
+ if (!every) every = e.relation === "every"
361
+ const rel = isRelationCheck(e.result, isRelation)
362
+ if (rel) {
363
+ s += isRelation
364
+ ? ` OR (${print(e.result, rel, every)})`
365
+ : ` OR ${wrapRelation(rel, print(e.result, rel, every), every)}`
366
+ } else {
367
+ s += ` OR (${print(e.result, null, every)})`
368
+ }
369
+ break
370
+ }
371
+ case "and-scope": {
372
+ if (!every) every = e.relation === "every"
373
+ const rel = isRelationCheck(e.result, isRelation)
374
+ if (rel) {
375
+ s += isRelation
376
+ ? ` AND (${print(e.result, rel, every)})`
377
+ : ` AND ${wrapRelation(rel, print(e.result, rel, every), every)}`
378
+ } else {
379
+ s += ` AND (${print(e.result, null, every)})`
380
+ }
381
+ break
382
+ }
383
+ case "where-scope": {
384
+ if (!every) every = e.relation === "every"
385
+ const rel = isRelationCheck(e.result, isRelation)
386
+ if (rel) {
387
+ s += isRelation
388
+ ? `(${print(e.result, rel, every)})`
389
+ : wrapRelation(rel, print(e.result, rel, every), every)
390
+ } else {
391
+ s += `(${print(e.result, null, every)})`
392
+ }
393
+ break
394
+ }
395
+ }
396
+ }
397
+ return s
398
+ }
399
+
400
+ const computedSelectExpr = (key: string, computed: ComputedProjectionIrExpression): string => {
401
+ const relationPath = dottedToJsonPath(computed.path)
402
+ const relationAlias = `_${computed.path}`
403
+ const relationFrom = dialect.jsonEachFrom(relationPath, relationAlias)
404
+ const toNumber = (expr: string) =>
405
+ dialect.jsonColumnType === "JSON" ? `CAST(${expr} AS REAL)` : `(${expr})::numeric`
406
+ const compileExpr = (expression: ComputedProjectionMathIrExpression): string => {
407
+ switch (expression._tag) {
408
+ case "field":
409
+ return toNumber(dialect.jsonExtractElement(relationAlias, expression.field))
410
+ case "mul":
411
+ return `(${compileExpr(expression.left)} * ${compileExpr(expression.right)})`
412
+ default:
413
+ return assertUnreachable(expression)
414
+ }
415
+ }
416
+ const factorCaseExpr = (unitExpr: string, toBase: string, factors: Readonly<Record<string, number>>) => {
417
+ const entries = Object.entries(factors).filter(([, factor]) => Number.isFinite(factor))
418
+ const cases = entries.map(([unit, factor]) => ` WHEN ${sqlStringLiteral(unit)} THEN ${factor}`).join("")
419
+ return `CASE ${unitExpr} WHEN ${sqlStringLiteral(toBase)} THEN 1${cases} ELSE NULL END`
420
+ }
421
+ const filter = "filter" in computed ? computed.filter : []
422
+ const whereClause = () =>
423
+ filter.length > 0
424
+ ? ` WHERE ${print(filter, computed.path, false)}`
425
+ : ""
426
+ const boolExpr = (sqlExpr: string) =>
427
+ dialect.jsonColumnType === "JSON"
428
+ ? `CASE WHEN ${sqlExpr} THEN 'true' ELSE 'false' END AS "${key}"`
429
+ : `${sqlExpr} AS "${key}"`
430
+ switch (computed._tag) {
431
+ case "relation-count":
432
+ return `(SELECT COUNT(1) FROM ${relationFrom}${whereClause()}) AS "${key}"`
433
+ case "relation-any":
434
+ return boolExpr(`EXISTS(SELECT 1 FROM ${relationFrom}${whereClause()})`)
435
+ case "relation-every":
436
+ // ∀x.P(x) ≡ ¬∃x.¬P(x). When no filter, no element exists that violates ⊤ → true.
437
+ return boolExpr(
438
+ filter.length === 0
439
+ ? `1=1`
440
+ : `NOT EXISTS(SELECT 1 FROM ${relationFrom} WHERE NOT (${print(filter, computed.path, false)}))`
441
+ )
442
+ case "relation-distinct-count": {
443
+ const fieldExtract = dialect.jsonExtractElement(relationAlias, computed.field)
444
+ return `(SELECT COUNT(DISTINCT ${fieldExtract}) FROM ${relationFrom}${whereClause()}) AS "${key}"`
445
+ }
446
+ case "relation-sum": {
447
+ const fieldExtract = dialect.jsonExtractElement(relationAlias, computed.field)
448
+ return `(SELECT COALESCE(SUM(${toNumber(fieldExtract)}), 0) FROM ${relationFrom}${whereClause()}) AS "${key}"`
449
+ }
450
+ case "relation-sum-expr": {
451
+ const expression = compileExpr(computed.expression)
452
+ return `(SELECT COALESCE(SUM(${expression}), 0) FROM ${relationFrom}${whereClause()}) AS "${key}"`
453
+ }
454
+ case "relation-sum-expr-by": {
455
+ const expression = compileExpr(computed.expression)
456
+ const unitExpr = dialect.jsonExtractElement(relationAlias, computed.unit)
457
+ if (dialect.jsonColumnType === "JSON") {
458
+ 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}"`
459
+ }
460
+ 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}"`
461
+ }
462
+ case "relation-sum-expr-normalized": {
463
+ const expression = compileExpr(computed.expression)
464
+ const unitExpr = dialect.jsonExtractElement(relationAlias, computed.unit)
465
+ const factorExpr = factorCaseExpr(unitExpr, computed.toBase, computed.factors)
466
+ return `(SELECT COALESCE(SUM((${expression}) * (${factorExpr})), 0) FROM ${relationFrom}${whereClause()}) AS "${key}"`
467
+ }
468
+ case "relation-collect": {
469
+ const fieldExtract = dialect.jsonExtractElement(relationAlias, computed.field)
470
+ if (dialect.jsonColumnType === "JSON") {
471
+ // sqlite: json_group_array does not accept DISTINCT; emulate via inner DISTINCT subquery
472
+ if (computed.distinct) {
473
+ return `(SELECT COALESCE(json_group_array(__v), json_array()) FROM (SELECT DISTINCT ${fieldExtract} AS __v FROM ${relationFrom}${whereClause()})) AS "${key}"`
474
+ }
475
+ return `(SELECT COALESCE(json_group_array(${fieldExtract}), json_array()) FROM ${relationFrom}${whereClause()}) AS "${key}"`
476
+ }
477
+ const aggArg = computed.distinct ? `DISTINCT ${fieldExtract}` : fieldExtract
478
+ return `(SELECT COALESCE(jsonb_agg(${aggArg}), '[]'::jsonb) FROM ${relationFrom}${whereClause()}) AS "${key}"`
479
+ }
480
+ case "relation-length": {
481
+ const arrPath = dottedToJsonPath(computed.path)
482
+ return `${dialect.arrayLength(arrPath)} AS "${key}"`
483
+ }
484
+ case "relation-collect-fields": {
485
+ const branches = computed.fields.map((field) => {
486
+ const fieldExtract = dialect.jsonExtractElement(relationAlias, field)
487
+ return `SELECT ${fieldExtract} AS __v FROM ${relationFrom}${whereClause()}`
488
+ })
489
+ const unionQuery = branches.join(" UNION ALL ")
490
+ if (dialect.jsonColumnType === "JSON") {
491
+ if (computed.distinct) {
492
+ return `(SELECT COALESCE(json_group_array(__v), json_array()) FROM (SELECT DISTINCT __v FROM (${unionQuery}))) AS "${key}"`
493
+ }
494
+ return `(SELECT COALESCE(json_group_array(__v), json_array()) FROM (${unionQuery})) AS "${key}"`
495
+ }
496
+ if (computed.distinct) {
497
+ return `(SELECT COALESCE(jsonb_agg(__v), '[]'::jsonb) FROM (SELECT DISTINCT __v FROM (${unionQuery}) inner_q) outer_q) AS "${key}"`
498
+ }
499
+ return `(SELECT COALESCE(jsonb_agg(__v), '[]'::jsonb) FROM (${unionQuery}) t) AS "${key}"`
500
+ }
501
+ default:
502
+ return assertUnreachable(computed)
503
+ }
504
+ }
505
+
506
+ const aggregateSelectExpr = (key: string, agg: AggregateIrExpression): string => {
507
+ switch (agg._tag) {
508
+ case "agg-count":
509
+ return `COUNT(1) AS "${key}"`
510
+ case "agg-count-when": {
511
+ if (agg.filter.length === 0) return `COUNT(1) AS "${key}"`
512
+ const cond = print([{ t: "where-scope", result: agg.filter, relation: "some" }], null, false)
513
+ return `COUNT(CASE WHEN ${cond} THEN 1 END) AS "${key}"`
514
+ }
515
+ case "agg-sum":
516
+ return `COALESCE(SUM(${fieldExpr(agg.field)}), 0) AS "${key}"`
517
+ case "agg-min":
518
+ return `MIN(${fieldExpr(agg.field)}) AS "${key}"`
519
+ case "agg-max":
520
+ return `MAX(${fieldExpr(agg.field)}) AS "${key}"`
521
+ default:
522
+ return assertUnreachable(agg)
523
+ }
524
+ }
525
+
526
+ const hasAggregates = select
527
+ ? select.some((s) => typeof s === "object" && s !== null && "aggregate" in s)
528
+ : false
529
+
530
+ const getSelectExpr = (): string => {
531
+ if (!select) return "id, _etag, data"
532
+ const fields = select.map((s) => {
533
+ if (typeof s === "string") {
534
+ if (s === idKey || s === "id") return `id`
535
+ if (s === "_etag") return `_etag`
536
+ return `${dialect.jsonExtractJson(s)} AS "${s}"`
537
+ }
538
+ if ("computed" in s) {
539
+ return computedSelectExpr(s.key, s.computed)
540
+ }
541
+ if ("aggregate" in s) {
542
+ return aggregateSelectExpr(s.key, s.aggregate)
543
+ }
544
+ if ("path" in s) {
545
+ // Group-by fields: extract as scalar (not JSON-encoded) so grouping works and values compare as plain strings/numbers
546
+ return `${fieldExpr(dottedToJsonPath(s.path))} AS "${s.key}"`
547
+ }
548
+ return `${dialect.jsonExtractJson(s.key)} AS "${s.key}"`
549
+ })
550
+ return fields.join(", ")
551
+ }
552
+
553
+ // Order matters: projection params must be emitted BEFORE user-filter
554
+ // params so positional `?` placeholders in SQLite match `params[]` order.
555
+ const selectExpr = getSelectExpr()
556
+
557
+ const namespaceClause = namespace !== undefined
558
+ ? `_namespace = ${addParam(namespace)}`
559
+ : ""
560
+ const userWhere = filter.length
561
+ ? print([{ t: "where-scope", result: filter, relation: "some" }], null, false)
562
+ : ""
563
+ const whereClause = namespaceClause && userWhere
564
+ ? `WHERE ${namespaceClause} AND ${userWhere}`
565
+ : namespaceClause
566
+ ? `WHERE ${namespaceClause}`
567
+ : userWhere
568
+ ? `WHERE ${userWhere}`
569
+ : ""
570
+
571
+ const groupByClause = hasAggregates && select
572
+ ? (() => {
573
+ const groupByExprs = select
574
+ .filter((s): s is string | { key: string; path: string } =>
575
+ typeof s === "string" || (typeof s === "object" && s !== null && "path" in s)
576
+ )
577
+ .map((s) => typeof s === "string" ? fieldExpr(s) : fieldExpr(dottedToJsonPath(s.path)))
578
+ return groupByExprs.length > 0 ? `GROUP BY ${groupByExprs.join(", ")}` : ""
579
+ })()
580
+ : ""
581
+
582
+ const orderClause = order
583
+ ? `ORDER BY ${
584
+ order
585
+ .map((_) =>
586
+ hasAggregates
587
+ ? `"${_.key}" ${_.direction}`
588
+ : `${fieldExpr(_.key)} ${_.direction}`
589
+ )
590
+ .join(", ")
591
+ }`
592
+ : ""
593
+
594
+ const limitClause = limit !== undefined || skip !== undefined
595
+ ? `LIMIT ${addParam(limit ?? 999999)} OFFSET ${addParam(skip ?? 0)}`
596
+ : ""
597
+
598
+ const sql = `SELECT ${selectExpr} FROM "${tableName}" ${whereClause} ${groupByClause} ${orderClause} ${limitClause}`
599
+ .replace(/\s+/g, " ")
600
+ .trim()
601
+
602
+ return { sql, params }
603
+ }