@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
@@ -1,149 +0,0 @@
1
- import { SQL, StringChunk, sql } from "drizzle-orm";
2
- import { BaseSQLiteDatabase, SQLiteSyncDialect } from "drizzle-orm/sqlite-core";
3
-
4
- //#region src/adapters/drizzle/drizzle-uow-executor.ts
5
- function isSyncSQLite(db) {
6
- return db instanceof BaseSQLiteDatabase && "dialect" in db && db.dialect instanceof SQLiteSyncDialect;
7
- }
8
- function assertSyncSQLite(db) {
9
- if (!isSyncSQLite(db)) throw new Error("Expected synchronous SQLite database (better-sqlite3)");
10
- }
11
- function postgresToSQL(sqlString, params) {
12
- const placeholderRegex = /\$(\d+)/g;
13
- const queryChunks = [];
14
- let lastIndex = 0;
15
- let match;
16
- while ((match = placeholderRegex.exec(sqlString)) !== null) {
17
- const textBefore = sqlString.substring(lastIndex, match.index);
18
- if (textBefore) queryChunks.push(new StringChunk(textBefore));
19
- const paramIndex = parseInt(match[1], 10) - 1;
20
- queryChunks.push(sql.param(params[paramIndex]));
21
- lastIndex = match.index + match[0].length;
22
- }
23
- const textAfter = sqlString.substring(lastIndex);
24
- if (textAfter) queryChunks.push(new StringChunk(textAfter));
25
- return queryChunks;
26
- }
27
- function sqliteToSQL(sqlString, params) {
28
- const chunks = [];
29
- let currentIndex = 0;
30
- const parts = sqlString.split("?");
31
- for (let i = 0; i < parts.length; i++) {
32
- if (parts[i]) chunks.push(new StringChunk(parts[i]));
33
- if (i < parts.length - 1 && currentIndex < params.length) chunks.push(sql.param(params[currentIndex++]));
34
- }
35
- return chunks;
36
- }
37
- function toSQL(query, provider) {
38
- const { sql: sqlString, params } = query;
39
- return new SQL(provider === "sqlite" ? sqliteToSQL(sqlString, params) : postgresToSQL(sqlString, params));
40
- }
41
- function getAffectedRows(result) {
42
- if (Array.isArray(result)) return result.length;
43
- if (result && typeof result === "object") {
44
- if ("rowsAffected" in result && typeof result["rowsAffected"] === "number") return result["rowsAffected"];
45
- if ("affectedRows" in result && typeof result["affectedRows"] === "number") return result["affectedRows"];
46
- if ("rowCount" in result && (typeof result["rowCount"] === "number" || typeof result["rowCount"] === "bigint")) {
47
- const rowCount = result["rowCount"];
48
- if (rowCount > Number.MAX_SAFE_INTEGER) throw new Error(`rowCount BigInt value ${rowCount.toString()} exceeds JS safe integer range`);
49
- return Number(rowCount);
50
- }
51
- if ("changes" in result && typeof result["changes"] === "number") return result["changes"];
52
- }
53
- throw new Error(`Unable to determine affected rows from result: ${JSON.stringify(result)}`);
54
- }
55
- async function executeInTransaction(db, provider, syncExecutor, asyncExecutor) {
56
- if (provider === "sqlite" && isSyncSQLite(db)) {
57
- assertSyncSQLite(db);
58
- db.transaction(() => syncExecutor(db));
59
- } else await db.transaction(async (tx) => await asyncExecutor(tx));
60
- }
61
- function extractCreatedInternalId(result) {
62
- if (result && typeof result === "object" && "lastInsertRowid" in result) {
63
- if (typeof result.lastInsertRowid === "bigint") return result.lastInsertRowid;
64
- if (typeof result.lastInsertRowid === "number") return BigInt(result.lastInsertRowid);
65
- throw new Error(`Unexpected lastInsertRowid type: ${typeof result.lastInsertRowid}`);
66
- }
67
- if (Array.isArray(result) && result.length > 0) {
68
- const row = result[0];
69
- if ("_internalId" in row || "_internal_id" in row) return row["_internalId"] ?? row["_internal_id"];
70
- }
71
- return null;
72
- }
73
- function validateAffectedRows(result, expected) {
74
- const actual = getAffectedRows(result);
75
- if (actual !== expected) throw new Error(`Version conflict: expected ${expected} rows affected, but got ${actual}`);
76
- }
77
- /**
78
- * Execute the retrieval phase of a Unit of Work using Drizzle
79
- *
80
- * All retrieval queries are executed inside a single transaction to ensure
81
- * snapshot isolation - all reads see a consistent view of the database.
82
- */
83
- async function executeDrizzleRetrievalPhase(db, retrievalBatch, provider) {
84
- if (retrievalBatch.length === 0) return [];
85
- const retrievalResults = [];
86
- await executeInTransaction(db, provider, (syncDb) => {
87
- for (const query of retrievalBatch) {
88
- const sqlObj = toSQL(query, provider);
89
- const result = {
90
- rows: syncDb.all(sqlObj),
91
- affectedRows: 0
92
- };
93
- retrievalResults.push(result);
94
- }
95
- }, async (tx) => {
96
- for (const query of retrievalBatch) {
97
- const sqlObj = toSQL(query, provider);
98
- const executeMethod = tx.execute ?? tx.run;
99
- if (!executeMethod) throw new Error("Transaction object has neither execute nor run method");
100
- const result = await executeMethod.call(tx, sqlObj);
101
- retrievalResults.push(result);
102
- }
103
- });
104
- return retrievalResults;
105
- }
106
- /**
107
- * Execute the mutation phase of a Unit of Work using Drizzle
108
- *
109
- * All mutation queries are executed in a transaction with optimistic locking.
110
- * If any version check fails, the entire transaction is rolled back and
111
- * success=false is returned.
112
- */
113
- async function executeDrizzleMutationPhase(db, mutationBatch, provider) {
114
- if (mutationBatch.length === 0) return {
115
- success: true,
116
- createdInternalIds: []
117
- };
118
- const createdInternalIds = [];
119
- try {
120
- await executeInTransaction(db, provider, (syncDb) => {
121
- for (const { query, expectedAffectedRows } of mutationBatch) {
122
- const sqlObj = toSQL(query, provider);
123
- const result = syncDb.run(sqlObj);
124
- if (expectedAffectedRows === null) createdInternalIds.push(extractCreatedInternalId(result));
125
- else validateAffectedRows(result, expectedAffectedRows);
126
- }
127
- }, async (tx) => {
128
- for (const { query, expectedAffectedRows } of mutationBatch) {
129
- const sqlObj = toSQL(query, provider);
130
- const executeMethod = tx.execute ?? tx.run;
131
- if (!executeMethod) throw new Error("Transaction object has neither execute nor run method");
132
- const result = await executeMethod.call(tx, sqlObj);
133
- if (expectedAffectedRows === null) createdInternalIds.push(extractCreatedInternalId(result));
134
- else validateAffectedRows(result, expectedAffectedRows);
135
- }
136
- });
137
- return {
138
- success: true,
139
- createdInternalIds
140
- };
141
- } catch (error) {
142
- if (error instanceof Error && error.message.includes("Version conflict")) return { success: false };
143
- throw error;
144
- }
145
- }
146
-
147
- //#endregion
148
- export { executeDrizzleMutationPhase, executeDrizzleRetrievalPhase };
149
- //# sourceMappingURL=drizzle-uow-executor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"drizzle-uow-executor.js","names":["queryChunks: SQLChunk[]","match: RegExpExecArray | null","chunks: SQLChunk[]","retrievalResults: DrizzleResult[]","result: DrizzleResult","createdInternalIds: (bigint | null)[]"],"sources":["../../../src/adapters/drizzle/drizzle-uow-executor.ts"],"sourcesContent":["import { SQL, StringChunk, sql, type SQLChunk } from \"drizzle-orm\";\nimport type { CompiledMutation, MutationResult } from \"../../query/unit-of-work\";\nimport type { DBType } from \"./shared\";\nimport type { DrizzleCompiledQuery } from \"./drizzle-uow-compiler\";\nimport type { DrizzleResult } from \"./shared\";\nimport { BaseSQLiteDatabase } from \"drizzle-orm/sqlite-core\";\nimport { SQLiteSyncDialect } from \"drizzle-orm/sqlite-core\";\n\ntype SyncSQLiteDB = BaseSQLiteDatabase<\n \"sync\",\n unknown,\n Record<string, never>,\n Record<string, never>\n>;\n\nfunction isSyncSQLite(db: unknown): boolean {\n return (\n db instanceof BaseSQLiteDatabase &&\n \"dialect\" in db &&\n (db as { dialect?: unknown }).dialect instanceof SQLiteSyncDialect\n );\n}\n\nfunction assertSyncSQLite(db: unknown): asserts db is SyncSQLiteDB {\n if (!isSyncSQLite(db)) {\n throw new Error(\"Expected synchronous SQLite database (better-sqlite3)\");\n }\n}\n\nfunction postgresToSQL(sqlString: string, params: unknown[]): SQLChunk[] {\n const placeholderRegex = /\\$(\\d+)/g;\n const queryChunks: SQLChunk[] = [];\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = placeholderRegex.exec(sqlString)) !== null) {\n const textBefore = sqlString.substring(lastIndex, match.index);\n if (textBefore) {\n queryChunks.push(new StringChunk(textBefore));\n }\n\n const paramIndex = parseInt(match[1]!, 10) - 1;\n queryChunks.push(sql.param(params[paramIndex]));\n\n lastIndex = match.index + match[0].length;\n }\n\n const textAfter = sqlString.substring(lastIndex);\n if (textAfter) {\n queryChunks.push(new StringChunk(textAfter));\n }\n\n return queryChunks;\n}\n\nfunction sqliteToSQL(sqlString: string, params: unknown[]): SQLChunk[] {\n const chunks: SQLChunk[] = [];\n let currentIndex = 0;\n\n const parts = sqlString.split(\"?\");\n for (let i = 0; i < parts.length; i++) {\n if (parts[i]) {\n chunks.push(new StringChunk(parts[i]));\n }\n if (i < parts.length - 1 && currentIndex < params.length) {\n chunks.push(sql.param(params[currentIndex++]));\n }\n }\n\n return chunks;\n}\n\nfunction toSQL(query: DrizzleCompiledQuery, provider: \"sqlite\" | \"mysql\" | \"postgresql\"): SQL {\n const { sql: sqlString, params } = query;\n\n const queryChunks =\n provider === \"sqlite\" ? sqliteToSQL(sqlString, params) : postgresToSQL(sqlString, params);\n\n return new SQL(queryChunks);\n}\n\nfunction getAffectedRows(result: unknown): number {\n if (Array.isArray(result)) {\n return result.length;\n }\n\n if (result && typeof result === \"object\") {\n // libsql uses rowsAffected\n if (\"rowsAffected\" in result && typeof result[\"rowsAffected\"] === \"number\") {\n return result[\"rowsAffected\"];\n }\n\n if (\"affectedRows\" in result && typeof result[\"affectedRows\"] === \"number\") {\n return result[\"affectedRows\"];\n }\n\n if (\n \"rowCount\" in result &&\n (typeof result[\"rowCount\"] === \"number\" || typeof result[\"rowCount\"] === \"bigint\")\n ) {\n const rowCount = result[\"rowCount\"];\n if (rowCount > Number.MAX_SAFE_INTEGER) {\n throw new Error(\n `rowCount BigInt value ${rowCount.toString()} exceeds JS safe integer range`,\n );\n }\n return Number(rowCount);\n }\n\n if (\"changes\" in result && typeof result[\"changes\"] === \"number\") {\n return result[\"changes\"];\n }\n }\n\n throw new Error(`Unable to determine affected rows from result: ${JSON.stringify(result)}`);\n}\n\nasync function executeInTransaction(\n db: DBType,\n provider: \"sqlite\" | \"mysql\" | \"postgresql\",\n syncExecutor: (db: SyncSQLiteDB) => void,\n asyncExecutor: (tx: {\n execute?: (sql: SQL) => Promise<unknown>;\n run?: (sql: SQL) => Promise<unknown>;\n }) => Promise<void>,\n): Promise<void> {\n if (provider === \"sqlite\" && isSyncSQLite(db)) {\n assertSyncSQLite(db);\n db.transaction(() => syncExecutor(db));\n } else {\n await db.transaction(\n async (tx) =>\n await asyncExecutor(\n tx as { execute?: (sql: SQL) => Promise<unknown>; run?: (sql: SQL) => Promise<unknown> },\n ),\n );\n }\n}\n\nfunction extractCreatedInternalId(result: unknown): bigint | null {\n if (result && typeof result === \"object\" && \"lastInsertRowid\" in result) {\n if (typeof result.lastInsertRowid === \"bigint\") {\n return result.lastInsertRowid;\n }\n\n if (typeof result.lastInsertRowid === \"number\") {\n return BigInt(result.lastInsertRowid);\n }\n\n throw new Error(`Unexpected lastInsertRowid type: ${typeof result.lastInsertRowid}`);\n }\n\n if (Array.isArray(result) && result.length > 0) {\n const row = result[0] as Record<string, unknown>;\n if (\"_internalId\" in row || \"_internal_id\" in row) {\n return (row[\"_internalId\"] ?? row[\"_internal_id\"]) as bigint;\n }\n }\n\n return null;\n}\n\nfunction validateAffectedRows(result: unknown, expected: number): void {\n const actual = getAffectedRows(result);\n if (actual !== expected) {\n throw new Error(`Version conflict: expected ${expected} rows affected, but got ${actual}`);\n }\n}\n\n/**\n * Execute the retrieval phase of a Unit of Work using Drizzle\n *\n * All retrieval queries are executed inside a single transaction to ensure\n * snapshot isolation - all reads see a consistent view of the database.\n */\nexport async function executeDrizzleRetrievalPhase(\n db: DBType,\n retrievalBatch: DrizzleCompiledQuery[],\n provider: \"sqlite\" | \"mysql\" | \"postgresql\",\n): Promise<DrizzleResult[]> {\n if (retrievalBatch.length === 0) {\n return [];\n }\n\n const retrievalResults: DrizzleResult[] = [];\n\n await executeInTransaction(\n db,\n provider,\n (syncDb) => {\n for (const query of retrievalBatch) {\n const sqlObj = toSQL(query, provider);\n const rows = syncDb.all(sqlObj as never) as Record<string, unknown>[];\n const result: DrizzleResult = { rows, affectedRows: 0 };\n retrievalResults.push(result);\n }\n },\n async (tx) => {\n for (const query of retrievalBatch) {\n const sqlObj = toSQL(query, provider);\n // Fallback to run when execute is not available (e.g., libsql)\n const executeMethod = tx.execute ?? tx.run;\n if (!executeMethod) {\n throw new Error(\"Transaction object has neither execute nor run method\");\n }\n const result = (await executeMethod.call(tx, sqlObj)) as DrizzleResult;\n retrievalResults.push(result);\n }\n },\n );\n\n return retrievalResults;\n}\n\n/**\n * Execute the mutation phase of a Unit of Work using Drizzle\n *\n * All mutation queries are executed in a transaction with optimistic locking.\n * If any version check fails, the entire transaction is rolled back and\n * success=false is returned.\n */\nexport async function executeDrizzleMutationPhase(\n db: DBType,\n mutationBatch: CompiledMutation<DrizzleCompiledQuery>[],\n provider: \"sqlite\" | \"mysql\" | \"postgresql\",\n): Promise<MutationResult> {\n if (mutationBatch.length === 0) {\n return { success: true, createdInternalIds: [] };\n }\n\n const createdInternalIds: (bigint | null)[] = [];\n\n try {\n await executeInTransaction(\n db,\n provider,\n (syncDb) => {\n for (const { query, expectedAffectedRows } of mutationBatch) {\n const sqlObj = toSQL(query, provider);\n // Type assertion needed due to drizzle-orm version mismatch in dependencies\n const result = syncDb.run(sqlObj as never);\n\n if (expectedAffectedRows === null) {\n createdInternalIds.push(extractCreatedInternalId(result));\n } else {\n validateAffectedRows(result, expectedAffectedRows);\n }\n }\n },\n async (tx) => {\n for (const { query, expectedAffectedRows } of mutationBatch) {\n const sqlObj = toSQL(query, provider);\n // Fallback to run when execute is not available (e.g., libsql)\n const executeMethod = tx.execute ?? tx.run;\n if (!executeMethod) {\n throw new Error(\"Transaction object has neither execute nor run method\");\n }\n const result = await executeMethod.call(tx, sqlObj);\n\n if (expectedAffectedRows === null) {\n createdInternalIds.push(extractCreatedInternalId(result));\n } else {\n validateAffectedRows(result, expectedAffectedRows);\n }\n }\n },\n );\n\n return { success: true, createdInternalIds };\n } catch (error) {\n if (error instanceof Error && error.message.includes(\"Version conflict\")) {\n return { success: false };\n }\n throw error;\n }\n}\n"],"mappings":"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"}
@@ -1,28 +0,0 @@
1
- //#region src/adapters/drizzle/join-column-utils.ts
2
- /**
3
- * Determine the ordered list of columns for a join selection.
4
- *
5
- * This logic is shared between the compiler (which builds the SQL)
6
- * and the decoder (which maps the result array back to objects).
7
- * The order MUST match exactly for the decoder to work correctly.
8
- *
9
- * @param targetTable - The table being joined
10
- * @param select - Selection options (true for all columns, or array of column keys)
11
- * @returns Array of column ORM names in the order they appear in the SQL/result
12
- */
13
- function getOrderedJoinColumns(targetTable, select) {
14
- const orderedColumns = [];
15
- if (select === true) for (const col of Object.values(targetTable.columns)) orderedColumns.push(col.ormName);
16
- else {
17
- for (const colKey of select) {
18
- const col = targetTable.columns[colKey];
19
- if (col) orderedColumns.push(col.ormName);
20
- }
21
- for (const col of Object.values(targetTable.columns)) if (col && col.isHidden && !orderedColumns.includes(col.ormName)) orderedColumns.push(col.ormName);
22
- }
23
- return orderedColumns;
24
- }
25
-
26
- //#endregion
27
- export { getOrderedJoinColumns };
28
- //# sourceMappingURL=join-column-utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"join-column-utils.js","names":["orderedColumns: string[]"],"sources":["../../../src/adapters/drizzle/join-column-utils.ts"],"sourcesContent":["import type { AnyTable } from \"../../schema/create\";\n\n/**\n * Determine the ordered list of columns for a join selection.\n *\n * This logic is shared between the compiler (which builds the SQL)\n * and the decoder (which maps the result array back to objects).\n * The order MUST match exactly for the decoder to work correctly.\n *\n * @param targetTable - The table being joined\n * @param select - Selection options (true for all columns, or array of column keys)\n * @returns Array of column ORM names in the order they appear in the SQL/result\n */\nexport function getOrderedJoinColumns(targetTable: AnyTable, select: true | string[]): string[] {\n const orderedColumns: string[] = [];\n\n if (select === true) {\n // All columns selected - iterate in the order they appear in targetTable.columns\n for (const col of Object.values(targetTable.columns)) {\n orderedColumns.push(col.ormName);\n }\n } else {\n // Specific columns selected\n for (const colKey of select) {\n const col = targetTable.columns[colKey];\n if (col) {\n orderedColumns.push(col.ormName);\n }\n }\n // Add hidden columns at the end (for FragnoId construction)\n for (const col of Object.values(targetTable.columns)) {\n if (col && col.isHidden && !orderedColumns.includes(col.ormName)) {\n orderedColumns.push(col.ormName);\n }\n }\n }\n\n return orderedColumns;\n}\n"],"mappings":";;;;;;;;;;;;AAaA,SAAgB,sBAAsB,aAAuB,QAAmC;CAC9F,MAAMA,iBAA2B,EAAE;AAEnC,KAAI,WAAW,KAEb,MAAK,MAAM,OAAO,OAAO,OAAO,YAAY,QAAQ,CAClD,gBAAe,KAAK,IAAI,QAAQ;MAE7B;AAEL,OAAK,MAAM,UAAU,QAAQ;GAC3B,MAAM,MAAM,YAAY,QAAQ;AAChC,OAAI,IACF,gBAAe,KAAK,IAAI,QAAQ;;AAIpC,OAAK,MAAM,OAAO,OAAO,OAAO,YAAY,QAAQ,CAClD,KAAI,OAAO,IAAI,YAAY,CAAC,eAAe,SAAS,IAAI,QAAQ,CAC9D,gBAAe,KAAK,IAAI,QAAQ;;AAKtC,QAAO"}
@@ -1,14 +0,0 @@
1
- import "drizzle-orm";
2
-
3
- //#region src/adapters/drizzle/shared.d.ts
4
-
5
- /**
6
- * Maps logical table names (used by fragment authors) to physical table names (with namespace suffix)
7
- */
8
- interface TableNameMapper {
9
- toPhysical(logicalName: string): string;
10
- toLogical(physicalName: string): string;
11
- }
12
- //#endregion
13
- export { TableNameMapper };
14
- //# sourceMappingURL=shared.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shared.d.ts","names":[],"sources":["../../../src/adapters/drizzle/shared.ts"],"sourcesContent":[],"mappings":";;;;;;;UA2BiB,eAAA"}
@@ -1,35 +0,0 @@
1
- import "drizzle-orm";
2
-
3
- //#region src/adapters/drizzle/shared.ts
4
- function parseDrizzle(drizzle) {
5
- const db = drizzle;
6
- const drizzleTables = db._.fullSchema;
7
- if (!drizzleTables || Object.keys(drizzleTables).length === 0) throw new Error("Drizzle adapter requires query mode, make sure to configure it following their guide: https://orm.drizzle.team/docs/rqb.");
8
- return [db, drizzleTables];
9
- }
10
- /**
11
- * Sanitize a namespace to be a valid JavaScript identifier
12
- * Replaces hyphens and other invalid characters with underscores
13
- */
14
- function sanitizeNamespace(namespace) {
15
- return namespace.replace(/[^a-zA-Z0-9_]/g, "_");
16
- }
17
- /**
18
- * Creates a table name mapper for a given namespace.
19
- * Physical names have format: {logicalName}_{sanitizedNamespace}
20
- * The namespace is sanitized to match TypeScript export names used in the schema
21
- */
22
- function createTableNameMapper(namespace) {
23
- const sanitized = sanitizeNamespace(namespace);
24
- return {
25
- toPhysical: (logicalName) => `${logicalName}_${sanitized}`,
26
- toLogical: (physicalName) => {
27
- if (physicalName.endsWith(`_${sanitized}`)) return physicalName.slice(0, -(sanitized.length + 1));
28
- return physicalName;
29
- }
30
- };
31
- }
32
-
33
- //#endregion
34
- export { createTableNameMapper, parseDrizzle, sanitizeNamespace };
35
- //# sourceMappingURL=shared.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"shared.js","names":[],"sources":["../../../src/adapters/drizzle/shared.ts"],"sourcesContent":["import * as Drizzle from \"drizzle-orm\";\nimport type * as MySQL from \"drizzle-orm/mysql-core\";\n\nexport type TableType = MySQL.MySqlTableWithColumns<MySQL.TableConfig>;\nexport type ColumnType = MySQL.AnyMySqlColumn;\nexport type DBType = MySQL.MySqlDatabase<\n MySQL.MySqlQueryResultHKT,\n MySQL.PreparedQueryHKTBase,\n Record<string, unknown>,\n Drizzle.TablesRelationalConfig\n>;\n\nexport function parseDrizzle(drizzle: unknown) {\n const db = drizzle as DBType;\n const drizzleTables = db._.fullSchema as Record<string, TableType>;\n if (!drizzleTables || Object.keys(drizzleTables).length === 0) {\n throw new Error(\n \"Drizzle adapter requires query mode, make sure to configure it following their guide: https://orm.drizzle.team/docs/rqb.\",\n );\n }\n\n return [db, drizzleTables] as const;\n}\n\n/**\n * Maps logical table names (used by fragment authors) to physical table names (with namespace suffix)\n */\nexport interface TableNameMapper {\n toPhysical(logicalName: string): string;\n toLogical(physicalName: string): string;\n}\n\n/**\n * Sanitize a namespace to be a valid JavaScript identifier\n * Replaces hyphens and other invalid characters with underscores\n */\nexport function sanitizeNamespace(namespace: string): string {\n return namespace.replace(/[^a-zA-Z0-9_]/g, \"_\");\n}\n\n/**\n * Creates a table name mapper for a given namespace.\n * Physical names have format: {logicalName}_{sanitizedNamespace}\n * The namespace is sanitized to match TypeScript export names used in the schema\n */\nexport function createTableNameMapper(namespace: string): TableNameMapper {\n const sanitized = sanitizeNamespace(namespace);\n return {\n toPhysical: (logicalName: string) => `${logicalName}_${sanitized}`,\n toLogical: (physicalName: string) => {\n if (physicalName.endsWith(`_${sanitized}`)) {\n return physicalName.slice(0, -(sanitized.length + 1));\n }\n return physicalName;\n },\n };\n}\n\nexport interface DrizzleResult {\n rows: Record<string, unknown>[];\n affectedRows: number;\n}\n"],"mappings":";;;AAYA,SAAgB,aAAa,SAAkB;CAC7C,MAAM,KAAK;CACX,MAAM,gBAAgB,GAAG,EAAE;AAC3B,KAAI,CAAC,iBAAiB,OAAO,KAAK,cAAc,CAAC,WAAW,EAC1D,OAAM,IAAI,MACR,2HACD;AAGH,QAAO,CAAC,IAAI,cAAc;;;;;;AAe5B,SAAgB,kBAAkB,WAA2B;AAC3D,QAAO,UAAU,QAAQ,kBAAkB,IAAI;;;;;;;AAQjD,SAAgB,sBAAsB,WAAoC;CACxE,MAAM,YAAY,kBAAkB,UAAU;AAC9C,QAAO;EACL,aAAa,gBAAwB,GAAG,YAAY,GAAG;EACvD,YAAY,iBAAyB;AACnC,OAAI,aAAa,SAAS,IAAI,YAAY,CACxC,QAAO,aAAa,MAAM,GAAG,EAAE,UAAU,SAAS,GAAG;AAEvD,UAAO;;EAEV"}
@@ -1,41 +0,0 @@
1
- //#region src/adapters/kysely/kysely-connection-pool.ts
2
- /**
3
- * Creates a Kysely-specific connection pool with proper cleanup.
4
- * Calls db.destroy() when the pool is closed to properly release database connections.
5
- */
6
- function createKyselyConnectionPool(dbOrFactory) {
7
- let cachedDb;
8
- let initPromise;
9
- const ensureInitialized = async () => {
10
- if (cachedDb) return cachedDb;
11
- if (!initPromise) initPromise = (async () => {
12
- const db = typeof dbOrFactory === "function" ? await dbOrFactory() : dbOrFactory;
13
- cachedDb = db;
14
- return db;
15
- })();
16
- return initPromise;
17
- };
18
- if (typeof dbOrFactory === "function") ensureInitialized();
19
- else cachedDb = dbOrFactory;
20
- return {
21
- async connect() {
22
- return {
23
- db: await ensureInitialized(),
24
- release: async () => {}
25
- };
26
- },
27
- getDatabaseSync() {
28
- if (!cachedDb) throw new Error("Cannot get database synchronously: database not initialized.");
29
- return cachedDb;
30
- },
31
- async close() {
32
- if (cachedDb) await cachedDb.destroy();
33
- cachedDb = void 0;
34
- initPromise = void 0;
35
- }
36
- };
37
- }
38
-
39
- //#endregion
40
- export { createKyselyConnectionPool };
41
- //# sourceMappingURL=kysely-connection-pool.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"kysely-connection-pool.js","names":["cachedDb: KyselyAny | undefined","initPromise: Promise<KyselyAny> | undefined"],"sources":["../../../src/adapters/kysely/kysely-connection-pool.ts"],"sourcesContent":["import type { Kysely } from \"kysely\";\nimport type { ConnectionPool } from \"../../shared/connection-pool\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype KyselyAny = Kysely<any>;\n\n/**\n * Creates a Kysely-specific connection pool with proper cleanup.\n * Calls db.destroy() when the pool is closed to properly release database connections.\n */\nexport function createKyselyConnectionPool(\n dbOrFactory: KyselyAny | (() => KyselyAny | Promise<KyselyAny>),\n): ConnectionPool<KyselyAny> {\n let cachedDb: KyselyAny | undefined;\n let initPromise: Promise<KyselyAny> | undefined;\n\n const ensureInitialized = async (): Promise<KyselyAny> => {\n if (cachedDb) {\n return cachedDb;\n }\n\n if (!initPromise) {\n initPromise = (async () => {\n const db =\n typeof dbOrFactory === \"function\"\n ? await (dbOrFactory as () => KyselyAny | Promise<KyselyAny>)()\n : dbOrFactory;\n cachedDb = db;\n return db;\n })();\n }\n\n return initPromise;\n };\n\n // Eagerly start initialization if it's a factory function\n if (typeof dbOrFactory === \"function\") {\n void ensureInitialized();\n } else {\n // Direct instance - cache it immediately\n cachedDb = dbOrFactory;\n }\n\n return {\n async connect() {\n const db = await ensureInitialized();\n\n return {\n db,\n release: async () => {},\n };\n },\n\n getDatabaseSync() {\n if (!cachedDb) {\n throw new Error(\"Cannot get database synchronously: database not initialized.\");\n }\n return cachedDb;\n },\n\n async close() {\n if (cachedDb) {\n // Properly destroy Kysely instance to close all connections\n await cachedDb.destroy();\n }\n cachedDb = undefined;\n initPromise = undefined;\n },\n };\n}\n"],"mappings":";;;;;AAUA,SAAgB,2BACd,aAC2B;CAC3B,IAAIA;CACJ,IAAIC;CAEJ,MAAM,oBAAoB,YAAgC;AACxD,MAAI,SACF,QAAO;AAGT,MAAI,CAAC,YACH,gBAAe,YAAY;GACzB,MAAM,KACJ,OAAO,gBAAgB,aACnB,MAAO,aAAsD,GAC7D;AACN,cAAW;AACX,UAAO;MACL;AAGN,SAAO;;AAIT,KAAI,OAAO,gBAAgB,WACzB,CAAK,mBAAmB;KAGxB,YAAW;AAGb,QAAO;EACL,MAAM,UAAU;AAGd,UAAO;IACL,IAHS,MAAM,mBAAmB;IAIlC,SAAS,YAAY;IACtB;;EAGH,kBAAkB;AAChB,OAAI,CAAC,SACH,OAAM,IAAI,MAAM,+DAA+D;AAEjF,UAAO;;EAGT,MAAM,QAAQ;AACZ,OAAI,SAEF,OAAM,SAAS,SAAS;AAE1B,cAAW;AACX,iBAAc;;EAEjB"}
@@ -1,321 +0,0 @@
1
- import { Column } from "../../schema/create.js";
2
- import { serialize } from "../../schema/serialize.js";
3
- import { ReferenceSubquery, encodeValues } from "../../query/result-transform.js";
4
- import { sql } from "kysely";
5
-
6
- //#region src/adapters/kysely/kysely-query-builder.ts
7
- /**
8
- * Returns the fully qualified SQL name for a column (table.column).
9
- *
10
- * @param column - The column to get the full name for
11
- * @param mapper - Optional table name mapper for namespace prefixing
12
- * @returns The fully qualified SQL name in the format "tableName.columnName"
13
- * @internal
14
- *
15
- * @example
16
- * ```ts
17
- * fullSQLName(userTable.columns.email)
18
- * // Returns: "users.email"
19
- * ```
20
- */
21
- function fullSQLName(column, mapper) {
22
- return `${mapper ? mapper.toPhysical(column.tableName) : column.tableName}.${column.name}`;
23
- }
24
- /**
25
- * Builds a WHERE clause expression from a Condition tree.
26
- *
27
- * Recursively processes condition objects to build Kysely WHERE expressions.
28
- * Handles comparison operators, logical AND/OR/NOT, and special string operators
29
- * like "contains", "starts with", and "ends with".
30
- *
31
- * @param condition - The condition tree to build the WHERE clause from
32
- * @param eb - Kysely expression builder for constructing SQL expressions
33
- * @param provider - The SQL provider (affects SQL generation)
34
- * @param mapper - Optional table name mapper for namespace prefixing
35
- * @param table - The table being queried (used for resolving reference columns)
36
- * @returns A Kysely expression wrapper representing the WHERE clause
37
- * @internal
38
- *
39
- * @example
40
- * ```ts
41
- * const condition = {
42
- * type: "compare",
43
- * a: userTable.columns.name,
44
- * operator: "contains",
45
- * b: "john"
46
- * };
47
- * const whereClause = buildWhere(condition, eb, 'postgresql');
48
- * ```
49
- */
50
- function buildWhere(condition, eb, provider, mapper, table) {
51
- if (condition.type === "compare") {
52
- const left = condition.a;
53
- const op = condition.operator;
54
- let val = condition.b;
55
- if (!(val instanceof Column)) if (left.role === "reference" && typeof val === "string" && table) {
56
- const relation = Object.values(table.relations).find((rel) => rel.on.some(([localCol]) => localCol === left.ormName));
57
- if (relation) {
58
- const refTable = relation.table;
59
- const internalIdCol = refTable.getInternalIdColumn();
60
- const idCol = refTable.getIdColumn();
61
- const physicalTableName = mapper ? mapper.toPhysical(refTable.ormName) : refTable.ormName;
62
- val = eb.selectFrom(physicalTableName).select(internalIdCol.name).where(idCol.name, "=", val).limit(1);
63
- }
64
- } else val = serialize(val, left, provider);
65
- let v;
66
- let rhs;
67
- switch (op) {
68
- case "contains":
69
- v = "like";
70
- rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, mapper))}, '%')` : `%${val}%`;
71
- break;
72
- case "not contains":
73
- v = "not like";
74
- rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, mapper))}, '%')` : `%${val}%`;
75
- break;
76
- case "starts with":
77
- v = "like";
78
- rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLName(val, mapper))}, '%')` : `${val}%`;
79
- break;
80
- case "not starts with":
81
- v = "not like";
82
- rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLName(val, mapper))}, '%')` : `${val}%`;
83
- break;
84
- case "ends with":
85
- v = "like";
86
- rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, mapper))})` : `%${val}`;
87
- break;
88
- case "not ends with":
89
- v = "not like";
90
- rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, mapper))})` : `%${val}`;
91
- break;
92
- default:
93
- v = op;
94
- rhs = val instanceof Column ? eb.ref(fullSQLName(val, mapper)) : val;
95
- }
96
- return eb(fullSQLName(left, mapper), v, rhs);
97
- }
98
- if (condition.type === "and") return eb.and(condition.items.map((v) => buildWhere(v, eb, provider, mapper, table)));
99
- if (condition.type === "not") return eb.not(buildWhere(condition.item, eb, provider, mapper, table));
100
- return eb.or(condition.items.map((v) => buildWhere(v, eb, provider, mapper, table)));
101
- }
102
- /**
103
- * Maps a select clause to SQL column names with optional aliases.
104
- *
105
- * Converts application-level select clauses (either array of keys or "select all")
106
- * into SQL-compatible column selections with proper aliasing for relations.
107
- *
108
- * @param select - The select clause (array of keys or true for all columns)
109
- * @param table - The table schema containing column definitions
110
- * @param options - Optional configuration
111
- * @param options.relation - Relation name to prefix in aliases (for joined data)
112
- * @param options.tableName - Override the table name in the SQL (defaults to table.name)
113
- * @returns Array of SQL select strings in the format "tableName.columnName as alias"
114
- * @internal
115
- *
116
- * @example
117
- * ```ts
118
- * mapSelect(['id', 'name'], userTable)
119
- * // Returns: ['users.id as id', 'users.name as name']
120
- *
121
- * mapSelect(['title'], postTable, { relation: 'posts' })
122
- * // Returns: ['posts.title as posts:title']
123
- * ```
124
- */
125
- function mapSelect(select, table, options = {}) {
126
- const { relation, tableName = table.name } = options;
127
- const out = [];
128
- const keys = Array.isArray(select) ? select : Object.keys(table.columns);
129
- for (const key of keys) {
130
- const col = table.columns[key];
131
- if (Array.isArray(select) && col.isHidden) continue;
132
- const name = relation ? `${relation}:${key}` : key;
133
- out.push(`${tableName}.${col.name} as ${name}`);
134
- }
135
- for (const key in table.columns) {
136
- const col = table.columns[key];
137
- if (col.isHidden && !keys.includes(key)) {
138
- const name = relation ? `${relation}:${key}` : key;
139
- out.push(`${tableName}.${col.name} as ${name}`);
140
- }
141
- }
142
- return out;
143
- }
144
- /**
145
- * Creates a builder that can extend a select clause with additional keys.
146
- *
147
- * This is useful when you need to temporarily include columns for join operations
148
- * or other internal processing, but don't want them in the final result.
149
- *
150
- * @param original - The original select clause from the user
151
- * @returns A select builder with extend() and compile() methods
152
- * @internal
153
- *
154
- * @example
155
- * ```ts
156
- * const builder = extendSelect(['name', 'email']);
157
- * builder.extend('id'); // Add id for join operation
158
- * const { result, removeExtendedKeys } = builder.compile();
159
- * // result: ['name', 'email', 'id']
160
- *
161
- * const record = { name: 'John', email: 'j@ex.com', id: 123 };
162
- * removeExtendedKeys(record);
163
- * // record: { name: 'John', email: 'j@ex.com' }
164
- * ```
165
- */
166
- function extendSelect(original) {
167
- const select = Array.isArray(original) ? new Set(original) : true;
168
- const extendedKeys = [];
169
- return {
170
- extend(key) {
171
- if (select === true || select.has(key)) return;
172
- select.add(key);
173
- extendedKeys.push(key);
174
- },
175
- compile() {
176
- return {
177
- result: select instanceof Set ? Array.from(select) : true,
178
- extendedKeys,
179
- removeExtendedKeys(record) {
180
- for (const key of extendedKeys) delete record[key];
181
- return record;
182
- }
183
- };
184
- }
185
- };
186
- }
187
- /**
188
- * Processes encoded values and replaces ReferenceSubquery markers with actual SQL subqueries.
189
- *
190
- * @param values - The encoded values that may contain ReferenceSubquery objects
191
- * @param kysely - The Kysely database instance for building subqueries
192
- * @param mapper - Optional table name mapper for namespace prefixing
193
- * @returns Processed values with subqueries in place of ReferenceSubquery markers
194
- * @internal
195
- */
196
- function processReferenceSubqueries(values, kysely, mapper) {
197
- const processed = {};
198
- const getTableName = (table) => mapper ? mapper.toPhysical(table.name) : table.name;
199
- for (const [key, value] of Object.entries(values)) if (value instanceof ReferenceSubquery) {
200
- const refTable = value.referencedTable;
201
- const externalId = value.externalIdValue;
202
- processed[key] = kysely.selectFrom(getTableName(refTable)).select(refTable.getInternalIdColumn().name).where(refTable.getIdColumn().name, "=", externalId).limit(1);
203
- } else processed[key] = value;
204
- return processed;
205
- }
206
- /**
207
- * Creates a query compiler that builds and compiles Kysely queries without executing them.
208
- *
209
- * Each method takes table and query parameters and returns a CompiledQuery that can be
210
- * executed later using kysely.executeQuery().
211
- *
212
- * @param kysely - The Kysely database instance
213
- * @param provider - The SQL provider (affects SQL generation)
214
- * @returns An object with methods for compiling various database operations
215
- * @internal
216
- *
217
- * @example
218
- * ```ts
219
- * const builder = createKyselyQueryBuilder(kysely, 'postgresql');
220
- * const query = builder.count(userTable, { where: someCondition });
221
- * const result = await kysely.executeQuery(query);
222
- * ```
223
- */
224
- function createKyselyQueryBuilder(kysely, provider, mapper) {
225
- const getTableName = (table) => mapper ? mapper.toPhysical(table.name) : table.name;
226
- return {
227
- count(table, { where }) {
228
- let query = kysely.selectFrom(getTableName(table)).select(kysely.fn.countAll().as("count"));
229
- if (where) query = query.where((b) => buildWhere(where, b, provider, mapper, table));
230
- return query.compile();
231
- },
232
- create(table, values) {
233
- const processedValues = processReferenceSubqueries(encodeValues(values, table, true, provider), kysely, mapper);
234
- const insert = kysely.insertInto(getTableName(table)).values(processedValues);
235
- if (provider === "mssql") return insert.output(mapSelect(true, table, { tableName: "inserted" })).compile();
236
- if (provider === "postgresql" || provider === "sqlite") return insert.returning(mapSelect(true, table, { tableName: getTableName(table) })).compile();
237
- return insert.compile();
238
- },
239
- findMany(table, v) {
240
- let query = kysely.selectFrom(getTableName(table));
241
- const where = v.where;
242
- if (where) query = query.where((eb) => buildWhere(where, eb, provider, mapper, table));
243
- if (v.offset !== void 0) query = query.offset(v.offset);
244
- if (v.limit !== void 0) query = provider === "mssql" ? query.top(v.limit) : query.limit(v.limit);
245
- if (v.orderBy) for (const [col, mode] of v.orderBy) query = query.orderBy(fullSQLName(col, mapper), mode);
246
- const selectBuilder = extendSelect(v.select);
247
- const mappedSelect = [];
248
- const processJoins = (joins, parentTable, parentTableName, parentPath = "") => {
249
- for (const join of joins ?? []) {
250
- const { options: joinOptions, relation } = join;
251
- if (joinOptions === false) continue;
252
- const targetTable = relation.table;
253
- const fullPath = parentPath ? `${parentPath}:${relation.name}` : relation.name;
254
- const joinName = fullPath.replace(/:/g, "_");
255
- mappedSelect.push(...mapSelect(joinOptions.select, targetTable, {
256
- relation: fullPath,
257
- tableName: joinName
258
- }));
259
- query = query.leftJoin(`${getTableName(targetTable)} as ${joinName}`, (b) => b.on((eb) => {
260
- const conditions = [];
261
- for (const [left, right] of relation.on) {
262
- const actualRight = targetTable.columns[right]?.role === "external-id" ? "_internalId" : right;
263
- conditions.push(eb(`${parentTableName}.${parentTable.columns[left].name}`, "=", eb.ref(`${joinName}.${targetTable.columns[actualRight].name}`)));
264
- }
265
- if (joinOptions.where) conditions.push(buildWhere(joinOptions.where, eb, provider, mapper, targetTable));
266
- return eb.and(conditions);
267
- }));
268
- processJoins(joinOptions.join, targetTable, joinName, fullPath);
269
- }
270
- };
271
- processJoins(v.join, table, getTableName(table));
272
- const compiledSelect = selectBuilder.compile();
273
- mappedSelect.push(...mapSelect(compiledSelect.result, table, { tableName: getTableName(table) }));
274
- return query.select(mappedSelect).compile();
275
- },
276
- updateMany(table, v) {
277
- const processed = processReferenceSubqueries(encodeValues(v.set, table, false, provider), kysely, mapper);
278
- const versionCol = table.getVersionColumn();
279
- processed[versionCol.name] = sql.raw(`COALESCE(${versionCol.name}, 0) + 1`);
280
- let query = kysely.updateTable(getTableName(table)).set(processed);
281
- const { where } = v;
282
- if (where) query = query.where((eb) => buildWhere(where, eb, provider, mapper, table));
283
- return query.compile();
284
- },
285
- upsertCheck(table, where) {
286
- const idColumn = table.getIdColumn();
287
- let query = kysely.selectFrom(getTableName(table)).select([`${idColumn.name} as id`]);
288
- if (where) query = query.where((b) => buildWhere(where, b, provider, mapper, table));
289
- return query.limit(1).compile();
290
- },
291
- upsertUpdate(table, update, where, top) {
292
- const processed = processReferenceSubqueries(encodeValues(update, table, false, provider), kysely, mapper);
293
- let query = kysely.updateTable(getTableName(table)).set(processed);
294
- if (top) query = query.top(1);
295
- if (where) query = query.where((b) => buildWhere(where, b, provider, mapper, table));
296
- return query.compile();
297
- },
298
- upsertUpdateById(table, update, id) {
299
- const idColumn = table.getIdColumn();
300
- const processed = processReferenceSubqueries(encodeValues(update, table, false, provider), kysely, mapper);
301
- return kysely.updateTable(getTableName(table)).set(processed).where(idColumn.name, "=", id).compile();
302
- },
303
- createMany(table, values) {
304
- const processedValues = values.map((v) => encodeValues(v, table, true, provider)).map((v) => processReferenceSubqueries(v, kysely, mapper));
305
- return kysely.insertInto(getTableName(table)).values(processedValues).compile();
306
- },
307
- deleteMany(table, { where }) {
308
- let query = kysely.deleteFrom(getTableName(table));
309
- if (where) query = query.where((eb) => buildWhere(where, eb, provider, mapper, table));
310
- return query.compile();
311
- },
312
- findById(table, idValue) {
313
- const idColumn = table.getIdColumn();
314
- return kysely.selectFrom(getTableName(table)).select(mapSelect(true, table, { tableName: getTableName(table) })).where(idColumn.name, "=", idValue).limit(1).compile();
315
- }
316
- };
317
- }
318
-
319
- //#endregion
320
- export { createKyselyQueryBuilder };
321
- //# sourceMappingURL=kysely-query-builder.js.map