@fragno-dev/db 0.1.14 → 0.2.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 (445) hide show
  1. package/.turbo/turbo-build.log +242 -139
  2. package/CHANGELOG.md +47 -0
  3. package/README.md +123 -8
  4. package/dist/adapters/adapters.d.ts +19 -5
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts +6 -19
  8. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  9. package/dist/adapters/drizzle/drizzle-adapter.js +7 -47
  10. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  11. package/dist/adapters/drizzle/generate.d.ts +7 -1
  12. package/dist/adapters/drizzle/generate.d.ts.map +1 -1
  13. package/dist/adapters/drizzle/generate.js +46 -45
  14. package/dist/adapters/drizzle/generate.js.map +1 -1
  15. package/dist/adapters/generic-sql/driver-config.d.ts +74 -0
  16. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -0
  17. package/dist/adapters/generic-sql/driver-config.js +94 -0
  18. package/dist/adapters/generic-sql/driver-config.js.map +1 -0
  19. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +43 -0
  20. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -0
  21. package/dist/adapters/generic-sql/generic-sql-adapter.js +87 -0
  22. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -0
  23. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +67 -0
  24. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -0
  25. package/dist/adapters/generic-sql/migration/cold-kysely.js +33 -0
  26. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -0
  27. package/dist/adapters/generic-sql/migration/dialect/mysql.js +60 -0
  28. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -0
  29. package/dist/adapters/generic-sql/migration/dialect/postgres.js +59 -0
  30. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -0
  31. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +96 -0
  32. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -0
  33. package/dist/adapters/generic-sql/migration/executor.d.ts +15 -0
  34. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  35. package/dist/adapters/generic-sql/migration/executor.js +18 -0
  36. package/dist/adapters/generic-sql/migration/executor.js.map +1 -0
  37. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  38. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  39. package/dist/adapters/generic-sql/migration/prepared-migrations.js +68 -0
  40. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -0
  41. package/dist/adapters/generic-sql/migration/sql-generator.js +212 -0
  42. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -0
  43. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +32 -0
  44. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -0
  45. package/dist/adapters/generic-sql/query/cursor-utils.js +37 -0
  46. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -0
  47. package/dist/adapters/generic-sql/query/dialect/mysql.js +33 -0
  48. package/dist/adapters/generic-sql/query/dialect/mysql.js.map +1 -0
  49. package/dist/adapters/generic-sql/query/dialect/postgres.js +32 -0
  50. package/dist/adapters/generic-sql/query/dialect/postgres.js.map +1 -0
  51. package/dist/adapters/generic-sql/query/dialect/sqlite.js +32 -0
  52. package/dist/adapters/generic-sql/query/dialect/sqlite.js.map +1 -0
  53. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +152 -0
  54. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -0
  55. package/dist/adapters/generic-sql/query/select-builder.js +69 -0
  56. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -0
  57. package/dist/adapters/generic-sql/query/sql-query-compiler.js +145 -0
  58. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -0
  59. package/dist/adapters/generic-sql/query/where-builder.js +129 -0
  60. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -0
  61. package/dist/adapters/generic-sql/result-interpreter.js +74 -0
  62. package/dist/adapters/generic-sql/result-interpreter.js.map +1 -0
  63. package/dist/adapters/generic-sql/uow-decoder.js +105 -0
  64. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -0
  65. package/dist/adapters/generic-sql/uow-encoder.js +93 -0
  66. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -0
  67. package/dist/adapters/kysely/kysely-adapter.d.ts +5 -16
  68. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  69. package/dist/adapters/kysely/kysely-adapter.js +6 -159
  70. package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
  71. package/dist/adapters/{drizzle/drizzle-query.js → shared/from-unit-of-work-compiler.js} +48 -62
  72. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -0
  73. package/dist/adapters/{kysely/kysely-shared.d.ts → shared/table-name-mapper.d.ts} +3 -2
  74. package/dist/adapters/shared/table-name-mapper.d.ts.map +1 -0
  75. package/dist/adapters/shared/table-name-mapper.js +43 -0
  76. package/dist/adapters/shared/table-name-mapper.js.map +1 -0
  77. package/dist/adapters/shared/uow-operation-compiler.js +105 -0
  78. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -0
  79. package/dist/db-fragment-definition-builder.d.ts +186 -0
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -0
  81. package/dist/db-fragment-definition-builder.js +207 -0
  82. package/dist/db-fragment-definition-builder.js.map +1 -0
  83. package/dist/fragments/internal-fragment.d.ts +53 -0
  84. package/dist/fragments/internal-fragment.d.ts.map +1 -0
  85. package/dist/fragments/internal-fragment.js +111 -0
  86. package/dist/fragments/internal-fragment.js.map +1 -0
  87. package/dist/hooks/hooks.d.ts +51 -0
  88. package/dist/hooks/hooks.d.ts.map +1 -0
  89. package/dist/hooks/hooks.js +88 -0
  90. package/dist/hooks/hooks.js.map +1 -0
  91. package/dist/migration-engine/generation-engine.d.ts +0 -2
  92. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  93. package/dist/migration-engine/generation-engine.js +38 -56
  94. package/dist/migration-engine/generation-engine.js.map +1 -1
  95. package/dist/mod.d.ts +35 -23
  96. package/dist/mod.d.ts.map +1 -1
  97. package/dist/mod.js +48 -45
  98. package/dist/mod.js.map +1 -1
  99. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +165 -0
  100. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +1 -0
  101. package/dist/packages/fragno/dist/api/bind-services.js +20 -0
  102. package/dist/packages/fragno/dist/api/bind-services.js.map +1 -0
  103. package/dist/packages/fragno/dist/api/error.js +48 -0
  104. package/dist/packages/fragno/dist/api/error.js.map +1 -0
  105. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +320 -0
  106. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -0
  107. package/dist/packages/fragno/dist/api/fragment-instantiator.js +525 -0
  108. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -0
  109. package/dist/packages/fragno/dist/api/fragno-response.js +73 -0
  110. package/dist/packages/fragno/dist/api/fragno-response.js.map +1 -0
  111. package/dist/packages/fragno/dist/api/internal/response-stream.js +81 -0
  112. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
  113. package/dist/packages/fragno/dist/api/internal/route.js +10 -0
  114. package/dist/packages/fragno/dist/api/internal/route.js.map +1 -0
  115. package/dist/packages/fragno/dist/api/mutable-request-state.js +97 -0
  116. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +1 -0
  117. package/dist/packages/fragno/dist/api/request-context-storage.js +43 -0
  118. package/dist/packages/fragno/dist/api/request-context-storage.js.map +1 -0
  119. package/dist/packages/fragno/dist/api/request-input-context.js +118 -0
  120. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -0
  121. package/dist/packages/fragno/dist/api/request-middleware.js +83 -0
  122. package/dist/packages/fragno/dist/api/request-middleware.js.map +1 -0
  123. package/dist/packages/fragno/dist/api/request-output-context.js +119 -0
  124. package/dist/packages/fragno/dist/api/request-output-context.js.map +1 -0
  125. package/dist/packages/fragno/dist/api/route.js +17 -0
  126. package/dist/packages/fragno/dist/api/route.js.map +1 -0
  127. package/dist/packages/fragno/dist/internal/symbols.js +10 -0
  128. package/dist/packages/fragno/dist/internal/symbols.js.map +1 -0
  129. package/dist/query/column-defaults.js +27 -0
  130. package/dist/query/column-defaults.js.map +1 -0
  131. package/dist/query/cursor.d.ts +14 -6
  132. package/dist/query/cursor.d.ts.map +1 -1
  133. package/dist/query/cursor.js +16 -7
  134. package/dist/query/cursor.js.map +1 -1
  135. package/dist/query/orm/orm.d.ts +1 -1
  136. package/dist/query/orm/orm.js.map +1 -1
  137. package/dist/query/serialize/create-sql-serializer.js +30 -0
  138. package/dist/query/serialize/create-sql-serializer.js.map +1 -0
  139. package/dist/query/serialize/dialect/mysql-serializer.js +87 -0
  140. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -0
  141. package/dist/query/serialize/dialect/postgres-serializer.js +80 -0
  142. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -0
  143. package/dist/query/serialize/dialect/sqlite-serializer.js +93 -0
  144. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -0
  145. package/dist/query/serialize/sql-serializer.js +67 -0
  146. package/dist/query/serialize/sql-serializer.js.map +1 -0
  147. package/dist/query/{query.d.ts → simple-query-interface.d.ts} +6 -6
  148. package/dist/query/simple-query-interface.d.ts.map +1 -0
  149. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +133 -0
  150. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  151. package/dist/query/unit-of-work/execute-unit-of-work.js +197 -0
  152. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  153. package/dist/query/unit-of-work/retry-policy.d.ts +88 -0
  154. package/dist/query/unit-of-work/retry-policy.d.ts.map +1 -0
  155. package/dist/query/unit-of-work/retry-policy.js +61 -0
  156. package/dist/query/unit-of-work/retry-policy.js.map +1 -0
  157. package/dist/query/{unit-of-work.d.ts → unit-of-work/unit-of-work.d.ts} +145 -58
  158. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  159. package/dist/query/{unit-of-work.js → unit-of-work/unit-of-work.js} +435 -198
  160. package/dist/query/unit-of-work/unit-of-work.js.map +1 -0
  161. package/dist/query/value-decoding.js +71 -0
  162. package/dist/query/value-decoding.js.map +1 -0
  163. package/dist/query/value-encoding.js +124 -0
  164. package/dist/query/value-encoding.js.map +1 -0
  165. package/dist/schema/create.d.ts +3 -0
  166. package/dist/schema/create.d.ts.map +1 -1
  167. package/dist/schema/create.js +4 -0
  168. package/dist/schema/create.js.map +1 -1
  169. package/dist/schema/type-conversion/create-sql-type-mapper.js +29 -0
  170. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -0
  171. package/dist/schema/type-conversion/dialect/mysql.js +57 -0
  172. package/dist/schema/type-conversion/dialect/mysql.js.map +1 -0
  173. package/dist/schema/type-conversion/dialect/postgres.js +56 -0
  174. package/dist/schema/type-conversion/dialect/postgres.js.map +1 -0
  175. package/dist/schema/type-conversion/dialect/sqlite.js +52 -0
  176. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -0
  177. package/dist/schema/type-conversion/type-mapping.js +63 -0
  178. package/dist/schema/type-conversion/type-mapping.js.map +1 -0
  179. package/dist/sql-driver/connection/connection-provider.d.ts +13 -0
  180. package/dist/sql-driver/connection/connection-provider.d.ts.map +1 -0
  181. package/dist/sql-driver/connection/connection-provider.js +19 -0
  182. package/dist/sql-driver/connection/connection-provider.js.map +1 -0
  183. package/dist/sql-driver/connection/single-connection-provider.js +23 -0
  184. package/dist/sql-driver/connection/single-connection-provider.js.map +1 -0
  185. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  186. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  187. package/dist/sql-driver/dialects/dialects.d.ts +2 -0
  188. package/dist/sql-driver/dialects/dialects.js +3 -0
  189. package/dist/sql-driver/dialects/durable-object-dialect.d.ts +72 -0
  190. package/dist/sql-driver/dialects/durable-object-dialect.d.ts.map +1 -0
  191. package/dist/sql-driver/dialects/durable-object-dialect.js +130 -0
  192. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -0
  193. package/dist/sql-driver/driver/runtime-driver.d.ts +23 -0
  194. package/dist/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  195. package/dist/sql-driver/driver/runtime-driver.js +56 -0
  196. package/dist/sql-driver/driver/runtime-driver.js.map +1 -0
  197. package/dist/sql-driver/query-executor/default-query-executor.js +26 -0
  198. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -0
  199. package/dist/sql-driver/query-executor/plugin.d.ts +17 -0
  200. package/dist/sql-driver/query-executor/plugin.d.ts.map +1 -0
  201. package/dist/sql-driver/query-executor/query-executor-base.js +25 -0
  202. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -0
  203. package/dist/sql-driver/query-executor/query-executor.d.ts +36 -0
  204. package/dist/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  205. package/dist/sql-driver/sql-driver-adapter.d.ts +29 -0
  206. package/dist/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  207. package/dist/sql-driver/sql-driver-adapter.js +68 -0
  208. package/dist/sql-driver/sql-driver-adapter.js.map +1 -0
  209. package/dist/sql-driver/sql-driver.d.ts +38 -0
  210. package/dist/sql-driver/sql-driver.d.ts.map +1 -0
  211. package/dist/sql-driver/sql-driver.js +1 -0
  212. package/dist/sql-driver/sql.js +50 -0
  213. package/dist/sql-driver/sql.js.map +1 -0
  214. package/dist/with-database.d.ts +32 -0
  215. package/dist/with-database.d.ts.map +1 -0
  216. package/dist/with-database.js +34 -0
  217. package/dist/with-database.js.map +1 -0
  218. package/package.json +43 -9
  219. package/src/adapters/adapters.ts +23 -4
  220. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +140 -185
  221. package/src/adapters/drizzle/{drizzle-adapter-sqlite.test.ts → drizzle-adapter-sqlite3.test.ts} +187 -55
  222. package/src/adapters/drizzle/drizzle-adapter.ts +14 -93
  223. package/src/adapters/drizzle/generate.test.ts +102 -269
  224. package/src/adapters/drizzle/generate.ts +89 -63
  225. package/src/adapters/drizzle/migrate-drizzle.test.ts +19 -0
  226. package/src/adapters/drizzle/shared.ts +0 -34
  227. package/src/adapters/drizzle/test-utils.ts +36 -5
  228. package/src/adapters/generic-sql/README.md +14 -0
  229. package/src/adapters/generic-sql/driver-config.ts +144 -0
  230. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +50 -0
  231. package/src/adapters/generic-sql/generic-sql-adapter.ts +146 -0
  232. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +130 -0
  233. package/src/adapters/generic-sql/migration/cold-kysely.ts +55 -0
  234. package/src/adapters/{kysely/migration/execute-mysql.test.ts → generic-sql/migration/dialect/mysql.test.ts} +342 -484
  235. package/src/adapters/generic-sql/migration/dialect/mysql.ts +104 -0
  236. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +1008 -0
  237. package/src/adapters/generic-sql/migration/dialect/postgres.ts +113 -0
  238. package/src/adapters/{kysely/migration/execute-sqlite.test.ts → generic-sql/migration/dialect/sqlite.test.ts} +307 -510
  239. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +189 -0
  240. package/src/adapters/generic-sql/migration/executor.ts +33 -0
  241. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +661 -0
  242. package/src/adapters/generic-sql/migration/prepared-migrations.ts +214 -0
  243. package/src/adapters/generic-sql/migration/sql-generator.ts +413 -0
  244. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +36 -0
  245. package/src/adapters/generic-sql/query/cursor-utils.ts +56 -0
  246. package/src/adapters/generic-sql/query/dialect/mysql.ts +34 -0
  247. package/src/adapters/generic-sql/query/dialect/postgres.ts +32 -0
  248. package/src/adapters/generic-sql/query/dialect/sqlite.ts +32 -0
  249. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +1568 -0
  250. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +314 -0
  251. package/src/adapters/generic-sql/query/select-builder.test.ts +256 -0
  252. package/src/adapters/generic-sql/query/select-builder.ts +137 -0
  253. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +195 -0
  254. package/src/adapters/generic-sql/query/sql-query-compiler.ts +367 -0
  255. package/src/adapters/generic-sql/query/where-builder.test.ts +744 -0
  256. package/src/adapters/generic-sql/query/where-builder.ts +211 -0
  257. package/src/adapters/generic-sql/result-interpreter.ts +102 -0
  258. package/src/adapters/generic-sql/test/generic-drizzle-adapter-sqlite3.test.ts +899 -0
  259. package/src/adapters/generic-sql/uow-decoder.test.ts +399 -0
  260. package/src/adapters/generic-sql/uow-decoder.ts +152 -0
  261. package/src/adapters/generic-sql/uow-encoder.test.ts +183 -0
  262. package/src/adapters/generic-sql/uow-encoder.ts +131 -0
  263. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +90 -96
  264. package/src/adapters/kysely/kysely-adapter-sqlocal.test.ts +215 -0
  265. package/src/adapters/kysely/kysely-adapter.ts +10 -242
  266. package/src/adapters/{drizzle/drizzle-query.ts → shared/from-unit-of-work-compiler.ts} +111 -106
  267. package/src/adapters/shared/table-name-mapper.ts +50 -0
  268. package/src/adapters/shared/uow-operation-compiler.ts +211 -0
  269. package/src/db-fragment-definition-builder.test.ts +887 -0
  270. package/src/db-fragment-definition-builder.ts +737 -0
  271. package/src/db-fragment-instantiator.test.ts +543 -0
  272. package/src/db-fragment-integration.test.ts +406 -0
  273. package/src/fragments/internal-fragment.test.ts +549 -0
  274. package/src/fragments/internal-fragment.ts +249 -0
  275. package/src/hooks/hooks.test.ts +575 -0
  276. package/src/hooks/hooks.ts +179 -0
  277. package/src/migration-engine/generation-engine.test.ts +60 -27
  278. package/src/migration-engine/generation-engine.ts +99 -92
  279. package/src/mod.ts +139 -78
  280. package/src/query/column-defaults.ts +49 -0
  281. package/src/query/cursor.test.ts +147 -3
  282. package/src/query/cursor.ts +25 -8
  283. package/src/query/orm/orm.ts +1 -1
  284. package/src/query/query-type.test.ts +9 -9
  285. package/src/query/serialize/create-sql-serializer.ts +34 -0
  286. package/src/query/serialize/dialect/mysql-serializer.ts +142 -0
  287. package/src/query/serialize/dialect/postgres-serializer.ts +129 -0
  288. package/src/query/serialize/dialect/sqlite-serializer.test.ts +251 -0
  289. package/src/query/serialize/dialect/sqlite-serializer.ts +156 -0
  290. package/src/query/serialize/sql-serializer.ts +143 -0
  291. package/src/query/{query.ts → simple-query-interface.ts} +4 -4
  292. package/src/query/unit-of-work/execute-unit-of-work.test.ts +1310 -0
  293. package/src/query/unit-of-work/execute-unit-of-work.ts +504 -0
  294. package/src/query/unit-of-work/retry-policy.test.ts +217 -0
  295. package/src/query/unit-of-work/retry-policy.ts +141 -0
  296. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +831 -0
  297. package/src/query/{unit-of-work-types.test.ts → unit-of-work/unit-of-work-types.test.ts} +7 -5
  298. package/src/query/unit-of-work/unit-of-work.test.ts +1716 -0
  299. package/src/query/{unit-of-work.ts → unit-of-work/unit-of-work.ts} +716 -420
  300. package/src/query/{result-transform.test.ts → value-decoding.test.ts} +45 -298
  301. package/src/query/value-decoding.ts +113 -0
  302. package/src/query/value-encoding.test.ts +390 -0
  303. package/src/query/value-encoding.ts +168 -0
  304. package/src/schema/create.test.ts +5 -1
  305. package/src/schema/create.ts +5 -0
  306. package/src/schema/serialize.test.ts +165 -407
  307. package/src/schema/type-conversion/create-sql-type-mapper.ts +28 -0
  308. package/src/schema/type-conversion/dialect/mysql.ts +64 -0
  309. package/src/schema/type-conversion/dialect/postgres.ts +62 -0
  310. package/src/schema/type-conversion/dialect/sqlite.ts +63 -0
  311. package/src/schema/type-conversion/type-mapping.test.ts +137 -0
  312. package/src/schema/type-conversion/type-mapping.ts +153 -0
  313. package/src/shared/connection-pool.ts +5 -5
  314. package/src/sql-driver/better-sqlite3.test.ts +126 -0
  315. package/src/sql-driver/connection/connection-provider.ts +27 -0
  316. package/src/sql-driver/connection/single-connection-provider.ts +42 -0
  317. package/src/sql-driver/dialect-adapter/dialect-adapter.ts +9 -0
  318. package/src/sql-driver/dialect-adapter/sqlite-dialect-adapter.ts +7 -0
  319. package/src/sql-driver/dialects/dialects.ts +1 -0
  320. package/src/sql-driver/dialects/durable-object-dialect.ts +260 -0
  321. package/src/sql-driver/driver/runtime-driver.ts +91 -0
  322. package/src/sql-driver/query-executor/default-query-executor.ts +38 -0
  323. package/src/sql-driver/query-executor/plugin.ts +22 -0
  324. package/src/sql-driver/query-executor/query-executor-base.ts +53 -0
  325. package/src/sql-driver/query-executor/query-executor.ts +44 -0
  326. package/src/sql-driver/sql-driver-adapter.ts +96 -0
  327. package/src/sql-driver/sql-driver.ts +53 -0
  328. package/src/sql-driver/sql.ts +57 -0
  329. package/src/sql-driver/sqlocal.test.ts +117 -0
  330. package/src/with-database.ts +152 -0
  331. package/tsdown.config.ts +8 -2
  332. package/dist/adapters/drizzle/drizzle-connection-pool.js +0 -40
  333. package/dist/adapters/drizzle/drizzle-connection-pool.js.map +0 -1
  334. package/dist/adapters/drizzle/drizzle-query.d.ts +0 -23
  335. package/dist/adapters/drizzle/drizzle-query.d.ts.map +0 -1
  336. package/dist/adapters/drizzle/drizzle-query.js.map +0 -1
  337. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -10
  338. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +0 -1
  339. package/dist/adapters/drizzle/drizzle-uow-compiler.js +0 -315
  340. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +0 -1
  341. package/dist/adapters/drizzle/drizzle-uow-decoder.js +0 -116
  342. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +0 -1
  343. package/dist/adapters/drizzle/drizzle-uow-executor.js +0 -149
  344. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +0 -1
  345. package/dist/adapters/drizzle/join-column-utils.js +0 -28
  346. package/dist/adapters/drizzle/join-column-utils.js.map +0 -1
  347. package/dist/adapters/drizzle/shared.d.ts +0 -14
  348. package/dist/adapters/drizzle/shared.d.ts.map +0 -1
  349. package/dist/adapters/drizzle/shared.js +0 -35
  350. package/dist/adapters/drizzle/shared.js.map +0 -1
  351. package/dist/adapters/kysely/kysely-connection-pool.js +0 -41
  352. package/dist/adapters/kysely/kysely-connection-pool.js.map +0 -1
  353. package/dist/adapters/kysely/kysely-query-builder.js +0 -321
  354. package/dist/adapters/kysely/kysely-query-builder.js.map +0 -1
  355. package/dist/adapters/kysely/kysely-query-compiler.js +0 -66
  356. package/dist/adapters/kysely/kysely-query-compiler.js.map +0 -1
  357. package/dist/adapters/kysely/kysely-query.d.ts +0 -22
  358. package/dist/adapters/kysely/kysely-query.d.ts.map +0 -1
  359. package/dist/adapters/kysely/kysely-query.js +0 -223
  360. package/dist/adapters/kysely/kysely-query.js.map +0 -1
  361. package/dist/adapters/kysely/kysely-shared.d.ts.map +0 -1
  362. package/dist/adapters/kysely/kysely-shared.js +0 -18
  363. package/dist/adapters/kysely/kysely-shared.js.map +0 -1
  364. package/dist/adapters/kysely/kysely-uow-compiler.js +0 -170
  365. package/dist/adapters/kysely/kysely-uow-compiler.js.map +0 -1
  366. package/dist/adapters/kysely/kysely-uow-executor.js +0 -89
  367. package/dist/adapters/kysely/kysely-uow-executor.js.map +0 -1
  368. package/dist/adapters/kysely/migration/execute-base.js +0 -128
  369. package/dist/adapters/kysely/migration/execute-base.js.map +0 -1
  370. package/dist/adapters/kysely/migration/execute-factory.js +0 -34
  371. package/dist/adapters/kysely/migration/execute-factory.js.map +0 -1
  372. package/dist/adapters/kysely/migration/execute-mssql.js +0 -112
  373. package/dist/adapters/kysely/migration/execute-mssql.js.map +0 -1
  374. package/dist/adapters/kysely/migration/execute-mysql.js +0 -93
  375. package/dist/adapters/kysely/migration/execute-mysql.js.map +0 -1
  376. package/dist/adapters/kysely/migration/execute-postgres.js +0 -104
  377. package/dist/adapters/kysely/migration/execute-postgres.js.map +0 -1
  378. package/dist/adapters/kysely/migration/execute-sqlite.js +0 -123
  379. package/dist/adapters/kysely/migration/execute-sqlite.js.map +0 -1
  380. package/dist/adapters/kysely/migration/execute.js +0 -34
  381. package/dist/adapters/kysely/migration/execute.js.map +0 -1
  382. package/dist/bind-services.d.ts +0 -7
  383. package/dist/bind-services.d.ts.map +0 -1
  384. package/dist/bind-services.js +0 -14
  385. package/dist/bind-services.js.map +0 -1
  386. package/dist/fragment.d.ts +0 -173
  387. package/dist/fragment.d.ts.map +0 -1
  388. package/dist/fragment.js +0 -191
  389. package/dist/fragment.js.map +0 -1
  390. package/dist/migration-engine/create.d.ts +0 -37
  391. package/dist/migration-engine/create.d.ts.map +0 -1
  392. package/dist/migration-engine/create.js +0 -58
  393. package/dist/migration-engine/create.js.map +0 -1
  394. package/dist/migration-engine/shared.d.ts +0 -112
  395. package/dist/migration-engine/shared.d.ts.map +0 -1
  396. package/dist/query/query.d.ts.map +0 -1
  397. package/dist/query/result-transform.js +0 -168
  398. package/dist/query/result-transform.js.map +0 -1
  399. package/dist/query/unit-of-work.d.ts.map +0 -1
  400. package/dist/query/unit-of-work.js.map +0 -1
  401. package/dist/schema/serialize.js +0 -106
  402. package/dist/schema/serialize.js.map +0 -1
  403. package/dist/shared/settings-schema.js +0 -36
  404. package/dist/shared/settings-schema.js.map +0 -1
  405. package/src/adapters/drizzle/drizzle-adapter.test.ts +0 -170
  406. package/src/adapters/drizzle/drizzle-connection-pool.ts +0 -66
  407. package/src/adapters/drizzle/drizzle-query.test.ts +0 -499
  408. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +0 -1383
  409. package/src/adapters/drizzle/drizzle-uow-compiler.ts +0 -636
  410. package/src/adapters/drizzle/drizzle-uow-decoder.ts +0 -218
  411. package/src/adapters/drizzle/drizzle-uow-executor.ts +0 -276
  412. package/src/adapters/drizzle/join-column-utils.test.ts +0 -79
  413. package/src/adapters/drizzle/join-column-utils.ts +0 -39
  414. package/src/adapters/kysely/kysely-connection-pool.ts +0 -70
  415. package/src/adapters/kysely/kysely-query-builder.test.ts +0 -1344
  416. package/src/adapters/kysely/kysely-query-builder.ts +0 -666
  417. package/src/adapters/kysely/kysely-query-compiler.ts +0 -132
  418. package/src/adapters/kysely/kysely-query.test.ts +0 -498
  419. package/src/adapters/kysely/kysely-query.ts +0 -390
  420. package/src/adapters/kysely/kysely-shared.ts +0 -23
  421. package/src/adapters/kysely/kysely-uow-compiler.test.ts +0 -998
  422. package/src/adapters/kysely/kysely-uow-compiler.ts +0 -318
  423. package/src/adapters/kysely/kysely-uow-executor.ts +0 -145
  424. package/src/adapters/kysely/kysely-uow-joins.test.ts +0 -811
  425. package/src/adapters/kysely/migration/execute-base.ts +0 -256
  426. package/src/adapters/kysely/migration/execute-factory.ts +0 -53
  427. package/src/adapters/kysely/migration/execute-mssql.ts +0 -250
  428. package/src/adapters/kysely/migration/execute-mysql.ts +0 -211
  429. package/src/adapters/kysely/migration/execute-postgres.test.ts +0 -2657
  430. package/src/adapters/kysely/migration/execute-postgres.ts +0 -234
  431. package/src/adapters/kysely/migration/execute-sqlite.ts +0 -247
  432. package/src/adapters/kysely/migration/execute.ts +0 -50
  433. package/src/adapters/kysely/migration/kysely-migrator.test.ts +0 -261
  434. package/src/bind-services.test.ts +0 -214
  435. package/src/bind-services.ts +0 -37
  436. package/src/db-fragment.test.ts +0 -800
  437. package/src/fragment.ts +0 -727
  438. package/src/query/result-transform.ts +0 -271
  439. package/src/query/unit-of-work-multi-schema.test.ts +0 -64
  440. package/src/query/unit-of-work.test.ts +0 -943
  441. package/src/schema/serialize.ts +0 -396
  442. package/src/shared/settings-schema.ts +0 -61
  443. package/src/uow-context-integration.test.ts +0 -102
  444. package/src/uow-context.test.ts +0 -182
  445. /package/dist/query/{query.js → simple-query-interface.js} +0 -0
@@ -0,0 +1,314 @@
1
+ import { UOWOperationCompiler } from "../../shared/uow-operation-compiler";
2
+ import type { CompiledQuery } from "kysely";
3
+ import type { DriverConfig } from "../driver-config";
4
+ import type { TableNameMapper } from "../../shared/table-name-mapper";
5
+ import type {
6
+ RetrievalOperation,
7
+ MutationOperation,
8
+ CompiledMutation,
9
+ } from "../../../query/unit-of-work/unit-of-work";
10
+ import type { AnyColumn, AnySchema } from "../../../schema/create";
11
+ import { buildCondition } from "../../../query/condition-builder";
12
+ import { createSQLQueryCompiler } from "./create-sql-query-compiler";
13
+ import { SQLQueryCompiler } from "./sql-query-compiler";
14
+ import { buildCursorCondition } from "./cursor-utils";
15
+ import type { Condition } from "../../../query/condition-builder";
16
+ import { buildFindOptions } from "../../../query/orm/orm";
17
+ import type { AnySelectClause } from "../../../query/simple-query-interface";
18
+ import { createColdKysely } from "../migration/cold-kysely";
19
+
20
+ /**
21
+ * Generic SQL UOW Operation Compiler.
22
+ *
23
+ * Uses SQLQueryCompiler for dialect-specific SQL generation while handling
24
+ * high-level business logic like cursor pagination, version checking, and index resolution.
25
+ */
26
+ export class GenericSQLUOWOperationCompiler extends UOWOperationCompiler<CompiledQuery> {
27
+ constructor(
28
+ driverConfig: DriverConfig,
29
+ mapperFactory?: (namespace: string | undefined) => TableNameMapper | undefined,
30
+ ) {
31
+ super(driverConfig, mapperFactory);
32
+ }
33
+
34
+ /**
35
+ * Get SQL compiler for a specific namespace
36
+ */
37
+ private getSQLCompiler(namespace: string | undefined): SQLQueryCompiler {
38
+ const mapper = this.getMapperForOperation(namespace);
39
+ const kysely = createColdKysely(this.driverConfig.databaseType);
40
+ return createSQLQueryCompiler(kysely, this.driverConfig, mapper);
41
+ }
42
+
43
+ override compileCount(
44
+ op: RetrievalOperation<AnySchema> & { type: "count" },
45
+ ): CompiledQuery | null {
46
+ const sqlCompiler = this.getSQLCompiler(op.namespace);
47
+
48
+ // Build where condition
49
+ let conditions = op.options.where
50
+ ? buildCondition(op.table.columns, op.options.where)
51
+ : undefined;
52
+
53
+ if (conditions === true) {
54
+ conditions = undefined;
55
+ }
56
+ if (conditions === false) {
57
+ return null;
58
+ }
59
+
60
+ return sqlCompiler.compileCount(op.table, { where: conditions });
61
+ }
62
+
63
+ override compileFind(op: RetrievalOperation<AnySchema> & { type: "find" }): CompiledQuery | null {
64
+ const sqlCompiler = this.getSQLCompiler(op.namespace);
65
+
66
+ // Extract options
67
+ const {
68
+ useIndex: _useIndex,
69
+ orderByIndex,
70
+ joins: join,
71
+ after,
72
+ before,
73
+ pageSize,
74
+ ...findManyOptions
75
+ } = op.options;
76
+
77
+ // Get index columns for ordering and cursor pagination
78
+ let indexColumns: AnyColumn[] = [];
79
+ let orderDirection: "asc" | "desc" = "asc";
80
+
81
+ if (orderByIndex) {
82
+ const index = op.table.indexes[orderByIndex.indexName];
83
+ orderDirection = orderByIndex.direction;
84
+
85
+ if (!index) {
86
+ // If _primary index doesn't exist, fall back to internal ID column
87
+ if (orderByIndex.indexName === "_primary") {
88
+ indexColumns = [op.table.getIdColumn()];
89
+ } else {
90
+ throw new Error(
91
+ `Index "${orderByIndex.indexName}" not found on table "${op.table.name}"`,
92
+ );
93
+ }
94
+ } else {
95
+ // Order by all columns in the index with the specified direction
96
+ indexColumns = index.columns;
97
+ }
98
+ }
99
+
100
+ // Convert orderByIndex to orderBy format
101
+ let orderBy: [AnyColumn, "asc" | "desc"][] | undefined;
102
+ if (indexColumns.length > 0) {
103
+ orderBy = indexColumns.map((col) => [col, orderDirection]);
104
+ }
105
+
106
+ // Handle cursor pagination - build a cursor condition
107
+ // TODO: Multi-column cursor pagination not yet supported
108
+ if ((after || before) && indexColumns.length > 1) {
109
+ throw new Error(
110
+ "Multi-column cursor pagination is not yet supported in Generic SQL implementation",
111
+ );
112
+ }
113
+ const cursorCondition = buildCursorCondition(
114
+ after || before,
115
+ indexColumns,
116
+ orderDirection,
117
+ !!after,
118
+ this.driverConfig,
119
+ );
120
+
121
+ // Combine user where clause with cursor condition
122
+ let combinedWhere: Condition | undefined;
123
+ if (findManyOptions.where) {
124
+ const whereResult = buildCondition(op.table.columns, findManyOptions.where);
125
+ if (whereResult === true) {
126
+ combinedWhere = undefined;
127
+ } else if (whereResult === false) {
128
+ return null;
129
+ } else {
130
+ combinedWhere = whereResult;
131
+ }
132
+ }
133
+
134
+ if (cursorCondition) {
135
+ if (combinedWhere) {
136
+ combinedWhere = {
137
+ type: "and",
138
+ items: [combinedWhere, cursorCondition],
139
+ };
140
+ } else {
141
+ combinedWhere = cursorCondition;
142
+ }
143
+ }
144
+
145
+ // For cursor pagination, fetch one extra item to determine if there's a next page
146
+ const effectiveLimit = pageSize && op.withCursor ? pageSize + 1 : pageSize;
147
+
148
+ // When we have joins, use the query builder directly
149
+ if (join && join.length > 0) {
150
+ return sqlCompiler.compileFindMany(op.table, {
151
+ select: (findManyOptions.select ?? true) as AnySelectClause,
152
+ where: combinedWhere,
153
+ orderBy,
154
+ limit: effectiveLimit,
155
+ join,
156
+ });
157
+ }
158
+
159
+ // Otherwise, use buildFindOptions to process the query options
160
+ const compiledOptions = buildFindOptions(op.table, {
161
+ ...findManyOptions,
162
+ where: combinedWhere ? () => combinedWhere! : undefined,
163
+ orderBy: orderBy?.map(([col, dir]) => [col.ormName, dir]),
164
+ limit: effectiveLimit,
165
+ });
166
+
167
+ if (compiledOptions === false) {
168
+ return null;
169
+ }
170
+
171
+ return sqlCompiler.compileFindMany(op.table, compiledOptions);
172
+ }
173
+
174
+ override compileCreate(
175
+ op: MutationOperation<AnySchema> & { type: "create" },
176
+ ): CompiledMutation<CompiledQuery> | null {
177
+ const sqlCompiler = this.getSQLCompiler(op.namespace);
178
+ const table = this.getTable(op.schema, op.table);
179
+
180
+ return {
181
+ query: sqlCompiler.compileCreate(table, op.values),
182
+ op: "create",
183
+ expectedAffectedRows: null, // creates don't need affected row checks
184
+ expectedReturnedRows: null,
185
+ };
186
+ }
187
+
188
+ override compileUpdate(
189
+ op: MutationOperation<AnySchema> & { type: "update" },
190
+ ): CompiledMutation<CompiledQuery> | null {
191
+ const sqlCompiler = this.getSQLCompiler(op.namespace);
192
+ const table = this.getTable(op.schema, op.table);
193
+ const idColumn = table.getIdColumn();
194
+ const versionColumn = table.getVersionColumn();
195
+
196
+ const externalId = this.getExternalId(op.id);
197
+ const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);
198
+
199
+ // Build WHERE clause that filters by ID and optionally by version
200
+ const conditionsResult =
201
+ versionToCheck !== undefined
202
+ ? buildCondition(table.columns, (eb) =>
203
+ eb.and(
204
+ eb(idColumn.ormName, "=", externalId),
205
+ eb(versionColumn.ormName, "=", versionToCheck),
206
+ ),
207
+ )
208
+ : buildCondition(table.columns, (eb) => eb(idColumn.ormName, "=", externalId));
209
+
210
+ if (conditionsResult === false) {
211
+ return null;
212
+ }
213
+
214
+ const conditions: Condition | undefined =
215
+ conditionsResult === true ? undefined : conditionsResult;
216
+
217
+ // Determine if we should use RETURNING-based checking
218
+ // Use RETURNING when driver supports it but doesn't support affected rows reporting
219
+ const useReturningForCheck =
220
+ op.checkVersion &&
221
+ this.driverConfig.supportsReturning &&
222
+ !this.driverConfig.supportsRowsAffected;
223
+
224
+ const query = sqlCompiler.compileUpdate(table, {
225
+ set: op.set,
226
+ where: conditions,
227
+ returning: useReturningForCheck,
228
+ });
229
+
230
+ return {
231
+ query,
232
+ op: "update",
233
+ expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,
234
+ expectedReturnedRows: useReturningForCheck ? 1 : null,
235
+ };
236
+ }
237
+
238
+ override compileDelete(
239
+ op: MutationOperation<AnySchema> & { type: "delete" },
240
+ ): CompiledMutation<CompiledQuery> | null {
241
+ const sqlCompiler = this.getSQLCompiler(op.namespace);
242
+ const table = this.getTable(op.schema, op.table);
243
+ const idColumn = table.getIdColumn();
244
+ const versionColumn = table.getVersionColumn();
245
+
246
+ const externalId = this.getExternalId(op.id);
247
+ const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);
248
+
249
+ // Build WHERE clause that filters by ID and optionally by version
250
+ const conditionsResult =
251
+ versionToCheck !== undefined
252
+ ? buildCondition(table.columns, (eb) =>
253
+ eb.and(
254
+ eb(idColumn.ormName, "=", externalId),
255
+ eb(versionColumn.ormName, "=", versionToCheck),
256
+ ),
257
+ )
258
+ : buildCondition(table.columns, (eb) => eb(idColumn.ormName, "=", externalId));
259
+
260
+ if (conditionsResult === false) {
261
+ return null;
262
+ }
263
+
264
+ const conditions: Condition | undefined =
265
+ conditionsResult === true ? undefined : conditionsResult;
266
+
267
+ // Determine if we should use RETURNING-based checking
268
+ // Use RETURNING when driver supports it but doesn't support affected rows reporting
269
+ const useReturningForCheck =
270
+ op.checkVersion &&
271
+ this.driverConfig.supportsReturning &&
272
+ !this.driverConfig.supportsRowsAffected;
273
+
274
+ const query = sqlCompiler.compileDelete(table, {
275
+ where: conditions,
276
+ returning: useReturningForCheck,
277
+ });
278
+
279
+ return {
280
+ query,
281
+ op: "delete",
282
+ expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,
283
+ expectedReturnedRows: useReturningForCheck ? 1 : null,
284
+ };
285
+ }
286
+
287
+ override compileCheck(
288
+ op: MutationOperation<AnySchema> & { type: "check" },
289
+ ): CompiledMutation<CompiledQuery> {
290
+ const sqlCompiler = this.getSQLCompiler(op.namespace);
291
+ const table = this.getTable(op.schema, op.table);
292
+ const idColumn = table.getIdColumn();
293
+ const versionColumn = table.getVersionColumn();
294
+
295
+ const externalId = op.id.externalId;
296
+ const version = op.id.version;
297
+
298
+ // Build a SELECT 1 query to check if the row exists with the correct version
299
+ const condition = buildCondition(table.columns, (eb) =>
300
+ eb.and(eb(idColumn.ormName, "=", externalId), eb(versionColumn.ormName, "=", version)),
301
+ );
302
+
303
+ if (typeof condition === "boolean") {
304
+ throw new Error("Condition is a boolean, but should be a condition object.");
305
+ }
306
+
307
+ return {
308
+ query: sqlCompiler.compileCheck(table, condition),
309
+ op: "check",
310
+ expectedAffectedRows: null,
311
+ expectedReturnedRows: 1, // Check that exactly 1 row was returned
312
+ };
313
+ }
314
+ }
@@ -0,0 +1,256 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { column, idColumn, referenceColumn, schema } from "../../../schema/create";
3
+ import { mapSelect, extendSelect } from "./select-builder";
4
+
5
+ describe("select-builder", () => {
6
+ const testSchema = schema((s) => {
7
+ return s
8
+ .addTable("users", (t) => {
9
+ return t
10
+ .addColumn("id", idColumn())
11
+ .addColumn("name", column("string"))
12
+ .addColumn("email", column("string"))
13
+ .addColumn("age", column("integer").nullable())
14
+ .addColumn("isActive", column("bool"))
15
+ .addColumn("createdAt", column("timestamp"));
16
+ })
17
+ .addTable("posts", (t) => {
18
+ return t
19
+ .addColumn("id", idColumn())
20
+ .addColumn("title", column("string"))
21
+ .addColumn("content", column("string"))
22
+ .addColumn("userId", referenceColumn())
23
+ .addColumn("viewCount", column("integer").defaultTo(0))
24
+ .addColumn("publishedAt", column("timestamp").nullable());
25
+ })
26
+ .addReference("author", {
27
+ type: "one",
28
+ from: { table: "posts", column: "userId" },
29
+ to: { table: "users", column: "id" },
30
+ });
31
+ });
32
+
33
+ const usersTable = testSchema.tables.users;
34
+ const postsTable = testSchema.tables.posts;
35
+
36
+ describe("mapSelect", () => {
37
+ it("should map select clause with array of keys", () => {
38
+ const result = mapSelect(["id", "name", "email"], usersTable);
39
+ expect(result).toEqual([
40
+ "users.id as id",
41
+ "users.name as name",
42
+ "users.email as email",
43
+ "users._internalId as _internalId",
44
+ "users._version as _version",
45
+ ]);
46
+ });
47
+
48
+ it("should map select all columns when true", () => {
49
+ const result = mapSelect(true, usersTable);
50
+ expect(result).toEqual([
51
+ "users.id as id",
52
+ "users.name as name",
53
+ "users.email as email",
54
+ "users.age as age",
55
+ "users.isActive as isActive",
56
+ "users.createdAt as createdAt",
57
+ "users._internalId as _internalId",
58
+ "users._version as _version",
59
+ ]);
60
+ });
61
+
62
+ it("should map select with relation prefix", () => {
63
+ const result = mapSelect(["id", "name"], usersTable, { relation: "author" });
64
+ expect(result).toEqual([
65
+ "users.id as author:id",
66
+ "users.name as author:name",
67
+ "users._internalId as author:_internalId",
68
+ "users._version as author:_version",
69
+ ]);
70
+ });
71
+
72
+ it("should map select with custom table name", () => {
73
+ const result = mapSelect(["id", "title"], postsTable, { tableName: "p" });
74
+ expect(result).toEqual([
75
+ "p.id as id",
76
+ "p.title as title",
77
+ "p._internalId as _internalId",
78
+ "p._version as _version",
79
+ ]);
80
+ });
81
+
82
+ it("should map select with both relation and custom table name", () => {
83
+ const result = mapSelect(["id", "title"], postsTable, {
84
+ relation: "posts",
85
+ tableName: "p",
86
+ });
87
+ expect(result).toEqual([
88
+ "p.id as posts:id",
89
+ "p.title as posts:title",
90
+ "p._internalId as posts:_internalId",
91
+ "p._version as posts:_version",
92
+ ]);
93
+ });
94
+
95
+ it("should handle single column select", () => {
96
+ const result = mapSelect(["name"], usersTable);
97
+ expect(result).toEqual([
98
+ "users.name as name",
99
+ "users._internalId as _internalId",
100
+ "users._version as _version",
101
+ ]);
102
+ });
103
+
104
+ it("should skip hidden columns when explicitly selecting", () => {
105
+ // When an array is passed, hidden columns should not be included in the select
106
+ // (unless they are in the array), but they should always be added at the end
107
+ const result = mapSelect(["name", "email"], usersTable);
108
+ // Should not duplicate _internalId or _version in the main select
109
+ expect(result).toEqual([
110
+ "users.name as name",
111
+ "users.email as email",
112
+ "users._internalId as _internalId",
113
+ "users._version as _version",
114
+ ]);
115
+ });
116
+
117
+ it("should always include hidden columns", () => {
118
+ // Hidden columns (_internalId, _version) should always be included
119
+ const result = mapSelect(["name"], usersTable);
120
+ expect(result.some((col) => col.includes("_internalId"))).toBe(true);
121
+ expect(result.some((col) => col.includes("_version"))).toBe(true);
122
+ });
123
+
124
+ it("should handle empty select array", () => {
125
+ const result = mapSelect([], usersTable);
126
+ // Should still include hidden columns
127
+ expect(result).toEqual(["users._internalId as _internalId", "users._version as _version"]);
128
+ });
129
+
130
+ it("should work with different table schemas", () => {
131
+ const result = mapSelect(["id", "title", "content"], postsTable);
132
+ expect(result).toEqual([
133
+ "posts.id as id",
134
+ "posts.title as title",
135
+ "posts.content as content",
136
+ "posts._internalId as _internalId",
137
+ "posts._version as _version",
138
+ ]);
139
+ });
140
+ });
141
+
142
+ describe("extendSelect", () => {
143
+ it("should extend array select with new key", () => {
144
+ const builder = extendSelect(["name", "email"]);
145
+ builder.extend("id");
146
+ const compiled = builder.compile();
147
+
148
+ expect(compiled.result).toEqual(["name", "email", "id"]);
149
+ expect(compiled.extendedKeys).toEqual(["id"]);
150
+ });
151
+
152
+ it("should not duplicate existing keys", () => {
153
+ const builder = extendSelect(["name", "email"]);
154
+ builder.extend("name");
155
+ const compiled = builder.compile();
156
+
157
+ expect(compiled.result).toEqual(["name", "email"]);
158
+ expect(compiled.extendedKeys).toEqual([]);
159
+ });
160
+
161
+ it("should handle true select clause", () => {
162
+ const builder = extendSelect(true);
163
+ builder.extend("id");
164
+ const compiled = builder.compile();
165
+
166
+ expect(compiled.result).toBe(true);
167
+ expect(compiled.extendedKeys).toEqual([]);
168
+ });
169
+
170
+ it("should track multiple extended keys", () => {
171
+ const builder = extendSelect(["name"]);
172
+ builder.extend("id");
173
+ builder.extend("email");
174
+ builder.extend("age");
175
+ const compiled = builder.compile();
176
+
177
+ expect(compiled.result).toEqual(["name", "id", "email", "age"]);
178
+ expect(compiled.extendedKeys).toEqual(["id", "email", "age"]);
179
+ });
180
+
181
+ it("should remove extended keys from record", () => {
182
+ const builder = extendSelect(["name", "email"]);
183
+ builder.extend("id");
184
+ const compiled = builder.compile();
185
+
186
+ const record = { id: "123", name: "John", email: "john@example.com", age: 30 };
187
+ compiled.removeExtendedKeys(record);
188
+
189
+ expect(record).toEqual({ name: "John", email: "john@example.com", age: 30 });
190
+ });
191
+
192
+ it("should not remove non-extended keys", () => {
193
+ const builder = extendSelect(["name", "email", "id"]);
194
+ builder.extend("age");
195
+ const compiled = builder.compile();
196
+
197
+ const record = { id: "123", name: "John", email: "john@example.com", age: 30 };
198
+ compiled.removeExtendedKeys(record);
199
+
200
+ expect(record).toEqual({ id: "123", name: "John", email: "john@example.com" });
201
+ });
202
+
203
+ it("should handle empty extended keys", () => {
204
+ const builder = extendSelect(["name", "email"]);
205
+ const compiled = builder.compile();
206
+
207
+ const record = { name: "John", email: "john@example.com" };
208
+ compiled.removeExtendedKeys(record);
209
+
210
+ expect(record).toEqual({ name: "John", email: "john@example.com" });
211
+ });
212
+
213
+ it("should handle multiple extends with duplicates", () => {
214
+ const builder = extendSelect(["name"]);
215
+ builder.extend("id");
216
+ builder.extend("email");
217
+ builder.extend("id"); // Duplicate
218
+ const compiled = builder.compile();
219
+
220
+ // Should not duplicate 'id'
221
+ expect(compiled.result).toEqual(["name", "id", "email"]);
222
+ expect(compiled.extendedKeys).toEqual(["id", "email"]);
223
+ });
224
+
225
+ it("should return mutated record from removeExtendedKeys", () => {
226
+ const builder = extendSelect(["name"]);
227
+ builder.extend("id");
228
+ const compiled = builder.compile();
229
+
230
+ const record = { id: "123", name: "John" };
231
+ const result = compiled.removeExtendedKeys(record);
232
+
233
+ // Should return the same record (mutated)
234
+ expect(result).toBe(record);
235
+ expect(result).toEqual({ name: "John" });
236
+ });
237
+
238
+ it("should handle extending with empty original select", () => {
239
+ const builder = extendSelect([]);
240
+ builder.extend("id");
241
+ builder.extend("name");
242
+ const compiled = builder.compile();
243
+
244
+ expect(compiled.result).toEqual(["id", "name"]);
245
+ expect(compiled.extendedKeys).toEqual(["id", "name"]);
246
+ });
247
+
248
+ it("should preserve original select order", () => {
249
+ const builder = extendSelect(["email", "name"]);
250
+ builder.extend("id");
251
+ const compiled = builder.compile();
252
+
253
+ expect(compiled.result).toEqual(["email", "name", "id"]);
254
+ });
255
+ });
256
+ });
@@ -0,0 +1,137 @@
1
+ import type { AnyTable } from "../../../schema/create";
2
+ import type { AnySelectClause } from "../../../query/simple-query-interface";
3
+
4
+ /**
5
+ * Maps a select clause to SQL column names with optional aliases.
6
+ *
7
+ * Converts application-level select clauses (either array of keys or "select all")
8
+ * into SQL-compatible column selections with proper aliasing for relations.
9
+ *
10
+ * @param select - The select clause (array of keys or true for all columns)
11
+ * @param table - The table schema containing column definitions
12
+ * @param options - Optional configuration
13
+ * @param options.relation - Relation name to prefix in aliases (for joined data)
14
+ * @param options.tableName - Override the table name in the SQL (defaults to table.name)
15
+ * @returns Array of SQL select strings in the format "tableName.columnName as alias"
16
+ * @internal
17
+ */
18
+ export function mapSelect(
19
+ select: AnySelectClause,
20
+ table: AnyTable,
21
+ options: {
22
+ relation?: string;
23
+ tableName?: string;
24
+ } = {},
25
+ ): string[] {
26
+ const { relation, tableName = table.name } = options;
27
+ const out: string[] = [];
28
+ const keys = Array.isArray(select) ? select : Object.keys(table.columns);
29
+
30
+ for (const key of keys) {
31
+ const col = table.columns[key];
32
+
33
+ // Skip hidden columns when explicitly selecting
34
+ if (Array.isArray(select) && col.isHidden) {
35
+ continue;
36
+ }
37
+
38
+ // Add the column to the select list
39
+ const name = relation ? `${relation}:${key}` : key;
40
+ out.push(`${tableName}.${col.name} as ${name}`);
41
+ }
42
+
43
+ // Always include hidden columns (for FragnoId construction with internal ID and version)
44
+ for (const key in table.columns) {
45
+ const col = table.columns[key];
46
+ if (col.isHidden && !keys.includes(key)) {
47
+ const name = relation ? `${relation}:${key}` : key;
48
+ out.push(`${tableName}.${col.name} as ${name}`);
49
+ }
50
+ }
51
+
52
+ return out;
53
+ }
54
+
55
+ /**
56
+ * Result type from compiling a select clause with extensions.
57
+ * @internal
58
+ */
59
+ export interface CompiledSelect {
60
+ /**
61
+ * The final select clause to use in the query
62
+ */
63
+ result: AnySelectClause;
64
+
65
+ /**
66
+ * Keys that were added to the select clause (not originally requested)
67
+ */
68
+ extendedKeys: string[];
69
+
70
+ /**
71
+ * Removes the extended keys from a record (mutates the record).
72
+ * Used to clean up keys that were only needed for join operations.
73
+ *
74
+ * @param record - The record to remove extended keys from
75
+ * @returns The same record with extended keys removed
76
+ */
77
+ removeExtendedKeys: (record: Record<string, unknown>) => Record<string, unknown>;
78
+ }
79
+
80
+ /**
81
+ * Builder for extending a select clause with additional keys.
82
+ * @internal
83
+ */
84
+ export interface SelectBuilder {
85
+ /**
86
+ * Adds a key to the select clause if not already present.
87
+ * Tracks which keys were added for later removal.
88
+ *
89
+ * @param key - The key to add to the select clause
90
+ */
91
+ extend: (key: string) => void;
92
+
93
+ /**
94
+ * Compiles the select clause into its final form.
95
+ *
96
+ * @returns The compiled select information
97
+ */
98
+ compile: () => CompiledSelect;
99
+ }
100
+
101
+ /**
102
+ * Creates a builder that can extend a select clause with additional keys.
103
+ *
104
+ * This is useful when you need to temporarily include columns for join operations
105
+ * or other internal processing, but don't want them in the final result.
106
+ *
107
+ * @param original - The original select clause from the user
108
+ * @returns A select builder with extend() and compile() methods
109
+ * @internal
110
+ */
111
+ export function extendSelect(original: AnySelectClause): SelectBuilder {
112
+ const select = Array.isArray(original) ? new Set(original) : true;
113
+ const extendedKeys: string[] = [];
114
+
115
+ return {
116
+ extend(key) {
117
+ if (select === true || select.has(key)) {
118
+ return;
119
+ }
120
+
121
+ select.add(key);
122
+ extendedKeys.push(key);
123
+ },
124
+ compile() {
125
+ return {
126
+ result: select instanceof Set ? Array.from(select) : true,
127
+ extendedKeys,
128
+ removeExtendedKeys(record) {
129
+ for (const key of extendedKeys) {
130
+ delete record[key];
131
+ }
132
+ return record;
133
+ },
134
+ };
135
+ },
136
+ };
137
+ }