typhex 0.1.0-alpha.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 (421) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/LICENSE +21 -0
  3. package/README.md +417 -0
  4. package/SECURITY.md +32 -0
  5. package/dist/arrow/aggregates.d.ts +12 -0
  6. package/dist/arrow/aggregates.d.ts.map +1 -0
  7. package/dist/arrow/aggregates.js +32 -0
  8. package/dist/arrow/aggregates.js.map +1 -0
  9. package/dist/arrow/constants.d.ts +15 -0
  10. package/dist/arrow/constants.d.ts.map +1 -0
  11. package/dist/arrow/constants.js +42 -0
  12. package/dist/arrow/constants.js.map +1 -0
  13. package/dist/arrow/index.d.ts +7 -0
  14. package/dist/arrow/index.d.ts.map +1 -0
  15. package/dist/arrow/index.js +7 -0
  16. package/dist/arrow/index.js.map +1 -0
  17. package/dist/config/index.d.ts +6 -0
  18. package/dist/config/index.d.ts.map +1 -0
  19. package/dist/config/index.js +4 -0
  20. package/dist/config/index.js.map +1 -0
  21. package/dist/config/load-config.d.ts +19 -0
  22. package/dist/config/load-config.d.ts.map +1 -0
  23. package/dist/config/load-config.js +84 -0
  24. package/dist/config/load-config.js.map +1 -0
  25. package/dist/config/load-env.d.ts +7 -0
  26. package/dist/config/load-env.d.ts.map +1 -0
  27. package/dist/config/load-env.js +62 -0
  28. package/dist/config/load-env.js.map +1 -0
  29. package/dist/config/types.d.ts +20 -0
  30. package/dist/config/types.d.ts.map +1 -0
  31. package/dist/config/types.js +10 -0
  32. package/dist/config/types.js.map +1 -0
  33. package/dist/dbs/base-migrator.d.ts +20 -0
  34. package/dist/dbs/base-migrator.d.ts.map +1 -0
  35. package/dist/dbs/base-migrator.js +112 -0
  36. package/dist/dbs/base-migrator.js.map +1 -0
  37. package/dist/dbs/index.d.ts +9 -0
  38. package/dist/dbs/index.d.ts.map +1 -0
  39. package/dist/dbs/index.js +17 -0
  40. package/dist/dbs/index.js.map +1 -0
  41. package/dist/dbs/postgres/dialect.d.ts +8 -0
  42. package/dist/dbs/postgres/dialect.d.ts.map +1 -0
  43. package/dist/dbs/postgres/dialect.js +17 -0
  44. package/dist/dbs/postgres/dialect.js.map +1 -0
  45. package/dist/dbs/postgres/driver.d.ts +42 -0
  46. package/dist/dbs/postgres/driver.d.ts.map +1 -0
  47. package/dist/dbs/postgres/driver.js +111 -0
  48. package/dist/dbs/postgres/driver.js.map +1 -0
  49. package/dist/dbs/postgres/index.d.ts +6 -0
  50. package/dist/dbs/postgres/index.d.ts.map +1 -0
  51. package/dist/dbs/postgres/index.js +5 -0
  52. package/dist/dbs/postgres/index.js.map +1 -0
  53. package/dist/dbs/postgres/migrator.d.ts +13 -0
  54. package/dist/dbs/postgres/migrator.d.ts.map +1 -0
  55. package/dist/dbs/postgres/migrator.js +22 -0
  56. package/dist/dbs/postgres/migrator.js.map +1 -0
  57. package/dist/dbs/postgres/query-compiler.d.ts +22 -0
  58. package/dist/dbs/postgres/query-compiler.d.ts.map +1 -0
  59. package/dist/dbs/postgres/query-compiler.js +140 -0
  60. package/dist/dbs/postgres/query-compiler.js.map +1 -0
  61. package/dist/dbs/postgres/trx.d.ts +16 -0
  62. package/dist/dbs/postgres/trx.d.ts.map +1 -0
  63. package/dist/dbs/postgres/trx.js +68 -0
  64. package/dist/dbs/postgres/trx.js.map +1 -0
  65. package/dist/dbs/query-compiler.d.ts +135 -0
  66. package/dist/dbs/query-compiler.d.ts.map +1 -0
  67. package/dist/dbs/query-compiler.js +775 -0
  68. package/dist/dbs/query-compiler.js.map +1 -0
  69. package/dist/dbs/sqlite/dialect.d.ts +8 -0
  70. package/dist/dbs/sqlite/dialect.d.ts.map +1 -0
  71. package/dist/dbs/sqlite/dialect.js +17 -0
  72. package/dist/dbs/sqlite/dialect.js.map +1 -0
  73. package/dist/dbs/sqlite/driver.d.ts +9 -0
  74. package/dist/dbs/sqlite/driver.d.ts.map +1 -0
  75. package/dist/dbs/sqlite/driver.js +66 -0
  76. package/dist/dbs/sqlite/driver.js.map +1 -0
  77. package/dist/dbs/sqlite/index.d.ts +6 -0
  78. package/dist/dbs/sqlite/index.d.ts.map +1 -0
  79. package/dist/dbs/sqlite/index.js +5 -0
  80. package/dist/dbs/sqlite/index.js.map +1 -0
  81. package/dist/dbs/sqlite/migrator.d.ts +13 -0
  82. package/dist/dbs/sqlite/migrator.d.ts.map +1 -0
  83. package/dist/dbs/sqlite/migrator.js +22 -0
  84. package/dist/dbs/sqlite/migrator.js.map +1 -0
  85. package/dist/dbs/sqlite/query-compiler.d.ts +26 -0
  86. package/dist/dbs/sqlite/query-compiler.d.ts.map +1 -0
  87. package/dist/dbs/sqlite/query-compiler.js +80 -0
  88. package/dist/dbs/sqlite/query-compiler.js.map +1 -0
  89. package/dist/dbs/sqlite/trx.d.ts +13 -0
  90. package/dist/dbs/sqlite/trx.d.ts.map +1 -0
  91. package/dist/dbs/sqlite/trx.js +69 -0
  92. package/dist/dbs/sqlite/trx.js.map +1 -0
  93. package/dist/dbs/types.d.ts +92 -0
  94. package/dist/dbs/types.d.ts.map +1 -0
  95. package/dist/dbs/types.js +26 -0
  96. package/dist/dbs/types.js.map +1 -0
  97. package/dist/dialect.d.ts +3 -0
  98. package/dist/dialect.d.ts.map +1 -0
  99. package/dist/dialect.js +2 -0
  100. package/dist/dialect.js.map +1 -0
  101. package/dist/driver/factory.d.ts +19 -0
  102. package/dist/driver/factory.d.ts.map +1 -0
  103. package/dist/driver/factory.js +24 -0
  104. package/dist/driver/factory.js.map +1 -0
  105. package/dist/driver/index.d.ts +6 -0
  106. package/dist/driver/index.d.ts.map +1 -0
  107. package/dist/driver/index.js +3 -0
  108. package/dist/driver/index.js.map +1 -0
  109. package/dist/driver/sqlite.d.ts +15 -0
  110. package/dist/driver/sqlite.d.ts.map +1 -0
  111. package/dist/driver/sqlite.js +74 -0
  112. package/dist/driver/sqlite.js.map +1 -0
  113. package/dist/driver/types.d.ts +75 -0
  114. package/dist/driver/types.d.ts.map +1 -0
  115. package/dist/driver/types.js +2 -0
  116. package/dist/driver/types.js.map +1 -0
  117. package/dist/entity/entity.d.ts +67 -0
  118. package/dist/entity/entity.d.ts.map +1 -0
  119. package/dist/entity/entity.js +139 -0
  120. package/dist/entity/entity.js.map +1 -0
  121. package/dist/entity/global-driver.d.ts +38 -0
  122. package/dist/entity/global-driver.d.ts.map +1 -0
  123. package/dist/entity/global-driver.js +109 -0
  124. package/dist/entity/global-driver.js.map +1 -0
  125. package/dist/entity/index.d.ts +8 -0
  126. package/dist/entity/index.d.ts.map +1 -0
  127. package/dist/entity/index.js +3 -0
  128. package/dist/entity/index.js.map +1 -0
  129. package/dist/entity/pk-columns.d.ts +5 -0
  130. package/dist/entity/pk-columns.d.ts.map +1 -0
  131. package/dist/entity/pk-columns.js +14 -0
  132. package/dist/entity/pk-columns.js.map +1 -0
  133. package/dist/entity/relations.d.ts +134 -0
  134. package/dist/entity/relations.d.ts.map +1 -0
  135. package/dist/entity/relations.js +23 -0
  136. package/dist/entity/relations.js.map +1 -0
  137. package/dist/entity/schema-inference.d.ts +77 -0
  138. package/dist/entity/schema-inference.d.ts.map +1 -0
  139. package/dist/entity/schema-inference.js +6 -0
  140. package/dist/entity/schema-inference.js.map +1 -0
  141. package/dist/entity/types.d.ts +30 -0
  142. package/dist/entity/types.d.ts.map +1 -0
  143. package/dist/entity/types.js +5 -0
  144. package/dist/entity/types.js.map +1 -0
  145. package/dist/index.d.ts +25 -0
  146. package/dist/index.d.ts.map +1 -0
  147. package/dist/index.js +12 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/ir/index.d.ts +2 -0
  150. package/dist/ir/index.d.ts.map +1 -0
  151. package/dist/ir/index.js +2 -0
  152. package/dist/ir/index.js.map +1 -0
  153. package/dist/ir/types.d.ts +148 -0
  154. package/dist/ir/types.d.ts.map +1 -0
  155. package/dist/ir/types.js +97 -0
  156. package/dist/ir/types.js.map +1 -0
  157. package/dist/migration/cli.d.ts +18 -0
  158. package/dist/migration/cli.d.ts.map +1 -0
  159. package/dist/migration/cli.js +236 -0
  160. package/dist/migration/cli.js.map +1 -0
  161. package/dist/migration/diff.d.ts +10 -0
  162. package/dist/migration/diff.d.ts.map +1 -0
  163. package/dist/migration/diff.js +10 -0
  164. package/dist/migration/diff.js.map +1 -0
  165. package/dist/migration/generator.d.ts +12 -0
  166. package/dist/migration/generator.d.ts.map +1 -0
  167. package/dist/migration/generator.js +98 -0
  168. package/dist/migration/generator.js.map +1 -0
  169. package/dist/migration/index.d.ts +7 -0
  170. package/dist/migration/index.d.ts.map +1 -0
  171. package/dist/migration/index.js +5 -0
  172. package/dist/migration/index.js.map +1 -0
  173. package/dist/migration/runner.d.ts +32 -0
  174. package/dist/migration/runner.d.ts.map +1 -0
  175. package/dist/migration/runner.js +279 -0
  176. package/dist/migration/runner.js.map +1 -0
  177. package/dist/migration/topo-sort.d.ts +12 -0
  178. package/dist/migration/topo-sort.d.ts.map +1 -0
  179. package/dist/migration/topo-sort.js +42 -0
  180. package/dist/migration/topo-sort.js.map +1 -0
  181. package/dist/migration/types.d.ts +45 -0
  182. package/dist/migration/types.d.ts.map +1 -0
  183. package/dist/migration/types.js +2 -0
  184. package/dist/migration/types.js.map +1 -0
  185. package/dist/orm/aggregates.d.ts +19 -0
  186. package/dist/orm/aggregates.d.ts.map +1 -0
  187. package/dist/orm/aggregates.js +32 -0
  188. package/dist/orm/aggregates.js.map +1 -0
  189. package/dist/orm/db.d.ts +105 -0
  190. package/dist/orm/db.d.ts.map +1 -0
  191. package/dist/orm/db.js +172 -0
  192. package/dist/orm/db.js.map +1 -0
  193. package/dist/orm/expr.d.ts +125 -0
  194. package/dist/orm/expr.d.ts.map +1 -0
  195. package/dist/orm/expr.js +10 -0
  196. package/dist/orm/expr.js.map +1 -0
  197. package/dist/orm/helpers/insert-graph/insert-graph-batch-executor.d.ts +9 -0
  198. package/dist/orm/helpers/insert-graph/insert-graph-batch-executor.d.ts.map +1 -0
  199. package/dist/orm/helpers/insert-graph/insert-graph-batch-executor.js +44 -0
  200. package/dist/orm/helpers/insert-graph/insert-graph-batch-executor.js.map +1 -0
  201. package/dist/orm/helpers/insert-graph/insert-graph-executor.d.ts +13 -0
  202. package/dist/orm/helpers/insert-graph/insert-graph-executor.d.ts.map +1 -0
  203. package/dist/orm/helpers/insert-graph/insert-graph-executor.js +42 -0
  204. package/dist/orm/helpers/insert-graph/insert-graph-executor.js.map +1 -0
  205. package/dist/orm/helpers/insert-graph/insert-graph-planner.d.ts +46 -0
  206. package/dist/orm/helpers/insert-graph/insert-graph-planner.d.ts.map +1 -0
  207. package/dist/orm/helpers/insert-graph/insert-graph-planner.js +258 -0
  208. package/dist/orm/helpers/insert-graph/insert-graph-planner.js.map +1 -0
  209. package/dist/orm/helpers/insert-graph/insert-graph-sequential-executor.d.ts +7 -0
  210. package/dist/orm/helpers/insert-graph/insert-graph-sequential-executor.d.ts.map +1 -0
  211. package/dist/orm/helpers/insert-graph/insert-graph-sequential-executor.js +8 -0
  212. package/dist/orm/helpers/insert-graph/insert-graph-sequential-executor.js.map +1 -0
  213. package/dist/orm/helpers/insert-graph/sequence-id-assigner.d.ts +15 -0
  214. package/dist/orm/helpers/insert-graph/sequence-id-assigner.d.ts.map +1 -0
  215. package/dist/orm/helpers/insert-graph/sequence-id-assigner.js +48 -0
  216. package/dist/orm/helpers/insert-graph/sequence-id-assigner.js.map +1 -0
  217. package/dist/orm/helpers/query-plan/expr-builder.d.ts +155 -0
  218. package/dist/orm/helpers/query-plan/expr-builder.d.ts.map +1 -0
  219. package/dist/orm/helpers/query-plan/expr-builder.js +297 -0
  220. package/dist/orm/helpers/query-plan/expr-builder.js.map +1 -0
  221. package/dist/orm/helpers/query-plan/query-ir-analyzer.d.ts +48 -0
  222. package/dist/orm/helpers/query-plan/query-ir-analyzer.d.ts.map +1 -0
  223. package/dist/orm/helpers/query-plan/query-ir-analyzer.js +262 -0
  224. package/dist/orm/helpers/query-plan/query-ir-analyzer.js.map +1 -0
  225. package/dist/orm/helpers/query-plan/query-plan.d.ts +164 -0
  226. package/dist/orm/helpers/query-plan/query-plan.d.ts.map +1 -0
  227. package/dist/orm/helpers/query-plan/query-plan.js +549 -0
  228. package/dist/orm/helpers/query-plan/query-plan.js.map +1 -0
  229. package/dist/orm/helpers/query-plan/select-classifier.d.ts +161 -0
  230. package/dist/orm/helpers/query-plan/select-classifier.d.ts.map +1 -0
  231. package/dist/orm/helpers/query-plan/select-classifier.js +359 -0
  232. package/dist/orm/helpers/query-plan/select-classifier.js.map +1 -0
  233. package/dist/orm/helpers/relations/relation-assembler.d.ts +21 -0
  234. package/dist/orm/helpers/relations/relation-assembler.d.ts.map +1 -0
  235. package/dist/orm/helpers/relations/relation-assembler.js +60 -0
  236. package/dist/orm/helpers/relations/relation-assembler.js.map +1 -0
  237. package/dist/orm/helpers/relations/relation-fetcher.d.ts +30 -0
  238. package/dist/orm/helpers/relations/relation-fetcher.d.ts.map +1 -0
  239. package/dist/orm/helpers/relations/relation-fetcher.js +128 -0
  240. package/dist/orm/helpers/relations/relation-fetcher.js.map +1 -0
  241. package/dist/orm/helpers/relations/relation-joins.d.ts +74 -0
  242. package/dist/orm/helpers/relations/relation-joins.d.ts.map +1 -0
  243. package/dist/orm/helpers/relations/relation-joins.js +138 -0
  244. package/dist/orm/helpers/relations/relation-joins.js.map +1 -0
  245. package/dist/orm/helpers/relations/relation-resolver.d.ts +14 -0
  246. package/dist/orm/helpers/relations/relation-resolver.d.ts.map +1 -0
  247. package/dist/orm/helpers/relations/relation-resolver.js +25 -0
  248. package/dist/orm/helpers/relations/relation-resolver.js.map +1 -0
  249. package/dist/orm/index.d.ts +7 -0
  250. package/dist/orm/index.d.ts.map +1 -0
  251. package/dist/orm/index.js +5 -0
  252. package/dist/orm/index.js.map +1 -0
  253. package/dist/orm/query-builder.d.ts +136 -0
  254. package/dist/orm/query-builder.d.ts.map +1 -0
  255. package/dist/orm/query-builder.js +433 -0
  256. package/dist/orm/query-builder.js.map +1 -0
  257. package/dist/orm/query-helpers.d.ts +35 -0
  258. package/dist/orm/query-helpers.d.ts.map +1 -0
  259. package/dist/orm/query-helpers.js +83 -0
  260. package/dist/orm/query-helpers.js.map +1 -0
  261. package/dist/orm/query-state.d.ts +56 -0
  262. package/dist/orm/query-state.d.ts.map +1 -0
  263. package/dist/orm/query-state.js +112 -0
  264. package/dist/orm/query-state.js.map +1 -0
  265. package/dist/orm/single-row-query-builder.d.ts +18 -0
  266. package/dist/orm/single-row-query-builder.d.ts.map +1 -0
  267. package/dist/orm/single-row-query-builder.js +90 -0
  268. package/dist/orm/single-row-query-builder.js.map +1 -0
  269. package/dist/orm/trx.d.ts +40 -0
  270. package/dist/orm/trx.d.ts.map +1 -0
  271. package/dist/orm/trx.js +118 -0
  272. package/dist/orm/trx.js.map +1 -0
  273. package/dist/parser/acorn-helpers.d.ts +43 -0
  274. package/dist/parser/acorn-helpers.d.ts.map +1 -0
  275. package/dist/parser/acorn-helpers.js +104 -0
  276. package/dist/parser/acorn-helpers.js.map +1 -0
  277. package/dist/parser/acorn-member.d.ts +16 -0
  278. package/dist/parser/acorn-member.d.ts.map +1 -0
  279. package/dist/parser/acorn-member.js +31 -0
  280. package/dist/parser/acorn-member.js.map +1 -0
  281. package/dist/parser/acorn-types.d.ts +14 -0
  282. package/dist/parser/acorn-types.d.ts.map +1 -0
  283. package/dist/parser/acorn-types.js +6 -0
  284. package/dist/parser/acorn-types.js.map +1 -0
  285. package/dist/parser/arrow-source.d.ts +23 -0
  286. package/dist/parser/arrow-source.d.ts.map +1 -0
  287. package/dist/parser/arrow-source.js +70 -0
  288. package/dist/parser/arrow-source.js.map +1 -0
  289. package/dist/parser/group-by.d.ts +17 -0
  290. package/dist/parser/group-by.d.ts.map +1 -0
  291. package/dist/parser/group-by.js +62 -0
  292. package/dist/parser/group-by.js.map +1 -0
  293. package/dist/parser/index.d.ts +5 -0
  294. package/dist/parser/index.d.ts.map +1 -0
  295. package/dist/parser/index.js +3 -0
  296. package/dist/parser/index.js.map +1 -0
  297. package/dist/parser/parse-arrow.d.ts +10 -0
  298. package/dist/parser/parse-arrow.d.ts.map +1 -0
  299. package/dist/parser/parse-arrow.js +9 -0
  300. package/dist/parser/parse-arrow.js.map +1 -0
  301. package/dist/parser/predicate-walk.d.ts +24 -0
  302. package/dist/parser/predicate-walk.d.ts.map +1 -0
  303. package/dist/parser/predicate-walk.js +247 -0
  304. package/dist/parser/predicate-walk.js.map +1 -0
  305. package/dist/parser/resolve.d.ts +25 -0
  306. package/dist/parser/resolve.d.ts.map +1 -0
  307. package/dist/parser/resolve.js +134 -0
  308. package/dist/parser/resolve.js.map +1 -0
  309. package/dist/parser/select.d.ts +7 -0
  310. package/dist/parser/select.d.ts.map +1 -0
  311. package/dist/parser/select.js +333 -0
  312. package/dist/parser/select.js.map +1 -0
  313. package/dist/parser/update.d.ts +7 -0
  314. package/dist/parser/update.d.ts.map +1 -0
  315. package/dist/parser/update.js +51 -0
  316. package/dist/parser/update.js.map +1 -0
  317. package/dist/postgres/aggregates.d.ts +12 -0
  318. package/dist/postgres/aggregates.d.ts.map +1 -0
  319. package/dist/postgres/aggregates.js +19 -0
  320. package/dist/postgres/aggregates.js.map +1 -0
  321. package/dist/postgres.d.ts +6 -0
  322. package/dist/postgres.d.ts.map +1 -0
  323. package/dist/postgres.js +6 -0
  324. package/dist/postgres.js.map +1 -0
  325. package/dist/schema/index.d.ts +2 -0
  326. package/dist/schema/index.d.ts.map +1 -0
  327. package/dist/schema/index.js +2 -0
  328. package/dist/schema/index.js.map +1 -0
  329. package/dist/schema/types.d.ts +16 -0
  330. package/dist/schema/types.d.ts.map +1 -0
  331. package/dist/schema/types.js +40 -0
  332. package/dist/schema/types.js.map +1 -0
  333. package/dist/sqlite/aggregates.d.ts +8 -0
  334. package/dist/sqlite/aggregates.d.ts.map +1 -0
  335. package/dist/sqlite/aggregates.js +11 -0
  336. package/dist/sqlite/aggregates.js.map +1 -0
  337. package/dist/sqlite.d.ts +6 -0
  338. package/dist/sqlite.d.ts.map +1 -0
  339. package/dist/sqlite.js +6 -0
  340. package/dist/sqlite.js.map +1 -0
  341. package/dist/transformer/bindings.d.ts +18 -0
  342. package/dist/transformer/bindings.d.ts.map +1 -0
  343. package/dist/transformer/bindings.js +52 -0
  344. package/dist/transformer/bindings.js.map +1 -0
  345. package/dist/transformer/index.d.ts +17 -0
  346. package/dist/transformer/index.d.ts.map +1 -0
  347. package/dist/transformer/index.js +75 -0
  348. package/dist/transformer/index.js.map +1 -0
  349. package/dist/transformer/ir-emit.d.ts +12 -0
  350. package/dist/transformer/ir-emit.d.ts.map +1 -0
  351. package/dist/transformer/ir-emit.js +144 -0
  352. package/dist/transformer/ir-emit.js.map +1 -0
  353. package/dist/transformer/join-transformer.d.ts +12 -0
  354. package/dist/transformer/join-transformer.d.ts.map +1 -0
  355. package/dist/transformer/join-transformer.js +102 -0
  356. package/dist/transformer/join-transformer.js.map +1 -0
  357. package/dist/transformer/orderby-transformer.d.ts +13 -0
  358. package/dist/transformer/orderby-transformer.d.ts.map +1 -0
  359. package/dist/transformer/orderby-transformer.js +84 -0
  360. package/dist/transformer/orderby-transformer.js.map +1 -0
  361. package/dist/transformer/select-transformer.d.ts +9 -0
  362. package/dist/transformer/select-transformer.d.ts.map +1 -0
  363. package/dist/transformer/select-transformer.js +222 -0
  364. package/dist/transformer/select-transformer.js.map +1 -0
  365. package/dist/transformer/shared.d.ts +12 -0
  366. package/dist/transformer/shared.d.ts.map +1 -0
  367. package/dist/transformer/shared.js +12 -0
  368. package/dist/transformer/shared.js.map +1 -0
  369. package/dist/transformer/subquery-transformer.d.ts +15 -0
  370. package/dist/transformer/subquery-transformer.d.ts.map +1 -0
  371. package/dist/transformer/subquery-transformer.js +43 -0
  372. package/dist/transformer/subquery-transformer.js.map +1 -0
  373. package/dist/transformer/ts-aggregates.d.ts +13 -0
  374. package/dist/transformer/ts-aggregates.d.ts.map +1 -0
  375. package/dist/transformer/ts-aggregates.js +83 -0
  376. package/dist/transformer/ts-aggregates.js.map +1 -0
  377. package/dist/transformer/ts-binary.d.ts +8 -0
  378. package/dist/transformer/ts-binary.d.ts.map +1 -0
  379. package/dist/transformer/ts-binary.js +32 -0
  380. package/dist/transformer/ts-binary.js.map +1 -0
  381. package/dist/transformer/ts-member.d.ts +12 -0
  382. package/dist/transformer/ts-member.d.ts.map +1 -0
  383. package/dist/transformer/ts-member.js +22 -0
  384. package/dist/transformer/ts-member.js.map +1 -0
  385. package/dist/transformer/ts-utils.d.ts +10 -0
  386. package/dist/transformer/ts-utils.d.ts.map +1 -0
  387. package/dist/transformer/ts-utils.js +38 -0
  388. package/dist/transformer/ts-utils.js.map +1 -0
  389. package/dist/transformer/typhex-type.d.ts +8 -0
  390. package/dist/transformer/typhex-type.d.ts.map +1 -0
  391. package/dist/transformer/typhex-type.js +52 -0
  392. package/dist/transformer/typhex-type.js.map +1 -0
  393. package/dist/transformer/where-transformer.d.ts +33 -0
  394. package/dist/transformer/where-transformer.d.ts.map +1 -0
  395. package/dist/transformer/where-transformer.js +400 -0
  396. package/dist/transformer/where-transformer.js.map +1 -0
  397. package/dist/utils.d.ts +5 -0
  398. package/dist/utils.d.ts.map +1 -0
  399. package/dist/utils.js +30 -0
  400. package/dist/utils.js.map +1 -0
  401. package/docs/drivers/postgres.md +54 -0
  402. package/docs/drivers/sqlite.md +33 -0
  403. package/docs/guide/aggregations.md +272 -0
  404. package/docs/guide/bulk-operations.md +204 -0
  405. package/docs/guide/cte-and-unions.md +270 -0
  406. package/docs/guide/entities-relations.md +208 -0
  407. package/docs/guide/expressions.md +98 -0
  408. package/docs/guide/filtering-by-relations.md +166 -0
  409. package/docs/guide/getting-started.md +277 -0
  410. package/docs/guide/querying-relations.md +133 -0
  411. package/docs/guide/subqueries.md +152 -0
  412. package/docs/guide/transactions.md +146 -0
  413. package/docs/guide/typescript-transformer.md +138 -0
  414. package/docs/index.md +33 -0
  415. package/docs/migrations/overview.md +143 -0
  416. package/docs/public-api.md +133 -0
  417. package/docs/reference/api.md +665 -0
  418. package/docs/reference/architecture.md +83 -0
  419. package/docs/release-checklist.md +55 -0
  420. package/etc/typhex.api.md +774 -0
  421. package/package.json +137 -0
@@ -0,0 +1,270 @@
1
+ # CTEs and Unions
2
+
3
+ Common table expressions let you name an inner query and reuse it from an outer query. Typhex exposes them through `.withCte()`, `.withRecursiveCte()`, `.from()`, and `.unionAll()`.
4
+
5
+ ## Basic CTE
6
+
7
+ Register a query with `.withCte(name, query)`, then read from it with `.from(name)`:
8
+
9
+ ```ts
10
+ const adults = User.query().where((u) => u.age >= 18);
11
+
12
+ const workingAge = await User.query()
13
+ .withCte("adults", adults)
14
+ .from("adults")
15
+ .where((u) => u.age < 65)
16
+ .toArray();
17
+ ```
18
+
19
+ ```sql
20
+ WITH "adults" AS (
21
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
22
+ FROM "users" AS "t0"
23
+ WHERE ("t0"."age" >= ?)
24
+ )
25
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
26
+ FROM "adults" AS "t0"
27
+ WHERE ("t0"."age" < ?)
28
+ -- params: [18, 65]
29
+ ```
30
+
31
+ ## Referencing Earlier CTEs
32
+
33
+ Later CTEs can read from earlier CTEs by using `.from("earlier_name")`:
34
+
35
+ ```ts
36
+ const adults = User.query().where((u) => u.age >= 18);
37
+ const ukAdults = User.query()
38
+ .from("adults")
39
+ .where((u) => u.country === "UK");
40
+
41
+ const rows = await User.query()
42
+ .withCte("adults", adults)
43
+ .withCte("uk_adults", ukAdults)
44
+ .from("uk_adults")
45
+ .toArray();
46
+ ```
47
+
48
+ ```sql
49
+ WITH "adults" AS (
50
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
51
+ FROM "users" AS "t0"
52
+ WHERE ("t0"."age" >= ?)
53
+ ), "uk_adults" AS (
54
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
55
+ FROM "adults" AS "t0"
56
+ WHERE ("t0"."country" = ?)
57
+ )
58
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
59
+ FROM "uk_adults" AS "t0"
60
+ WHERE 1=1
61
+ -- params: [18, "UK"]
62
+ ```
63
+
64
+ Use this when the later CTE is a filtered subset of an earlier one. The inner query reads directly from the earlier CTE name.
65
+
66
+ ## Correlating with `ctes.*` in WHERE
67
+
68
+ Sometimes the later CTE should scan the **base entity table** and correlate to an earlier CTE in `WHERE`, instead of using `.from("earlier_name")`. Typhex exposes earlier registered CTEs through a `ctes` context.
69
+
70
+ Typical shape:
71
+
72
+ ```ts
73
+ const adults = User.query().where((u) => u.age >= 18);
74
+
75
+ await User.query()
76
+ .withCte("adults", adults)
77
+ .withCte("uk_adults", (ctes) =>
78
+ User.query().where((u) => u.country === "UK" && u.id === ctes.adults.id),
79
+ )
80
+ .from("uk_adults")
81
+ .toArray();
82
+ ```
83
+
84
+ ```sql
85
+ WITH "adults" AS (
86
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
87
+ FROM "users" AS "t0"
88
+ WHERE ("t0"."age" >= ?)
89
+ ), "uk_adults" AS (
90
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
91
+ FROM "users" AS "t0", "adults"
92
+ WHERE ("t0"."country" = ?) AND ("t0"."id" = "adults"."id")
93
+ )
94
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
95
+ FROM "uk_adults" AS "t0"
96
+ WHERE 1=1
97
+ -- params: [18, "UK"]
98
+ ```
99
+
100
+ The important difference from `.from("adults")`:
101
+
102
+ | Approach | Inner `FROM` | Typical use |
103
+ | -------------------------- | ------------------------ | --------------------------------------------------- |
104
+ | `.from("adults")` | `"adults"` | Filter rows already materialized in the earlier CTE |
105
+ | `ctes.adults.*` in `WHERE` | base table + earlier CTE | Match base-table rows against earlier CTE rows |
106
+
107
+ ### Transformer: `ctes.*` in a single-arg `where`
108
+
109
+ When the Typhex transformer is enabled, reference earlier CTE columns directly inside a one-argument `where()` lambda. The transformer captures `ctes` from the `.withCte()` callback:
110
+
111
+ ```ts
112
+ .withCte("uk_adults", (ctes) =>
113
+ User.query().where((u) => u.country === "UK" && u.id === ctes.adults.id),
114
+ )
115
+ ```
116
+
117
+ This is the pattern used in `examples/cte/cte.ts` section 3b.
118
+
119
+ ### Runtime: two-arg `where((row, ctes) => ...)`
120
+
121
+ Without the transformer, pass the `ctes` object explicitly as the second parameter to `where()`. This works when building a later CTE body and when correlating mutations on the outer builder:
122
+
123
+ ```ts
124
+ // Later CTE body — runtime-friendly
125
+ .withCte("uk_adults", () =>
126
+ User.query().where(
127
+ (u, ctes) => u.country === "UK" && u.id === ctes.adults.id,
128
+ ),
129
+ )
130
+
131
+ // Outer UPDATE/DELETE on the same builder
132
+ await User.query()
133
+ .withCte("adults", adults)
134
+ .where((u, ctes) => u.age === 35 && u.id === ctes.adults.id)
135
+ .update({ name: "Robert" });
136
+ ```
137
+
138
+ ```sql
139
+ WITH "adults" AS (
140
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
141
+ FROM "users" AS "t0"
142
+ WHERE ("t0"."age" >= ?)
143
+ )
144
+ UPDATE "users" AS "t0"
145
+ SET "name" = ?
146
+ FROM "adults"
147
+ WHERE ("t0"."age" = ?) AND ("t0"."id" = "adults"."id")
148
+ -- params: [18, "Robert", 35]
149
+ ```
150
+
151
+ The two-arg form is the reliable way to correlate registered CTEs at runtime. The single-arg `ctes.adults.id` form inside a `.withCte()` callback requires the transformer.
152
+
153
+ ## `UNION ALL`
154
+
155
+ Use `.unionAll()` to combine compatible SELECT branches, often inside a CTE:
156
+
157
+ ```ts
158
+ const young = User.query().where((u) => u.age < 25);
159
+ const senior = User.query().where((u) => u.age >= 65);
160
+
161
+ const rows = await User.query()
162
+ .withCte("ends", young.unionAll(senior))
163
+ .from("ends")
164
+ .orderBy("name", "asc")
165
+ .toArray();
166
+ ```
167
+
168
+ ```sql
169
+ WITH "ends" AS (
170
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
171
+ FROM "users" AS "t0"
172
+ WHERE ("t0"."age" < ?)
173
+ UNION ALL
174
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
175
+ FROM "users" AS "t0"
176
+ WHERE ("t0"."age" >= ?)
177
+ )
178
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
179
+ FROM "ends" AS "t0"
180
+ WHERE 1=1
181
+ ORDER BY "t0"."name" ASC
182
+ -- params: [25, 65]
183
+ ```
184
+
185
+ ## Recursive CTEs
186
+
187
+ Recursive CTEs combine an anchor query with a recursive branch. The recursive branch refers to the CTE name via `.from(name)`:
188
+
189
+ ```ts
190
+ const anchor = Category.query().where((c) => c.parentId === null);
191
+ const recursive = Category.query()
192
+ .from("tree")
193
+ .innerJoin(Category, (child, parent) => child.parentId === parent.id);
194
+
195
+ const tree = await Category.query()
196
+ .withRecursiveCte("tree", anchor.unionAll(recursive))
197
+ .from("tree")
198
+ .toArray();
199
+ ```
200
+
201
+ ```sql
202
+ WITH RECURSIVE "tree" AS (
203
+ SELECT "t0"."id", "t0"."name", "t0"."parentId"
204
+ FROM "categories" AS "t0"
205
+ WHERE ("t0"."parentId" IS NULL)
206
+ UNION ALL
207
+ SELECT "t0"."id", "t0"."name", "t0"."parentId"
208
+ FROM "tree" AS "t0"
209
+ INNER JOIN "categories" AS "t1"
210
+ ON ("t1"."parentId" = "t0"."id")
211
+ )
212
+ SELECT "t0"."id", "t0"."name", "t0"."parentId"
213
+ FROM "tree" AS "t0"
214
+ WHERE 1=1
215
+ ```
216
+
217
+ Entity-table joins such as `.innerJoin(Category, on)` are useful in recursive branches and self-joins.
218
+
219
+ ## CTEs with Mutations
220
+
221
+ Registered CTEs can also constrain updates and deletes on the outer builder. Use the two-argument `where((row, ctes) => ...)` form to correlate the mutation target to a registered CTE:
222
+
223
+ ```ts
224
+ const adults = User.query().where((u) => u.age >= 18);
225
+
226
+ await User.query()
227
+ .withCte("adults", adults)
228
+ .where((u, ctes) => u.id === ctes.adults.id && u.age === 35)
229
+ .update({ name: "Robert" });
230
+ ```
231
+
232
+ ```sql
233
+ WITH "adults" AS (
234
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
235
+ FROM "users" AS "t0"
236
+ WHERE ("t0"."age" >= ?)
237
+ )
238
+ UPDATE "users" AS "t0"
239
+ SET "name" = ?
240
+ FROM "adults"
241
+ WHERE ("t0"."age" = ?) AND ("t0"."id" = "adults"."id")
242
+ -- params: [18, "Robert", 35]
243
+ ```
244
+
245
+ For deletes, Typhex correlates through `EXISTS`:
246
+
247
+ ```ts
248
+ const ukAdults = User.query().where((u) => u.country === "UK" && u.age >= 18);
249
+
250
+ await User.query()
251
+ .withCte("uk_adults", ukAdults)
252
+ .where((u, ctes) => u.age >= 65 && u.id === ctes.uk_adults.id)
253
+ .delete();
254
+ ```
255
+
256
+ ```sql
257
+ WITH "uk_adults" AS (
258
+ SELECT "t0"."id", "t0"."name", "t0"."age", "t0"."country"
259
+ FROM "users" AS "t0"
260
+ WHERE (("t0"."country" = ?) AND ("t0"."age" >= ?))
261
+ )
262
+ DELETE FROM "users" AS "t0"
263
+ WHERE EXISTS (
264
+ SELECT 1 FROM "uk_adults"
265
+ WHERE ("t0"."age" >= ?) AND ("t0"."id" = "uk_adults"."id")
266
+ )
267
+ -- params: ["UK", 18, 65]
268
+ ```
269
+
270
+ See the [API reference](/reference/api#withcte-name-query) for method signatures and run `npm run cte` from `examples/` for end-to-end output.
@@ -0,0 +1,208 @@
1
+ # Entities & Relations
2
+
3
+ ## The `Entity()` Factory
4
+
5
+ `Entity()` creates a base class for a database table. The second argument is the schema — a map from column name to SQL type string.
6
+
7
+ ```ts
8
+ import { Entity, rel } from "typhex";
9
+
10
+ const User = Entity("users", {
11
+ id: "integer primary key autoincrement",
12
+ name: "text not null",
13
+ email: "text",
14
+ age: "integer",
15
+ createdAt: "datetime not null",
16
+ });
17
+ ```
18
+
19
+ TypeScript infers the row shape from the schema, so `User` instances are typed — no separate interface declaration required.
20
+
21
+ ## Defining Relations
22
+
23
+ Pass a third argument to `Entity()` to declare relations. Use the `rel` helper:
24
+
25
+ ```ts
26
+ const Post = Entity(
27
+ "posts",
28
+ {
29
+ id: "integer primary key autoincrement",
30
+ title: "text not null",
31
+ authorId: "integer not null",
32
+ createdAt: "datetime not null",
33
+ },
34
+ {
35
+ author: rel.manyToOne(() => User, { foreignKey: "authorId" }), // [!code highlight]
36
+ },
37
+ );
38
+ ```
39
+
40
+ The target entity is passed as a thunk (`() => User`) to allow forward-references when entities are defined in separate files or have circular references.
41
+
42
+ ### Relation helpers
43
+
44
+ | Helper | Direction | What it means |
45
+ | ---------------------------------------------------------------------- | --------- | -------------------------------------------- |
46
+ | `rel.manyToOne(() => Target, { foreignKey })` | N:1 | This table holds the foreign key |
47
+ | `rel.oneToMany(() => Target, { foreignKey })` | 1:N | The other table holds the foreign key |
48
+ | `rel.oneToOne(() => Target, { foreignKey })` | 1:1 | FK on this table; loads a single related row |
49
+ | `rel.manyToMany(() => Target, { junction, foreignKey, referenceKey })` | M:N | Via a junction table |
50
+
51
+ ## One-to-One Relations
52
+
53
+ Use `rel.oneToOne()` when each row has at most one related row. The FK lives on this entity's table:
54
+
55
+ ```ts
56
+ const UserProfile = Entity("user_profiles", {
57
+ id: "integer primary key autoincrement",
58
+ userId: "integer not null unique",
59
+ bio: "text",
60
+ });
61
+
62
+ const User = Entity(
63
+ "users",
64
+ { id: "integer primary key autoincrement", name: "text not null" },
65
+ { profile: rel.oneToOne(() => UserProfile, { foreignKey: "userId" }) },
66
+ );
67
+
68
+ // Load the profile alongside the user
69
+ const users = await User.query()
70
+ .select((u) => ({ id: u.id, name: u.name, profile: u.profile }))
71
+ .toArray();
72
+ ```
73
+
74
+ ```sql
75
+ -- 1. Main query
76
+ SELECT id AS id, name AS name FROM users
77
+
78
+ -- 2. Relation fetch (one round-trip, regardless of result count)
79
+ SELECT id, userId, bio FROM user_profiles WHERE userId IN (?, ?, ...)
80
+ ```
81
+
82
+ ## Many-to-Many Relations
83
+
84
+ A `manyToMany` relation works through a junction table that you manage directly in SQL (Typhex doesn't auto-migrate junction tables):
85
+
86
+ ```ts
87
+ import { Entity, rel, type ManyToMany } from "typhex";
88
+ import { Tag } from "./tag.js";
89
+
90
+ export class Post extends Entity(
91
+ "posts",
92
+ { id: "integer primary key autoincrement", title: "text not null" },
93
+ {
94
+ tags: rel.manyToMany(() => Tag, {
95
+ junction: "post_tags", // junction table name
96
+ foreignKey: "postId", // column pointing to this entity
97
+ referenceKey: "tagId", // column pointing to the target
98
+ }),
99
+ },
100
+ ) {
101
+ declare tags: ManyToMany<Tag>; // needed when Post and Tag are in separate files
102
+ }
103
+ ```
104
+
105
+ Create the junction table manually (once):
106
+
107
+ ```ts
108
+ await db.run("CREATE TABLE post_tags (postId INTEGER NOT NULL, tagId INTEGER NOT NULL)");
109
+ ```
110
+
111
+ Then use it like any other relation in `select()`:
112
+
113
+ ```ts
114
+ const posts = await Post.query()
115
+ .select((p) => ({
116
+ id: p.id,
117
+ title: p.title,
118
+ tags: p.tags
119
+ .query()
120
+ .select((t) => ({ name: t.name }))
121
+ .orderBy((t) => t.name, "asc"),
122
+ }))
123
+ .toArray();
124
+ ```
125
+
126
+ ```sql
127
+ -- 1. Main query
128
+ SELECT id AS id, title AS title FROM posts
129
+
130
+ -- 2. Junction + target fetched together
131
+ SELECT post_tags.postId, tags.name AS name
132
+ FROM post_tags
133
+ JOIN tags ON tags.id = post_tags.tagId
134
+ WHERE post_tags.postId IN (?, ?, ...)
135
+ ORDER BY tags.name ASC
136
+ ```
137
+
138
+ ## Composite Primary Keys
139
+
140
+ When a table's primary key spans multiple columns, mark each column with `"primary key"` in the schema. Relations accept an array for composite foreign keys:
141
+
142
+ ```ts
143
+ const Project = Entity(
144
+ "projects",
145
+ {
146
+ tenantId: "text primary key",
147
+ projectId: "text primary key",
148
+ name: "text not null",
149
+ },
150
+ {
151
+ tasks: rel.oneToMany(() => Task, { foreignKey: ["tenantId", "projectId"] }),
152
+ },
153
+ );
154
+
155
+ const Task = Entity(
156
+ "tasks",
157
+ {
158
+ id: "integer primary key autoincrement",
159
+ tenantId: "text not null",
160
+ projectId: "text not null",
161
+ title: "text not null",
162
+ },
163
+ { project: rel.manyToOne(() => Project, { foreignKey: ["tenantId", "projectId"] }) },
164
+ );
165
+ ```
166
+
167
+ `findById` accepts an object for composite keys:
168
+
169
+ ```ts
170
+ const project = await Project.query().findById({ tenantId: "acme", projectId: "p1" });
171
+ ```
172
+
173
+ ```sql
174
+ SELECT tenantId, projectId, name FROM projects
175
+ WHERE tenantId = ? AND projectId = ?
176
+ LIMIT 1
177
+ -- params: ["acme", "p1"]
178
+ ```
179
+
180
+ ::: warning SQLite DDL
181
+ SQLite doesn't allow two `PRIMARY KEY` column constraints in one `CREATE TABLE`. Use `db.run()` with a table-level `PRIMARY KEY (col1, col2)` clause instead of `db.migrate()` for composite-PK tables.
182
+ :::
183
+
184
+ ## Custom Entity Classes
185
+
186
+ Subclass the `Entity()` result to add computed properties and lifecycle hooks. The subclass inherits all ORM methods (`.query()`, `.where()`, `.insert()`, etc.) and instances are returned by query methods.
187
+
188
+ ```ts
189
+ class UserEntity extends User {
190
+ // Computed property
191
+ get displayName() {
192
+ return this.name ?? this.email ?? "Anonymous";
193
+ }
194
+
195
+ // Lifecycle hook — called before every save()
196
+ beforeSave() {
197
+ if (!this.createdAt) this.createdAt = new Date();
198
+ }
199
+ }
200
+
201
+ // Query and use the computed property
202
+ const user = await UserEntity.query()
203
+ .where((u) => u.age > 18)
204
+ .first();
205
+ console.log(user?.displayName);
206
+ ```
207
+
208
+ `beforeSave()` is the only lifecycle hook. Use it to set defaults or enforce invariants — it runs before both inserts and updates.
@@ -0,0 +1,98 @@
1
+ # Expressions in Queries
2
+
3
+ Typhex accepts a practical expression subset anywhere a query lambda expects a value: `where()`, `having()`, `select()`, aggregate arguments, and `orderBy()`.
4
+
5
+ ## Conditional and Arithmetic Expressions
6
+
7
+ Use JavaScript ternaries for SQL `CASE` expressions, and arithmetic operators for derived values:
8
+
9
+ ```ts
10
+ const lineItems = await Order.query()
11
+ .select((o) => ({
12
+ id: o.id,
13
+ revenue: o.price * o.qty,
14
+ bucket: o.qty < 5 ? "small" : "large",
15
+ }))
16
+ .orderBy((o) => (o.qty < 5 ? 1 : 0))
17
+ .toArray();
18
+ ```
19
+
20
+ ```sql
21
+ SELECT id AS id,
22
+ (price * qty) AS revenue,
23
+ CASE WHEN qty < ? THEN ? ELSE ? END AS bucket
24
+ FROM orders
25
+ ORDER BY CASE WHEN qty < ? THEN ? ELSE ? END ASC
26
+ ```
27
+
28
+ Supported arithmetic operators are `+`, `-`, `*`, `/`, and `%`. Bitwise operators `&`, `|`, `^`, `<<`, `>>`, and unary `~` are also supported; PostgreSQL emits `#` for XOR.
29
+
30
+ ## Null Checks
31
+
32
+ Strict null comparisons compile to SQL null semantics:
33
+
34
+ ```ts
35
+ const liveCount = await Order.query()
36
+ .where((o) => o.deletedAt === null)
37
+ .count();
38
+
39
+ const deletedCount = await Order.query()
40
+ .where((o) => o.deletedAt !== null)
41
+ .count();
42
+ ```
43
+
44
+ ```sql
45
+ WHERE deletedAt IS NULL
46
+ WHERE deletedAt IS NOT NULL
47
+ ```
48
+
49
+ ## Computed Select Columns
50
+
51
+ Projection fields can be expressions, not just direct columns:
52
+
53
+ ```ts
54
+ const prices = await Order.query()
55
+ .select((o) => ({
56
+ id: o.id,
57
+ cents: o.price * 100,
58
+ activeLabel: o.active ? "active" : "inactive",
59
+ }))
60
+ .toArray();
61
+ ```
62
+
63
+ If the lambda returns a single scalar expression, Typhex aliases it as `expr`:
64
+
65
+ ```ts
66
+ const cents = await Order.query()
67
+ .select((o) => o.price * 100)
68
+ .toArray();
69
+ ```
70
+
71
+ ## Expressions Inside Aggregates
72
+
73
+ Aggregate arguments can include ternaries and arithmetic, which is useful for conditional counts and revenue totals:
74
+
75
+ ```ts
76
+ import { sum } from "typhex";
77
+
78
+ const cutoff = 5;
79
+ const buckets = await Order.query()
80
+ .select(
81
+ (o) => ({
82
+ category: o.category,
83
+ revenue: sum(o.price * o.qty),
84
+ smalls: sum(o.qty < cutoff ? 1 : 0),
85
+ }),
86
+ { cutoff },
87
+ )
88
+ .groupBy("category")
89
+ .toArray();
90
+ ```
91
+
92
+ In runtime mode, pass closure variables used by `.select()` as the second argument. With the TypeScript transformer, those variables are captured automatically.
93
+
94
+ ## Runtime and Transformer Boundaries
95
+
96
+ Ternaries, arithmetic, bitwise operators, null checks, computed projections, and expression `orderBy()` work in runtime mode and transformer mode.
97
+
98
+ Scalar correlated subqueries in `.select()`, comparison `.where()` predicates, and `.orderBy()` are transformer-only. See [Subqueries](/guide/subqueries) for those shapes.