@fragno-dev/db 0.3.0 → 0.4.1

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 (516) hide show
  1. package/.turbo/turbo-build.log +327 -160
  2. package/CHANGELOG.md +74 -0
  3. package/README.md +24 -0
  4. package/dist/adapters/adapters.d.ts +1 -1
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +0 -3
  8. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/generic-sql-adapter.js +11 -12
  10. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +46 -6
  12. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  13. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -1
  14. package/dist/adapters/generic-sql/migration/dialect/mysql.js +1 -1
  15. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  16. package/dist/adapters/generic-sql/migration/dialect/postgres.js +1 -1
  17. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  18. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +185 -19
  19. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  20. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -1
  21. package/dist/adapters/generic-sql/migration/executor.js +30 -3
  22. package/dist/adapters/generic-sql/migration/executor.js.map +1 -1
  23. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  24. package/dist/adapters/generic-sql/migration/prepared-migrations.js +3 -3
  25. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  26. package/dist/adapters/generic-sql/migration/sql-generator.js +1 -1
  27. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  28. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +1 -1
  29. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  30. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  31. package/dist/adapters/generic-sql/query/db-now-sql.js +27 -0
  32. package/dist/adapters/generic-sql/query/db-now-sql.js.map +1 -0
  33. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +9 -6
  34. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  35. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/sql-query-compiler.js +37 -9
  37. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  38. package/dist/adapters/generic-sql/query/where-builder.js +24 -20
  39. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  40. package/dist/adapters/generic-sql/uow-decoder.js +1 -1
  41. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  42. package/dist/adapters/generic-sql/uow-encoder.js +8 -9
  43. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  44. package/dist/adapters/in-memory/condition-evaluator.js +10 -6
  45. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -1
  46. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -1
  47. package/dist/adapters/in-memory/in-memory-adapter.js +45 -25
  48. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -1
  49. package/dist/adapters/in-memory/in-memory-uow.js +236 -13
  50. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -1
  51. package/dist/adapters/in-memory/options.d.ts +2 -0
  52. package/dist/adapters/in-memory/options.d.ts.map +1 -1
  53. package/dist/adapters/in-memory/options.js +3 -2
  54. package/dist/adapters/in-memory/options.js.map +1 -1
  55. package/dist/adapters/in-memory/reference-resolution.js.map +1 -1
  56. package/dist/adapters/in-memory/store.js +1 -1
  57. package/dist/adapters/in-memory/store.js.map +1 -1
  58. package/dist/adapters/shared/from-unit-of-work-compiler.js +51 -24
  59. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  60. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  61. package/dist/browser/adapters/adapters.d.ts +61 -0
  62. package/dist/browser/adapters/adapters.d.ts.map +1 -0
  63. package/dist/browser/adapters/generic-sql/migration/executor.d.ts +15 -0
  64. package/dist/browser/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  65. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  66. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  67. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts +11 -0
  68. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  69. package/dist/browser/adapters/in-memory/in-memory-adapter.d.ts +5 -0
  70. package/dist/browser/adapters/in-memory/index.d.ts +2 -0
  71. package/dist/browser/adapters/in-memory/options.d.ts +1 -0
  72. package/dist/browser/db-fragment-definition-builder.d.ts +237 -0
  73. package/dist/browser/db-fragment-definition-builder.d.ts.map +1 -0
  74. package/dist/browser/durable-hooks.d.ts +3 -0
  75. package/dist/browser/fragments/internal-fragment.d.ts +317 -0
  76. package/dist/browser/fragments/internal-fragment.d.ts.map +1 -0
  77. package/dist/browser/fragments/internal-fragment.schema.d.ts +1 -0
  78. package/dist/browser/hooks/durable-hooks-logger.d.ts +10 -0
  79. package/dist/browser/hooks/durable-hooks-logger.d.ts.map +1 -0
  80. package/dist/browser/hooks/hooks.d.ts +146 -0
  81. package/dist/browser/hooks/hooks.d.ts.map +1 -0
  82. package/dist/browser/id.js +1 -0
  83. package/dist/browser/internal/adapter-registry.d.ts +4 -0
  84. package/dist/browser/internal/outbox-state.d.ts +2 -0
  85. package/dist/browser/mod.d.ts +15 -0
  86. package/dist/browser/mod.d.ts.map +1 -0
  87. package/dist/browser/mod.js +17 -0
  88. package/dist/browser/mod.js.map +1 -0
  89. package/dist/browser/mod2.d.ts +48 -0
  90. package/dist/browser/mod2.d.ts.map +1 -0
  91. package/dist/browser/naming/sql-naming.d.ts +19 -0
  92. package/dist/browser/naming/sql-naming.d.ts.map +1 -0
  93. package/dist/browser/outbox/outbox.d.ts +21 -0
  94. package/dist/browser/outbox/outbox.d.ts.map +1 -0
  95. package/dist/browser/query/column-defaults.js +1 -0
  96. package/dist/browser/query/condition-builder.d.ts +44 -0
  97. package/dist/browser/query/condition-builder.d.ts.map +1 -0
  98. package/dist/browser/query/condition-builder.js +97 -0
  99. package/dist/browser/query/condition-builder.js.map +1 -0
  100. package/dist/browser/query/cursor.d.ts +105 -0
  101. package/dist/browser/query/cursor.d.ts.map +1 -0
  102. package/dist/browser/query/cursor.js +150 -0
  103. package/dist/browser/query/cursor.js.map +1 -0
  104. package/dist/browser/query/db-now.d.ts +22 -0
  105. package/dist/browser/query/db-now.d.ts.map +1 -0
  106. package/dist/browser/query/db-now.js +33 -0
  107. package/dist/browser/query/db-now.js.map +1 -0
  108. package/dist/browser/query/orm/orm.d.ts +18 -0
  109. package/dist/browser/query/orm/orm.d.ts.map +1 -0
  110. package/dist/browser/query/simple-query-interface.d.ts +108 -0
  111. package/dist/browser/query/simple-query-interface.d.ts.map +1 -0
  112. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts +423 -0
  113. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  114. package/dist/browser/query/unit-of-work/execute-unit-of-work.js +507 -0
  115. package/dist/browser/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  116. package/dist/browser/query/unit-of-work/retry-policy.d.ts +23 -0
  117. package/dist/browser/query/unit-of-work/retry-policy.d.ts.map +1 -0
  118. package/dist/browser/query/unit-of-work/retry-policy.js +40 -0
  119. package/dist/browser/query/unit-of-work/retry-policy.js.map +1 -0
  120. package/dist/browser/query/unit-of-work/unit-of-work.d.ts +703 -0
  121. package/dist/browser/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  122. package/dist/browser/query/unit-of-work/unit-of-work.js +1206 -0
  123. package/dist/browser/query/unit-of-work/unit-of-work.js.map +1 -0
  124. package/dist/browser/query/value-encoding.js +38 -0
  125. package/dist/browser/query/value-encoding.js.map +1 -0
  126. package/dist/browser/schema/create.d.ts +326 -0
  127. package/dist/browser/schema/create.d.ts.map +1 -0
  128. package/dist/browser/schema/create.js +89 -0
  129. package/dist/browser/schema/create.js.map +1 -0
  130. package/dist/browser/schema/generate-id.js +28 -0
  131. package/dist/browser/schema/generate-id.js.map +1 -0
  132. package/dist/browser/shared/providers.d.ts +6 -0
  133. package/dist/browser/shared/providers.d.ts.map +1 -0
  134. package/dist/browser/sql-driver/connection/connection-provider.d.ts +13 -0
  135. package/dist/browser/sql-driver/connection/connection-provider.d.ts.map +1 -0
  136. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  137. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  138. package/dist/browser/sql-driver/driver/runtime-driver.d.ts +23 -0
  139. package/dist/browser/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  140. package/dist/browser/sql-driver/query-executor/plugin.d.ts +17 -0
  141. package/dist/browser/sql-driver/query-executor/plugin.d.ts.map +1 -0
  142. package/dist/browser/sql-driver/query-executor/query-executor.d.ts +36 -0
  143. package/dist/browser/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  144. package/dist/browser/sql-driver/sql-driver-adapter.d.ts +29 -0
  145. package/dist/browser/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  146. package/dist/browser/sql-driver/sql-driver.d.ts +38 -0
  147. package/dist/browser/sql-driver/sql-driver.d.ts.map +1 -0
  148. package/dist/browser/sync/commands.d.ts +15 -0
  149. package/dist/browser/sync/commands.d.ts.map +1 -0
  150. package/dist/browser/sync/commands.js +27 -0
  151. package/dist/browser/sync/commands.js.map +1 -0
  152. package/dist/browser/sync/types.d.ts +63 -0
  153. package/dist/browser/sync/types.d.ts.map +1 -0
  154. package/dist/browser/util/types.d.ts +8 -0
  155. package/dist/browser/util/types.d.ts.map +1 -0
  156. package/dist/browser/with-database.d.ts +29 -0
  157. package/dist/browser/with-database.d.ts.map +1 -0
  158. package/dist/client.d.ts +4 -0
  159. package/dist/client.js +5 -0
  160. package/dist/db-fragment-definition-builder.d.ts +85 -28
  161. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  162. package/dist/db-fragment-definition-builder.js +374 -46
  163. package/dist/db-fragment-definition-builder.js.map +1 -1
  164. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts +20 -0
  165. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts.map +1 -0
  166. package/dist/dispatchers/cloudflare-do/dispatcher.js +147 -0
  167. package/dist/dispatchers/cloudflare-do/dispatcher.js.map +1 -0
  168. package/dist/dispatchers/cloudflare-do/index.d.ts +5 -20
  169. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -1
  170. package/dist/dispatchers/cloudflare-do/index.js +23 -55
  171. package/dist/dispatchers/cloudflare-do/index.js.map +1 -1
  172. package/dist/dispatchers/node/dispatcher.d.ts +14 -0
  173. package/dist/dispatchers/node/dispatcher.d.ts.map +1 -0
  174. package/dist/dispatchers/node/dispatcher.js +80 -0
  175. package/dist/dispatchers/node/dispatcher.js.map +1 -0
  176. package/dist/dispatchers/node/index.d.ts +5 -10
  177. package/dist/dispatchers/node/index.d.ts.map +1 -1
  178. package/dist/dispatchers/node/index.js +21 -53
  179. package/dist/dispatchers/node/index.js.map +1 -1
  180. package/dist/durable-hooks.d.ts +31 -0
  181. package/dist/durable-hooks.d.ts.map +1 -0
  182. package/dist/durable-hooks.js +23 -0
  183. package/dist/durable-hooks.js.map +1 -0
  184. package/dist/fragments/internal-fragment.d.ts +128 -27
  185. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  186. package/dist/fragments/internal-fragment.js +125 -78
  187. package/dist/fragments/internal-fragment.js.map +1 -1
  188. package/dist/fragments/internal-fragment.routes.js +138 -3
  189. package/dist/fragments/internal-fragment.routes.js.map +1 -1
  190. package/dist/fragments/internal-fragment.schema.d.ts +7 -1
  191. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -1
  192. package/dist/fragments/internal-fragment.schema.js +18 -1
  193. package/dist/fragments/internal-fragment.schema.js.map +1 -1
  194. package/dist/hooks/durable-hooks-logger.d.ts +10 -0
  195. package/dist/hooks/durable-hooks-logger.d.ts.map +1 -0
  196. package/dist/hooks/durable-hooks-logger.js +75 -0
  197. package/dist/hooks/durable-hooks-logger.js.map +1 -0
  198. package/dist/hooks/durable-hooks-processor.d.ts +1 -14
  199. package/dist/hooks/durable-hooks-processor.js +58 -10
  200. package/dist/hooks/durable-hooks-processor.js.map +1 -1
  201. package/dist/hooks/durable-hooks-runtime.js +44 -0
  202. package/dist/hooks/durable-hooks-runtime.js.map +1 -0
  203. package/dist/hooks/hooks.d.ts +60 -2
  204. package/dist/hooks/hooks.d.ts.map +1 -1
  205. package/dist/hooks/hooks.js +214 -53
  206. package/dist/hooks/hooks.js.map +1 -1
  207. package/dist/id.d.ts +2 -2
  208. package/dist/id.js +2 -2
  209. package/dist/internal/adapter-registry.d.ts +11 -0
  210. package/dist/internal/adapter-registry.d.ts.map +1 -0
  211. package/dist/internal/adapter-registry.js +135 -0
  212. package/dist/internal/adapter-registry.js.map +1 -0
  213. package/dist/internal/outbox-state.d.ts +2 -0
  214. package/dist/internal/outbox-state.js +26 -0
  215. package/dist/internal/outbox-state.js.map +1 -0
  216. package/dist/migration-engine/auto-from-schema.d.ts +33 -0
  217. package/dist/migration-engine/auto-from-schema.d.ts.map +1 -0
  218. package/dist/migration-engine/auto-from-schema.js +210 -27
  219. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  220. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  221. package/dist/migration-engine/generation-engine.js +17 -5
  222. package/dist/migration-engine/generation-engine.js.map +1 -1
  223. package/dist/migration-engine/shared.d.ts +113 -0
  224. package/dist/migration-engine/shared.d.ts.map +1 -0
  225. package/dist/migration-engine/shared.js.map +1 -1
  226. package/dist/mod.d.ts +12 -11
  227. package/dist/mod.d.ts.map +1 -1
  228. package/dist/mod.js +10 -10
  229. package/dist/mod.js.map +1 -1
  230. package/dist/naming/sql-naming.d.ts.map +1 -1
  231. package/dist/naming/sql-naming.js.map +1 -1
  232. package/dist/outbox/outbox-builder.js.map +1 -1
  233. package/dist/outbox/outbox.d.ts +3 -1
  234. package/dist/outbox/outbox.d.ts.map +1 -1
  235. package/dist/outbox/outbox.js.map +1 -1
  236. package/dist/query/column-defaults.js.map +1 -1
  237. package/dist/query/condition-builder.d.ts +7 -1
  238. package/dist/query/condition-builder.d.ts.map +1 -1
  239. package/dist/query/condition-builder.js +5 -1
  240. package/dist/query/condition-builder.js.map +1 -1
  241. package/dist/query/cursor-client.d.ts +105 -0
  242. package/dist/query/cursor-client.d.ts.map +1 -0
  243. package/dist/query/cursor-client.js +165 -0
  244. package/dist/query/cursor-client.js.map +1 -0
  245. package/dist/query/cursor.d.ts.map +1 -1
  246. package/dist/query/cursor.js +7 -1
  247. package/dist/query/cursor.js.map +1 -1
  248. package/dist/query/db-now.d.ts +15 -1
  249. package/dist/query/db-now.d.ts.map +1 -1
  250. package/dist/query/db-now.js +30 -2
  251. package/dist/query/db-now.js.map +1 -1
  252. package/dist/query/orm/orm.js.map +1 -1
  253. package/dist/query/serialize/create-sql-serializer.js +2 -2
  254. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  255. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  256. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  257. package/dist/query/serialize/dialect/sqlite-serializer.js +6 -2
  258. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  259. package/dist/query/simple-query-interface.d.ts +7 -3
  260. package/dist/query/simple-query-interface.d.ts.map +1 -1
  261. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +37 -2
  262. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  263. package/dist/query/unit-of-work/execute-unit-of-work.js +39 -18
  264. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  265. package/dist/query/unit-of-work/unit-of-work.d.ts +42 -16
  266. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  267. package/dist/query/unit-of-work/unit-of-work.js +50 -6
  268. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  269. package/dist/query/value-decoding.js +8 -1
  270. package/dist/query/value-decoding.js.map +1 -1
  271. package/dist/query/value-encoding.js.map +1 -1
  272. package/dist/schema/create.d.ts +69 -25
  273. package/dist/schema/create.d.ts.map +1 -1
  274. package/dist/schema/create.js +91 -16
  275. package/dist/schema/create.js.map +1 -1
  276. package/dist/schema/type-conversion/create-sql-type-mapper.js +1 -1
  277. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  278. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  279. package/dist/schema/validator.d.ts.map +1 -1
  280. package/dist/schema/validator.js.map +1 -1
  281. package/dist/schema-output/drizzle.d.ts.map +1 -1
  282. package/dist/schema-output/drizzle.js +8 -6
  283. package/dist/schema-output/drizzle.js.map +1 -1
  284. package/dist/schema-output/prisma.d.ts.map +1 -1
  285. package/dist/schema-output/prisma.js +21 -10
  286. package/dist/schema-output/prisma.js.map +1 -1
  287. package/dist/sql-driver/dialects/durable-object-dialect.js +3 -9
  288. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -1
  289. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -1
  290. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -1
  291. package/dist/sql-driver/sql-driver-adapter.js.map +1 -1
  292. package/dist/sql-driver/sql.js.map +1 -1
  293. package/dist/sync/commands.d.ts +15 -0
  294. package/dist/sync/commands.d.ts.map +1 -0
  295. package/dist/sync/commands.js +27 -0
  296. package/dist/sync/commands.js.map +1 -0
  297. package/dist/sync/index.d.ts +4 -0
  298. package/dist/sync/index.js +4 -0
  299. package/dist/sync/read-tracking.d.ts +25 -0
  300. package/dist/sync/read-tracking.d.ts.map +1 -0
  301. package/dist/sync/read-tracking.js +148 -0
  302. package/dist/sync/read-tracking.js.map +1 -0
  303. package/dist/sync/submit.js +213 -0
  304. package/dist/sync/submit.js.map +1 -0
  305. package/dist/sync/types.d.ts +63 -0
  306. package/dist/sync/types.d.ts.map +1 -0
  307. package/dist/util/default-database-adapter.js +6 -1
  308. package/dist/util/default-database-adapter.js.map +1 -1
  309. package/dist/with-database.d.ts +3 -6
  310. package/dist/with-database.d.ts.map +1 -1
  311. package/dist/with-database.js +7 -15
  312. package/dist/with-database.js.map +1 -1
  313. package/package.json +33 -41
  314. package/src/adapters/adapters.ts +5 -4
  315. package/src/adapters/drizzle/migrate-drizzle.test.ts +46 -9
  316. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +5 -3
  317. package/src/adapters/drizzle/test-utils.ts +2 -1
  318. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -3
  319. package/src/adapters/generic-sql/generic-sql-adapter.ts +21 -24
  320. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +1 -0
  321. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +81 -15
  322. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +4 -2
  323. package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
  324. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +3 -2
  325. package/src/adapters/generic-sql/migration/dialect/mysql.ts +1 -0
  326. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +5 -4
  327. package/src/adapters/generic-sql/migration/dialect/postgres.ts +2 -1
  328. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +795 -3
  329. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +385 -57
  330. package/src/adapters/generic-sql/migration/executor.test.ts +52 -0
  331. package/src/adapters/generic-sql/migration/executor.ts +47 -4
  332. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +117 -14
  333. package/src/adapters/generic-sql/migration/prepared-migrations.ts +9 -8
  334. package/src/adapters/generic-sql/migration/sql-generator.ts +5 -3
  335. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +3 -3
  336. package/src/adapters/generic-sql/query/cursor-utils.test.ts +3 -2
  337. package/src/adapters/generic-sql/query/cursor-utils.ts +1 -1
  338. package/src/adapters/generic-sql/query/db-now-sql.ts +49 -0
  339. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +144 -8
  340. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +16 -17
  341. package/src/adapters/generic-sql/query/select-builder.test.ts +1 -0
  342. package/src/adapters/generic-sql/query/select-builder.ts +2 -2
  343. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +24 -5
  344. package/src/adapters/generic-sql/query/sql-query-compiler.ts +83 -13
  345. package/src/adapters/generic-sql/query/where-builder.test.ts +7 -5
  346. package/src/adapters/generic-sql/query/where-builder.ts +48 -29
  347. package/src/adapters/generic-sql/sql-adapter-pglite-migrations.test.ts +6 -15
  348. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +52 -7
  349. package/src/adapters/generic-sql/sql-adapter-pglite-queries.test.ts +9 -6
  350. package/src/adapters/generic-sql/sql-adapter-sqlite3-driver.test.ts +273 -5
  351. package/src/adapters/generic-sql/sql-adapter-sqlite3-uow.test.ts +123 -6
  352. package/src/adapters/generic-sql/sql-adapter-sqlocal.test.ts +4 -2
  353. package/src/adapters/generic-sql/uow-decoder.test.ts +4 -3
  354. package/src/adapters/generic-sql/uow-decoder.ts +3 -3
  355. package/src/adapters/generic-sql/uow-encoder.test.ts +4 -2
  356. package/src/adapters/generic-sql/uow-encoder.ts +14 -18
  357. package/src/adapters/in-memory/condition-evaluator.test.ts +2 -1
  358. package/src/adapters/in-memory/condition-evaluator.ts +9 -4
  359. package/src/adapters/in-memory/in-memory-adapter.ts +155 -44
  360. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +50 -2
  361. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +158 -3
  362. package/src/adapters/in-memory/in-memory-uow.ts +402 -26
  363. package/src/adapters/in-memory/options.test.ts +1 -0
  364. package/src/adapters/in-memory/options.ts +5 -1
  365. package/src/adapters/in-memory/outbox.test.ts +361 -0
  366. package/src/adapters/in-memory/reference-resolution.test.ts +3 -2
  367. package/src/adapters/in-memory/reference-resolution.ts +2 -2
  368. package/src/adapters/in-memory/sorted-array-index.test.ts +1 -0
  369. package/src/adapters/in-memory/store.test.ts +1 -0
  370. package/src/adapters/in-memory/store.ts +3 -3
  371. package/src/adapters/in-memory/value-normalization.test.ts +1 -0
  372. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +51 -7
  373. package/src/adapters/shared/from-unit-of-work-compiler.ts +156 -46
  374. package/src/adapters/shared/uow-operation-compiler.ts +3 -3
  375. package/src/browser/mod.ts +64 -0
  376. package/src/client.ts +19 -0
  377. package/src/db-fragment-definition-builder.test.ts +821 -47
  378. package/src/db-fragment-definition-builder.ts +857 -110
  379. package/src/db-fragment-instantiator.test.ts +114 -90
  380. package/src/db-fragment-integration.test.ts +9 -6
  381. package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
  382. package/src/dispatchers/cloudflare-do/index.test.ts +145 -12
  383. package/src/dispatchers/cloudflare-do/index.ts +49 -90
  384. package/src/dispatchers/node/dispatcher.ts +112 -0
  385. package/src/dispatchers/node/index.test.ts +43 -14
  386. package/src/dispatchers/node/index.ts +38 -75
  387. package/src/durable-hooks.test.ts +80 -0
  388. package/src/durable-hooks.ts +67 -0
  389. package/src/fragments/internal-fragment.routes.test.ts +570 -0
  390. package/src/fragments/internal-fragment.routes.ts +297 -5
  391. package/src/fragments/internal-fragment.schema.ts +45 -1
  392. package/src/fragments/internal-fragment.test.ts +223 -251
  393. package/src/fragments/internal-fragment.ts +278 -154
  394. package/src/hooks/durable-hooks-logger.ts +126 -0
  395. package/src/hooks/durable-hooks-processor.pglite.test.ts +87 -0
  396. package/src/hooks/durable-hooks-processor.test.ts +179 -14
  397. package/src/hooks/durable-hooks-processor.ts +120 -14
  398. package/src/hooks/durable-hooks-runtime.test.ts +65 -0
  399. package/src/hooks/durable-hooks-runtime.ts +81 -0
  400. package/src/hooks/hooks.test.ts +314 -53
  401. package/src/hooks/hooks.ts +360 -81
  402. package/src/id.test.ts +34 -0
  403. package/src/id.ts +1 -3
  404. package/src/internal/adapter-registry.test.ts +93 -0
  405. package/src/internal/adapter-registry.ts +239 -0
  406. package/src/internal/outbox-state.ts +43 -0
  407. package/src/migration-engine/auto-from-schema.test.ts +93 -0
  408. package/src/migration-engine/auto-from-schema.ts +360 -42
  409. package/src/migration-engine/create.test.ts +2 -1
  410. package/src/migration-engine/create.ts +1 -1
  411. package/src/migration-engine/generation-engine.test.ts +66 -9
  412. package/src/migration-engine/generation-engine.ts +31 -10
  413. package/src/migration-engine/shared.ts +13 -0
  414. package/src/mod.ts +45 -27
  415. package/src/naming/sql-naming.ts +1 -0
  416. package/src/outbox/outbox-builder.ts +2 -2
  417. package/src/outbox/outbox.test.ts +216 -45
  418. package/src/outbox/outbox.ts +3 -1
  419. package/src/query/column-defaults.ts +1 -1
  420. package/src/query/condition-builder.test.ts +15 -0
  421. package/src/query/condition-builder.ts +7 -0
  422. package/src/query/cursor-client.test.ts +70 -0
  423. package/src/query/cursor-client.ts +263 -0
  424. package/src/query/cursor.test.ts +3 -2
  425. package/src/query/cursor.ts +15 -3
  426. package/src/query/db-now.ts +69 -2
  427. package/src/query/orm/orm.ts +2 -2
  428. package/src/query/query-type.test.ts +2 -1
  429. package/src/query/serialize/create-sql-serializer.ts +3 -3
  430. package/src/query/serialize/dialect/mysql-serializer.ts +1 -1
  431. package/src/query/serialize/dialect/postgres-serializer.ts +1 -1
  432. package/src/query/serialize/dialect/sqlite-serializer.test.ts +39 -2
  433. package/src/query/serialize/dialect/sqlite-serializer.ts +18 -5
  434. package/src/query/simple-query-interface.ts +10 -4
  435. package/src/query/unit-of-work/execute-unit-of-work.test.ts +347 -9
  436. package/src/query/unit-of-work/execute-unit-of-work.ts +63 -20
  437. package/src/query/unit-of-work/retry-policy.test.ts +1 -0
  438. package/src/query/unit-of-work/tx-builder.test.ts +73 -1
  439. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +5 -4
  440. package/src/query/unit-of-work/unit-of-work-types.test.ts +41 -11
  441. package/src/query/unit-of-work/unit-of-work.test.ts +28 -2
  442. package/src/query/unit-of-work/unit-of-work.ts +105 -19
  443. package/src/query/value-decoding.test.ts +50 -2
  444. package/src/query/value-decoding.ts +17 -4
  445. package/src/query/value-encoding.test.ts +1 -0
  446. package/src/query/value-encoding.ts +1 -1
  447. package/src/schema/create.test.ts +164 -5
  448. package/src/schema/create.ts +222 -24
  449. package/src/schema/generate-id.test.ts +1 -0
  450. package/src/schema/serialize.test.ts +4 -3
  451. package/src/schema/type-conversion/create-sql-type-mapper.ts +1 -1
  452. package/src/schema/type-conversion/dialect/sqlite.ts +2 -2
  453. package/src/schema/type-conversion/type-mapping.test.ts +2 -1
  454. package/src/schema/validator.test.ts +4 -2
  455. package/src/schema/validator.ts +1 -0
  456. package/src/schema-output/drizzle.test.ts +72 -19
  457. package/src/schema-output/drizzle.ts +24 -18
  458. package/src/schema-output/prisma.test.ts +172 -14
  459. package/src/schema-output/prisma.ts +34 -14
  460. package/src/sql-driver/better-sqlite3.test.ts +5 -3
  461. package/src/sql-driver/dialects/durable-object-dialect.ts +3 -8
  462. package/src/sql-driver/query-executor/default-query-executor.ts +1 -1
  463. package/src/sql-driver/query-executor/query-executor-base.ts +1 -1
  464. package/src/sql-driver/query-executor/query-executor.ts +1 -1
  465. package/src/sql-driver/sql-driver-adapter.ts +2 -2
  466. package/src/sql-driver/sql.ts +2 -1
  467. package/src/sql-driver/sqlocal.test.ts +4 -2
  468. package/src/sync/commands.test.ts +39 -0
  469. package/src/sync/commands.ts +51 -0
  470. package/src/sync/conflict-checker.test.ts +450 -0
  471. package/src/sync/conflict-checker.ts +248 -0
  472. package/src/sync/index.ts +14 -0
  473. package/src/sync/plan.ts +9 -0
  474. package/src/sync/read-tracking.test.ts +177 -0
  475. package/src/sync/read-tracking.ts +287 -0
  476. package/src/sync/submit.test.ts +205 -0
  477. package/src/sync/submit.ts +328 -0
  478. package/src/sync/types.ts +80 -0
  479. package/src/util/default-database-adapter.ts +15 -2
  480. package/src/with-database.ts +20 -50
  481. package/tsconfig.json +1 -1
  482. package/tsdown.config.ts +38 -26
  483. package/vitest.config.ts +1 -0
  484. package/dist/hooks/durable-hooks-processor.d.ts.map +0 -1
  485. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js +0 -168
  486. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +0 -1
  487. package/dist/packages/fragno/dist/api/bind-services.js +0 -20
  488. package/dist/packages/fragno/dist/api/bind-services.js.map +0 -1
  489. package/dist/packages/fragno/dist/api/error.js +0 -48
  490. package/dist/packages/fragno/dist/api/error.js.map +0 -1
  491. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +0 -321
  492. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
  493. package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -669
  494. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +0 -1
  495. package/dist/packages/fragno/dist/api/fragno-response.js +0 -73
  496. package/dist/packages/fragno/dist/api/fragno-response.js.map +0 -1
  497. package/dist/packages/fragno/dist/api/internal/response-stream.js +0 -81
  498. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +0 -1
  499. package/dist/packages/fragno/dist/api/internal/route.js +0 -10
  500. package/dist/packages/fragno/dist/api/internal/route.js.map +0 -1
  501. package/dist/packages/fragno/dist/api/mutable-request-state.js +0 -97
  502. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +0 -1
  503. package/dist/packages/fragno/dist/api/request-context-storage.js +0 -43
  504. package/dist/packages/fragno/dist/api/request-context-storage.js.map +0 -1
  505. package/dist/packages/fragno/dist/api/request-input-context.js +0 -185
  506. package/dist/packages/fragno/dist/api/request-input-context.js.map +0 -1
  507. package/dist/packages/fragno/dist/api/request-middleware.js +0 -83
  508. package/dist/packages/fragno/dist/api/request-middleware.js.map +0 -1
  509. package/dist/packages/fragno/dist/api/request-output-context.js +0 -119
  510. package/dist/packages/fragno/dist/api/request-output-context.js.map +0 -1
  511. package/dist/packages/fragno/dist/api/route.js +0 -30
  512. package/dist/packages/fragno/dist/api/route.js.map +0 -1
  513. package/dist/packages/fragno/dist/internal/symbols.js +0 -10
  514. package/dist/packages/fragno/dist/internal/symbols.js.map +0 -1
  515. package/dist/packages/fragno/dist/internal/trace-context.js +0 -12
  516. package/dist/packages/fragno/dist/internal/trace-context.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"cursor-utils.js","names":["orConditions: Condition[]","andItems: Condition[]"],"sources":["../../../../src/adapters/generic-sql/query/cursor-utils.ts"],"sourcesContent":["import type { AnyColumn } from \"../../../schema/create\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport { decodeCursor, serializeCursorValues, type Cursor } from \"../../../query/cursor\";\nimport type { DriverConfig } from \"../driver-config\";\nimport type { SQLiteStorageMode } from \"../sqlite-storage\";\n\n/**\n * Build a cursor condition for pagination.\n *\n * Handles both single-column and multi-column cursor comparisons.\n * For single columns: uses simple comparison (col > value)\n * For multi-columns: builds tuple comparison ((col1, col2) > (val1, val2))\n *\n * @param cursor - The cursor string or object\n * @param indexColumns - Columns used in the index for ordering\n * @param orderDirection - Direction of ordering (asc/desc)\n * @param isAfter - True for \"after\" cursor (forward pagination), false for \"before\" (backward)\n * @param driverConfig - The driver configuration for value serialization\n * @param sqliteStorageMode - Optional SQLite storage mode for date/bigint serialization\n * @returns A Condition object for the cursor, or undefined if no cursor\n * @throws Error if multi-column cursors are not supported by the implementation\n */\nexport function buildCursorCondition(\n cursor: string | Cursor | undefined,\n indexColumns: AnyColumn[],\n orderDirection: \"asc\" | \"desc\",\n isAfter: boolean,\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n): Condition | undefined {\n if (!cursor || indexColumns.length === 0) {\n return undefined;\n }\n\n // Decode cursor if it's a string, otherwise use it as-is\n const cursorObj = typeof cursor === \"string\" ? decodeCursor(cursor) : cursor;\n const serializedValues = serializeCursorValues(\n cursorObj,\n indexColumns,\n driverConfig,\n sqliteStorageMode,\n );\n\n // Determine comparison operator based on direction and after/before\n const useGreaterThan =\n (isAfter && orderDirection === \"asc\") || (!isAfter && orderDirection === \"desc\");\n\n if (indexColumns.length === 1) {\n // Simple single-column case\n const col = indexColumns[0]!;\n const val = serializedValues[col.name];\n const operator = useGreaterThan ? \">\" : \"<\";\n return {\n type: \"compare\",\n a: col,\n operator,\n b: val,\n };\n }\n\n const operator = useGreaterThan ? \">\" : \"<\";\n const orConditions: Condition[] = [];\n const isNullish = (value: unknown): value is null | undefined =>\n value === null || value === undefined;\n const buildEqualityCondition = (column: AnyColumn, value: unknown): Condition =>\n isNullish(value)\n ? { type: \"compare\", a: column, operator: \"is\", b: null }\n : { type: \"compare\", a: column, operator: \"=\", b: value };\n\n for (let i = 0; i < indexColumns.length; i += 1) {\n const col = indexColumns[i]!;\n const val = serializedValues[col.name];\n const andItems: Condition[] = [];\n\n for (let j = 0; j < i; j += 1) {\n const prevCol = indexColumns[j]!;\n andItems.push(buildEqualityCondition(prevCol, serializedValues[prevCol.name]));\n }\n\n andItems.push({\n type: \"compare\",\n a: col,\n operator,\n b: val,\n });\n\n orConditions.push(andItems.length === 1 ? andItems[0]! : { type: \"and\", items: andItems });\n }\n\n return { type: \"or\", items: orConditions };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,qBACd,QACA,cACA,gBACA,SACA,cACA,mBACuB;AACvB,KAAI,CAAC,UAAU,aAAa,WAAW,EACrC;CAKF,MAAM,mBAAmB,sBADP,OAAO,WAAW,WAAW,aAAa,OAAO,GAAG,QAGpE,cACA,cACA,kBACD;CAGD,MAAM,iBACH,WAAW,mBAAmB,SAAW,CAAC,WAAW,mBAAmB;AAE3E,KAAI,aAAa,WAAW,GAAG;EAE7B,MAAM,MAAM,aAAa;EACzB,MAAM,MAAM,iBAAiB,IAAI;AAEjC,SAAO;GACL,MAAM;GACN,GAAG;GACH,UAJe,iBAAiB,MAAM;GAKtC,GAAG;GACJ;;CAGH,MAAM,WAAW,iBAAiB,MAAM;CACxC,MAAMA,eAA4B,EAAE;CACpC,MAAM,aAAa,UACjB,UAAU,QAAQ,UAAU;CAC9B,MAAM,0BAA0B,QAAmB,UACjD,UAAU,MAAM,GACZ;EAAE,MAAM;EAAW,GAAG;EAAQ,UAAU;EAAM,GAAG;EAAM,GACvD;EAAE,MAAM;EAAW,GAAG;EAAQ,UAAU;EAAK,GAAG;EAAO;AAE7D,MAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,GAAG;EAC/C,MAAM,MAAM,aAAa;EACzB,MAAM,MAAM,iBAAiB,IAAI;EACjC,MAAMC,WAAwB,EAAE;AAEhC,OAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG;GAC7B,MAAM,UAAU,aAAa;AAC7B,YAAS,KAAK,uBAAuB,SAAS,iBAAiB,QAAQ,MAAM,CAAC;;AAGhF,WAAS,KAAK;GACZ,MAAM;GACN,GAAG;GACH;GACA,GAAG;GACJ,CAAC;AAEF,eAAa,KAAK,SAAS,WAAW,IAAI,SAAS,KAAM;GAAE,MAAM;GAAO,OAAO;GAAU,CAAC;;AAG5F,QAAO;EAAE,MAAM;EAAM,OAAO;EAAc"}
1
+ {"version":3,"file":"cursor-utils.js","names":["orConditions: Condition[]","andItems: Condition[]"],"sources":["../../../../src/adapters/generic-sql/query/cursor-utils.ts"],"sourcesContent":["import type { Condition } from \"../../../query/condition-builder\";\nimport { decodeCursor, serializeCursorValues, type Cursor } from \"../../../query/cursor\";\nimport type { AnyColumn } from \"../../../schema/create\";\nimport type { DriverConfig } from \"../driver-config\";\nimport type { SQLiteStorageMode } from \"../sqlite-storage\";\n\n/**\n * Build a cursor condition for pagination.\n *\n * Handles both single-column and multi-column cursor comparisons.\n * For single columns: uses simple comparison (col > value)\n * For multi-columns: builds tuple comparison ((col1, col2) > (val1, val2))\n *\n * @param cursor - The cursor string or object\n * @param indexColumns - Columns used in the index for ordering\n * @param orderDirection - Direction of ordering (asc/desc)\n * @param isAfter - True for \"after\" cursor (forward pagination), false for \"before\" (backward)\n * @param driverConfig - The driver configuration for value serialization\n * @param sqliteStorageMode - Optional SQLite storage mode for date/bigint serialization\n * @returns A Condition object for the cursor, or undefined if no cursor\n * @throws Error if multi-column cursors are not supported by the implementation\n */\nexport function buildCursorCondition(\n cursor: string | Cursor | undefined,\n indexColumns: AnyColumn[],\n orderDirection: \"asc\" | \"desc\",\n isAfter: boolean,\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n): Condition | undefined {\n if (!cursor || indexColumns.length === 0) {\n return undefined;\n }\n\n // Decode cursor if it's a string, otherwise use it as-is\n const cursorObj = typeof cursor === \"string\" ? decodeCursor(cursor) : cursor;\n const serializedValues = serializeCursorValues(\n cursorObj,\n indexColumns,\n driverConfig,\n sqliteStorageMode,\n );\n\n // Determine comparison operator based on direction and after/before\n const useGreaterThan =\n (isAfter && orderDirection === \"asc\") || (!isAfter && orderDirection === \"desc\");\n\n if (indexColumns.length === 1) {\n // Simple single-column case\n const col = indexColumns[0]!;\n const val = serializedValues[col.name];\n const operator = useGreaterThan ? \">\" : \"<\";\n return {\n type: \"compare\",\n a: col,\n operator,\n b: val,\n };\n }\n\n const operator = useGreaterThan ? \">\" : \"<\";\n const orConditions: Condition[] = [];\n const isNullish = (value: unknown): value is null | undefined =>\n value === null || value === undefined;\n const buildEqualityCondition = (column: AnyColumn, value: unknown): Condition =>\n isNullish(value)\n ? { type: \"compare\", a: column, operator: \"is\", b: null }\n : { type: \"compare\", a: column, operator: \"=\", b: value };\n\n for (let i = 0; i < indexColumns.length; i += 1) {\n const col = indexColumns[i]!;\n const val = serializedValues[col.name];\n const andItems: Condition[] = [];\n\n for (let j = 0; j < i; j += 1) {\n const prevCol = indexColumns[j]!;\n andItems.push(buildEqualityCondition(prevCol, serializedValues[prevCol.name]));\n }\n\n andItems.push({\n type: \"compare\",\n a: col,\n operator,\n b: val,\n });\n\n orConditions.push(andItems.length === 1 ? andItems[0]! : { type: \"and\", items: andItems });\n }\n\n return { type: \"or\", items: orConditions };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,qBACd,QACA,cACA,gBACA,SACA,cACA,mBACuB;AACvB,KAAI,CAAC,UAAU,aAAa,WAAW,EACrC;CAKF,MAAM,mBAAmB,sBADP,OAAO,WAAW,WAAW,aAAa,OAAO,GAAG,QAGpE,cACA,cACA,kBACD;CAGD,MAAM,iBACH,WAAW,mBAAmB,SAAW,CAAC,WAAW,mBAAmB;AAE3E,KAAI,aAAa,WAAW,GAAG;EAE7B,MAAM,MAAM,aAAa;EACzB,MAAM,MAAM,iBAAiB,IAAI;AAEjC,SAAO;GACL,MAAM;GACN,GAAG;GACH,UAJe,iBAAiB,MAAM;GAKtC,GAAG;GACJ;;CAGH,MAAM,WAAW,iBAAiB,MAAM;CACxC,MAAMA,eAA4B,EAAE;CACpC,MAAM,aAAa,UACjB,UAAU,QAAQ,UAAU;CAC9B,MAAM,0BAA0B,QAAmB,UACjD,UAAU,MAAM,GACZ;EAAE,MAAM;EAAW,GAAG;EAAQ,UAAU;EAAM,GAAG;EAAM,GACvD;EAAE,MAAM;EAAW,GAAG;EAAQ,UAAU;EAAK,GAAG;EAAO;AAE7D,MAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,GAAG;EAC/C,MAAM,MAAM,aAAa;EACzB,MAAM,MAAM,iBAAiB,IAAI;EACjC,MAAMC,WAAwB,EAAE;AAEhC,OAAK,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG;GAC7B,MAAM,UAAU,aAAa;AAC7B,YAAS,KAAK,uBAAuB,SAAS,iBAAiB,QAAQ,MAAM,CAAC;;AAGhF,WAAS,KAAK;GACZ,MAAM;GACN,GAAG;GACH;GACA,GAAG;GACJ,CAAC;AAEF,eAAa,KAAK,SAAS,WAAW,IAAI,SAAS,KAAM;GAAE,MAAM;GAAO,OAAO;GAAU,CAAC;;AAG5F,QAAO;EAAE,MAAM;EAAM,OAAO;EAAc"}
@@ -0,0 +1,27 @@
1
+ import { sqliteStorageDefault } from "../sqlite-storage.js";
2
+ import { sql } from "kysely";
3
+
4
+ //#region src/adapters/generic-sql/query/db-now-sql.ts
5
+ const buildDbNowSql = ({ driverConfig, columnType, offsetMs, sqliteStorageMode }) => {
6
+ if (driverConfig.databaseType === "sqlite") {
7
+ const storageMode = sqliteStorageMode ?? sqliteStorageDefault;
8
+ const storage = columnType === "date" ? storageMode.dateStorage : storageMode.timestampStorage;
9
+ if ((columnType === "timestamp" || columnType === "date") && storage === "epoch-ms") {
10
+ const base = sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`;
11
+ return offsetMs === 0 ? base : sql`${base} + ${offsetMs}`;
12
+ }
13
+ if (offsetMs === 0) return sql`CURRENT_TIMESTAMP`;
14
+ const roundedSeconds = Math.round(offsetMs / 1e3 * 1e3) / 1e3;
15
+ return sql`datetime('now', ${`${roundedSeconds >= 0 ? "+" : ""}${roundedSeconds} seconds`})`;
16
+ }
17
+ if (driverConfig.databaseType === "mysql") {
18
+ if (offsetMs === 0) return sql`CURRENT_TIMESTAMP`;
19
+ return sql`TIMESTAMPADD(MICROSECOND, ${Math.trunc(offsetMs * 1e3)}, CURRENT_TIMESTAMP)`;
20
+ }
21
+ if (offsetMs === 0) return sql`CURRENT_TIMESTAMP`;
22
+ return sql`(CURRENT_TIMESTAMP + (${offsetMs} * interval '1 millisecond'))`;
23
+ };
24
+
25
+ //#endregion
26
+ export { buildDbNowSql };
27
+ //# sourceMappingURL=db-now-sql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-now-sql.js","names":[],"sources":["../../../../src/adapters/generic-sql/query/db-now-sql.ts"],"sourcesContent":["import { sql } from \"kysely\";\n\nimport type { AnyColumn } from \"../../../schema/create\";\nimport type { DriverConfig } from \"../driver-config\";\nimport { sqliteStorageDefault, type SQLiteStorageMode } from \"../sqlite-storage\";\n\ntype ColumnType = AnyColumn[\"type\"];\n\ntype BuildDbNowSqlOptions = {\n driverConfig: DriverConfig;\n columnType: ColumnType;\n offsetMs: number;\n sqliteStorageMode?: SQLiteStorageMode;\n};\n\nexport const buildDbNowSql = ({\n driverConfig,\n columnType,\n offsetMs,\n sqliteStorageMode,\n}: BuildDbNowSqlOptions) => {\n if (driverConfig.databaseType === \"sqlite\") {\n const storageMode = sqliteStorageMode ?? sqliteStorageDefault;\n const storage = columnType === \"date\" ? storageMode.dateStorage : storageMode.timestampStorage;\n if ((columnType === \"timestamp\" || columnType === \"date\") && storage === \"epoch-ms\") {\n const base = sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`;\n return offsetMs === 0 ? base : sql`${base} + ${offsetMs}`;\n }\n if (offsetMs === 0) {\n return sql`CURRENT_TIMESTAMP`;\n }\n const roundedSeconds = Math.round((offsetMs / 1000) * 1000) / 1000;\n const modifier = `${roundedSeconds >= 0 ? \"+\" : \"\"}${roundedSeconds} seconds`;\n return sql`datetime('now', ${modifier})`;\n }\n\n if (driverConfig.databaseType === \"mysql\") {\n if (offsetMs === 0) {\n return sql`CURRENT_TIMESTAMP`;\n }\n const micros = Math.trunc(offsetMs * 1000);\n return sql`TIMESTAMPADD(MICROSECOND, ${micros}, CURRENT_TIMESTAMP)`;\n }\n\n if (offsetMs === 0) {\n return sql`CURRENT_TIMESTAMP`;\n }\n return sql`(CURRENT_TIMESTAMP + (${offsetMs} * interval '1 millisecond'))`;\n};\n"],"mappings":";;;;AAeA,MAAa,iBAAiB,EAC5B,cACA,YACA,UACA,wBAC0B;AAC1B,KAAI,aAAa,iBAAiB,UAAU;EAC1C,MAAM,cAAc,qBAAqB;EACzC,MAAM,UAAU,eAAe,SAAS,YAAY,cAAc,YAAY;AAC9E,OAAK,eAAe,eAAe,eAAe,WAAW,YAAY,YAAY;GACnF,MAAM,OAAO,GAAG;AAChB,UAAO,aAAa,IAAI,OAAO,GAAG,GAAG,KAAK,KAAK;;AAEjD,MAAI,aAAa,EACf,QAAO,GAAG;EAEZ,MAAM,iBAAiB,KAAK,MAAO,WAAW,MAAQ,IAAK,GAAG;AAE9D,SAAO,GAAG,mBADO,GAAG,kBAAkB,IAAI,MAAM,KAAK,eAAe,UAC9B;;AAGxC,KAAI,aAAa,iBAAiB,SAAS;AACzC,MAAI,aAAa,EACf,QAAO,GAAG;AAGZ,SAAO,GAAG,6BADK,KAAK,MAAM,WAAW,IAAK,CACI;;AAGhD,KAAI,aAAa,EACf,QAAO,GAAG;AAEZ,QAAO,GAAG,yBAAyB,SAAS"}
@@ -1,10 +1,10 @@
1
- import { createColdKysely } from "../migration/cold-kysely.js";
2
- import { UOWOperationCompiler } from "../../shared/uow-operation-compiler.js";
3
1
  import { buildCondition } from "../../../query/condition-builder.js";
2
+ import { UOWOperationCompiler } from "../../shared/uow-operation-compiler.js";
3
+ import { createColdKysely } from "../migration/cold-kysely.js";
4
+ import { buildFindOptions } from "../../../query/orm/orm.js";
4
5
  import "./sql-query-compiler.js";
5
6
  import { createSQLQueryCompiler } from "./create-sql-query-compiler.js";
6
7
  import { buildCursorCondition } from "./cursor-utils.js";
7
- import { buildFindOptions } from "../../../query/orm/orm.js";
8
8
 
9
9
  //#region src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts
10
10
  /**
@@ -49,7 +49,6 @@ var GenericSQLUOWOperationCompiler = class extends UOWOperationCompiler {
49
49
  }
50
50
  let orderBy;
51
51
  if (indexColumns.length > 0) orderBy = indexColumns.map((col) => [col, orderDirection]);
52
- if ((after || before) && indexColumns.length > 1) throw new Error("Multi-column cursor pagination is not yet supported in Generic SQL implementation");
53
52
  const cursorCondition = buildCursorCondition(after || before, indexColumns, orderDirection, !!after, this.driverConfig, this.sqliteStorageMode);
54
53
  let combinedWhere;
55
54
  if (findManyOptions.where) {
@@ -69,7 +68,8 @@ var GenericSQLUOWOperationCompiler = class extends UOWOperationCompiler {
69
68
  where: combinedWhere,
70
69
  orderBy,
71
70
  limit: effectiveLimit,
72
- join
71
+ join,
72
+ readTracking: op.readTracking
73
73
  });
74
74
  const compiledOptions = buildFindOptions(op.table, {
75
75
  ...findManyOptions,
@@ -78,7 +78,10 @@ var GenericSQLUOWOperationCompiler = class extends UOWOperationCompiler {
78
78
  limit: effectiveLimit
79
79
  });
80
80
  if (compiledOptions === false) return null;
81
- return sqlCompiler.compileFindMany(op.table, compiledOptions);
81
+ return sqlCompiler.compileFindMany(op.table, {
82
+ ...compiledOptions,
83
+ readTracking: op.readTracking
84
+ });
82
85
  }
83
86
  compileCreate(op) {
84
87
  const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);
@@ -1 +1 @@
1
- {"version":3,"file":"generic-sql-uow-operation-compiler.js","names":["indexColumns: AnyColumn[]","orderDirection: \"asc\" | \"desc\"","orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined","combinedWhere: Condition | undefined","conditions: Condition | undefined"],"sources":["../../../../src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts"],"sourcesContent":["import { UOWOperationCompiler } from \"../../shared/uow-operation-compiler\";\nimport type { CompiledQuery } from \"kysely\";\nimport type { DriverConfig } from \"../driver-config\";\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\nimport type { SQLiteStorageMode } from \"../sqlite-storage\";\nimport type {\n RetrievalOperation,\n MutationOperation,\n CompiledMutation,\n} from \"../../../query/unit-of-work/unit-of-work\";\nimport type { AnyColumn, AnySchema } from \"../../../schema/create\";\nimport { buildCondition } from \"../../../query/condition-builder\";\nimport { createSQLQueryCompiler } from \"./create-sql-query-compiler\";\nimport { SQLQueryCompiler } from \"./sql-query-compiler\";\nimport { buildCursorCondition } from \"./cursor-utils\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport { buildFindOptions } from \"../../../query/orm/orm\";\nimport type { AnySelectClause } from \"../../../query/simple-query-interface\";\nimport { createColdKysely } from \"../migration/cold-kysely\";\n\n/**\n * Generic SQL UOW Operation Compiler.\n *\n * Uses SQLQueryCompiler for dialect-specific SQL generation while handling\n * high-level business logic like cursor pagination, version checking, and index resolution.\n */\nexport class GenericSQLUOWOperationCompiler extends UOWOperationCompiler<CompiledQuery> {\n private readonly sqliteStorageMode?: SQLiteStorageMode;\n\n constructor(\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n resolverFactory?: (schema: AnySchema, namespace: string | null) => NamingResolver,\n ) {\n super(driverConfig, resolverFactory);\n this.sqliteStorageMode = sqliteStorageMode;\n }\n\n /**\n * Get SQL compiler for a specific namespace\n */\n private getSQLCompiler(\n schema: AnySchema,\n namespace: string | null | undefined,\n ): SQLQueryCompiler {\n const resolver = this.getNamingResolver(schema, namespace ?? null);\n const kysely = createColdKysely(this.driverConfig.databaseType);\n const schemaName = resolver.getSchemaName();\n const scopedKysely = schemaName ? kysely.withSchema(schemaName) : kysely;\n return createSQLQueryCompiler(\n scopedKysely,\n this.driverConfig,\n this.sqliteStorageMode,\n resolver,\n );\n }\n\n override compileCount(\n op: RetrievalOperation<AnySchema> & { type: \"count\" },\n ): CompiledQuery | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n\n // Build where condition\n let conditions = op.options.where\n ? buildCondition(op.table.columns, op.options.where)\n : undefined;\n\n if (conditions === true) {\n conditions = undefined;\n }\n if (conditions === false) {\n return null;\n }\n\n return sqlCompiler.compileCount(op.table, { where: conditions });\n }\n\n override compileFind(op: RetrievalOperation<AnySchema> & { type: \"find\" }): CompiledQuery | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n\n // Extract options\n const {\n useIndex: _useIndex,\n orderByIndex,\n joins: join,\n after,\n before,\n pageSize,\n ...findManyOptions\n } = op.options;\n\n // Get index columns for ordering and cursor pagination\n let indexColumns: AnyColumn[] = [];\n let orderDirection: \"asc\" | \"desc\" = \"asc\";\n\n if (orderByIndex) {\n const index = op.table.indexes[orderByIndex.indexName];\n orderDirection = orderByIndex.direction;\n\n if (!index) {\n // If _primary index doesn't exist, fall back to internal ID column\n if (orderByIndex.indexName === \"_primary\") {\n indexColumns = [op.table.getIdColumn()];\n } else {\n throw new Error(\n `Index \"${orderByIndex.indexName}\" not found on table \"${op.table.name}\"`,\n );\n }\n } else {\n // Order by all columns in the index with the specified direction\n indexColumns = index.columns;\n }\n }\n\n // Convert orderByIndex to orderBy format\n let orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined;\n if (indexColumns.length > 0) {\n orderBy = indexColumns.map((col) => [col, orderDirection]);\n }\n\n // Handle cursor pagination - build a cursor condition\n // TODO: Multi-column cursor pagination not yet supported\n if ((after || before) && indexColumns.length > 1) {\n throw new Error(\n \"Multi-column cursor pagination is not yet supported in Generic SQL implementation\",\n );\n }\n const cursorCondition = buildCursorCondition(\n after || before,\n indexColumns,\n orderDirection,\n !!after,\n this.driverConfig,\n this.sqliteStorageMode,\n );\n\n // Combine user where clause with cursor condition\n let combinedWhere: Condition | undefined;\n if (findManyOptions.where) {\n const whereResult = buildCondition(op.table.columns, findManyOptions.where);\n if (whereResult === true) {\n combinedWhere = undefined;\n } else if (whereResult === false) {\n return null;\n } else {\n combinedWhere = whereResult;\n }\n }\n\n if (cursorCondition) {\n if (combinedWhere) {\n combinedWhere = {\n type: \"and\",\n items: [combinedWhere, cursorCondition],\n };\n } else {\n combinedWhere = cursorCondition;\n }\n }\n\n // For cursor pagination, fetch one extra item to determine if there's a next page\n const effectiveLimit = pageSize && op.withCursor ? pageSize + 1 : pageSize;\n\n // When we have joins, use the query builder directly\n if (join && join.length > 0) {\n return sqlCompiler.compileFindMany(op.table, {\n select: (findManyOptions.select ?? true) as AnySelectClause,\n where: combinedWhere,\n orderBy,\n limit: effectiveLimit,\n join,\n });\n }\n\n // Otherwise, use buildFindOptions to process the query options\n const compiledOptions = buildFindOptions(op.table, {\n ...findManyOptions,\n where: combinedWhere ? () => combinedWhere! : undefined,\n orderBy: orderBy?.map(([col, dir]) => [col.name, dir]),\n limit: effectiveLimit,\n });\n\n if (compiledOptions === false) {\n return null;\n }\n\n return sqlCompiler.compileFindMany(op.table, compiledOptions);\n }\n\n override compileCreate(\n op: MutationOperation<AnySchema> & { type: \"create\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n\n return {\n query: sqlCompiler.compileCreate(table, op.values),\n operation: op,\n op: \"create\",\n expectedAffectedRows: null, // creates don't need affected row checks\n expectedReturnedRows: null,\n };\n }\n\n override compileUpdate(\n op: MutationOperation<AnySchema> & { type: \"update\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = this.getExternalId(op.id);\n const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const conditionsResult =\n versionToCheck !== undefined\n ? buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.name, \"=\", externalId), eb(versionColumn.name, \"=\", versionToCheck)),\n )\n : buildCondition(table.columns, (eb) => eb(idColumn.name, \"=\", externalId));\n\n if (conditionsResult === false) {\n return null;\n }\n\n const conditions: Condition | undefined =\n conditionsResult === true ? undefined : conditionsResult;\n\n // Determine if we should use RETURNING-based checking\n // Use RETURNING when driver supports it but doesn't support affected rows reporting\n const useReturningForCheck =\n op.checkVersion &&\n this.driverConfig.supportsReturning &&\n !this.driverConfig.supportsRowsAffected;\n\n const query = sqlCompiler.compileUpdate(table, {\n set: op.set,\n where: conditions,\n returning: useReturningForCheck,\n });\n\n return {\n query,\n operation: op,\n op: \"update\",\n expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,\n expectedReturnedRows: useReturningForCheck ? 1 : null,\n };\n }\n\n override compileDelete(\n op: MutationOperation<AnySchema> & { type: \"delete\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = this.getExternalId(op.id);\n const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const conditionsResult =\n versionToCheck !== undefined\n ? buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.name, \"=\", externalId), eb(versionColumn.name, \"=\", versionToCheck)),\n )\n : buildCondition(table.columns, (eb) => eb(idColumn.name, \"=\", externalId));\n\n if (conditionsResult === false) {\n return null;\n }\n\n const conditions: Condition | undefined =\n conditionsResult === true ? undefined : conditionsResult;\n\n // Determine if we should use RETURNING-based checking\n // Use RETURNING when driver supports it but doesn't support affected rows reporting\n const useReturningForCheck =\n op.checkVersion &&\n this.driverConfig.supportsReturning &&\n !this.driverConfig.supportsRowsAffected;\n\n const query = sqlCompiler.compileDelete(table, {\n where: conditions,\n returning: useReturningForCheck,\n });\n\n return {\n query,\n operation: op,\n op: \"delete\",\n expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,\n expectedReturnedRows: useReturningForCheck ? 1 : null,\n };\n }\n\n override compileCheck(\n op: MutationOperation<AnySchema> & { type: \"check\" },\n ): CompiledMutation<CompiledQuery> {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = op.id.externalId;\n const version = op.id.version;\n\n // Build a SELECT 1 query to check if the row exists with the correct version\n const condition = buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.name, \"=\", externalId), eb(versionColumn.name, \"=\", version)),\n );\n\n if (typeof condition === \"boolean\") {\n throw new Error(\"Condition is a boolean, but should be a condition object.\");\n }\n\n return {\n query: sqlCompiler.compileCheck(table, condition),\n operation: op,\n op: \"check\",\n expectedAffectedRows: null,\n expectedReturnedRows: 1, // Check that exactly 1 row was returned\n };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"generic-sql-uow-operation-compiler.js","names":["indexColumns: AnyColumn[]","orderDirection: \"asc\" | \"desc\"","orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined","combinedWhere: Condition | undefined","conditions: Condition | undefined"],"sources":["../../../../src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts"],"sourcesContent":["import type { CompiledQuery } from \"kysely\";\n\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\nimport { buildCondition } from \"../../../query/condition-builder\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport { buildFindOptions } from \"../../../query/orm/orm\";\nimport type { AnySelectClause } from \"../../../query/simple-query-interface\";\nimport type {\n RetrievalOperation,\n MutationOperation,\n CompiledMutation,\n} from \"../../../query/unit-of-work/unit-of-work\";\nimport type { AnyColumn, AnySchema } from \"../../../schema/create\";\nimport { UOWOperationCompiler } from \"../../shared/uow-operation-compiler\";\nimport type { DriverConfig } from \"../driver-config\";\nimport { createColdKysely } from \"../migration/cold-kysely\";\nimport type { SQLiteStorageMode } from \"../sqlite-storage\";\nimport { createSQLQueryCompiler } from \"./create-sql-query-compiler\";\nimport { buildCursorCondition } from \"./cursor-utils\";\nimport { SQLQueryCompiler } from \"./sql-query-compiler\";\n\n/**\n * Generic SQL UOW Operation Compiler.\n *\n * Uses SQLQueryCompiler for dialect-specific SQL generation while handling\n * high-level business logic like cursor pagination, version checking, and index resolution.\n */\nexport class GenericSQLUOWOperationCompiler extends UOWOperationCompiler<CompiledQuery> {\n private readonly sqliteStorageMode?: SQLiteStorageMode;\n\n constructor(\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n resolverFactory?: (schema: AnySchema, namespace: string | null) => NamingResolver,\n ) {\n super(driverConfig, resolverFactory);\n this.sqliteStorageMode = sqliteStorageMode;\n }\n\n /**\n * Get SQL compiler for a specific namespace\n */\n private getSQLCompiler(\n schema: AnySchema,\n namespace: string | null | undefined,\n ): SQLQueryCompiler {\n const resolver = this.getNamingResolver(schema, namespace ?? null);\n const kysely = createColdKysely(this.driverConfig.databaseType);\n const schemaName = resolver.getSchemaName();\n const scopedKysely = schemaName ? kysely.withSchema(schemaName) : kysely;\n return createSQLQueryCompiler(\n scopedKysely,\n this.driverConfig,\n this.sqliteStorageMode,\n resolver,\n );\n }\n\n override compileCount(\n op: RetrievalOperation<AnySchema> & { type: \"count\" },\n ): CompiledQuery | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n\n // Build where condition\n let conditions = op.options.where\n ? buildCondition(op.table.columns, op.options.where)\n : undefined;\n\n if (conditions === true) {\n conditions = undefined;\n }\n if (conditions === false) {\n return null;\n }\n\n return sqlCompiler.compileCount(op.table, { where: conditions });\n }\n\n override compileFind(op: RetrievalOperation<AnySchema> & { type: \"find\" }): CompiledQuery | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n\n // Extract options\n const {\n useIndex: _useIndex,\n orderByIndex,\n joins: join,\n after,\n before,\n pageSize,\n ...findManyOptions\n } = op.options;\n\n // Get index columns for ordering and cursor pagination\n let indexColumns: AnyColumn[] = [];\n let orderDirection: \"asc\" | \"desc\" = \"asc\";\n\n if (orderByIndex) {\n const index = op.table.indexes[orderByIndex.indexName];\n orderDirection = orderByIndex.direction;\n\n if (!index) {\n // If _primary index doesn't exist, fall back to internal ID column\n if (orderByIndex.indexName === \"_primary\") {\n indexColumns = [op.table.getIdColumn()];\n } else {\n throw new Error(\n `Index \"${orderByIndex.indexName}\" not found on table \"${op.table.name}\"`,\n );\n }\n } else {\n // Order by all columns in the index with the specified direction\n indexColumns = index.columns;\n }\n }\n\n // Convert orderByIndex to orderBy format\n let orderBy: [AnyColumn, \"asc\" | \"desc\"][] | undefined;\n if (indexColumns.length > 0) {\n orderBy = indexColumns.map((col) => [col, orderDirection]);\n }\n\n // Handle cursor pagination - build a cursor condition (supports multi-column lexicographic compare)\n const cursorCondition = buildCursorCondition(\n after || before,\n indexColumns,\n orderDirection,\n !!after,\n this.driverConfig,\n this.sqliteStorageMode,\n );\n\n // Combine user where clause with cursor condition\n let combinedWhere: Condition | undefined;\n if (findManyOptions.where) {\n const whereResult = buildCondition(op.table.columns, findManyOptions.where);\n if (whereResult === true) {\n combinedWhere = undefined;\n } else if (whereResult === false) {\n return null;\n } else {\n combinedWhere = whereResult;\n }\n }\n\n if (cursorCondition) {\n if (combinedWhere) {\n combinedWhere = {\n type: \"and\",\n items: [combinedWhere, cursorCondition],\n };\n } else {\n combinedWhere = cursorCondition;\n }\n }\n\n // For cursor pagination, fetch one extra item to determine if there's a next page\n const effectiveLimit = pageSize && op.withCursor ? pageSize + 1 : pageSize;\n\n // When we have joins, use the query builder directly\n if (join && join.length > 0) {\n return sqlCompiler.compileFindMany(op.table, {\n select: (findManyOptions.select ?? true) as AnySelectClause,\n where: combinedWhere,\n orderBy,\n limit: effectiveLimit,\n join,\n readTracking: op.readTracking,\n });\n }\n\n // Otherwise, use buildFindOptions to process the query options\n const compiledOptions = buildFindOptions(op.table, {\n ...findManyOptions,\n where: combinedWhere ? () => combinedWhere! : undefined,\n orderBy: orderBy?.map(([col, dir]) => [col.name, dir]),\n limit: effectiveLimit,\n });\n\n if (compiledOptions === false) {\n return null;\n }\n\n return sqlCompiler.compileFindMany(op.table, {\n ...compiledOptions,\n readTracking: op.readTracking,\n });\n }\n\n override compileCreate(\n op: MutationOperation<AnySchema> & { type: \"create\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n\n return {\n query: sqlCompiler.compileCreate(table, op.values),\n operation: op,\n op: \"create\",\n expectedAffectedRows: null, // creates don't need affected row checks\n expectedReturnedRows: null,\n };\n }\n\n override compileUpdate(\n op: MutationOperation<AnySchema> & { type: \"update\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = this.getExternalId(op.id);\n const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const conditionsResult =\n versionToCheck !== undefined\n ? buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.name, \"=\", externalId), eb(versionColumn.name, \"=\", versionToCheck)),\n )\n : buildCondition(table.columns, (eb) => eb(idColumn.name, \"=\", externalId));\n\n if (conditionsResult === false) {\n return null;\n }\n\n const conditions: Condition | undefined =\n conditionsResult === true ? undefined : conditionsResult;\n\n // Determine if we should use RETURNING-based checking\n // Use RETURNING when driver supports it but doesn't support affected rows reporting\n const useReturningForCheck =\n op.checkVersion &&\n this.driverConfig.supportsReturning &&\n !this.driverConfig.supportsRowsAffected;\n\n const query = sqlCompiler.compileUpdate(table, {\n set: op.set,\n where: conditions,\n returning: useReturningForCheck,\n });\n\n return {\n query,\n operation: op,\n op: \"update\",\n expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,\n expectedReturnedRows: useReturningForCheck ? 1 : null,\n };\n }\n\n override compileDelete(\n op: MutationOperation<AnySchema> & { type: \"delete\" },\n ): CompiledMutation<CompiledQuery> | null {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = this.getExternalId(op.id);\n const versionToCheck = this.getVersionToCheck(op.id, op.checkVersion);\n\n // Build WHERE clause that filters by ID and optionally by version\n const conditionsResult =\n versionToCheck !== undefined\n ? buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.name, \"=\", externalId), eb(versionColumn.name, \"=\", versionToCheck)),\n )\n : buildCondition(table.columns, (eb) => eb(idColumn.name, \"=\", externalId));\n\n if (conditionsResult === false) {\n return null;\n }\n\n const conditions: Condition | undefined =\n conditionsResult === true ? undefined : conditionsResult;\n\n // Determine if we should use RETURNING-based checking\n // Use RETURNING when driver supports it but doesn't support affected rows reporting\n const useReturningForCheck =\n op.checkVersion &&\n this.driverConfig.supportsReturning &&\n !this.driverConfig.supportsRowsAffected;\n\n const query = sqlCompiler.compileDelete(table, {\n where: conditions,\n returning: useReturningForCheck,\n });\n\n return {\n query,\n operation: op,\n op: \"delete\",\n expectedAffectedRows: useReturningForCheck ? null : op.checkVersion ? 1n : null,\n expectedReturnedRows: useReturningForCheck ? 1 : null,\n };\n }\n\n override compileCheck(\n op: MutationOperation<AnySchema> & { type: \"check\" },\n ): CompiledMutation<CompiledQuery> {\n const sqlCompiler = this.getSQLCompiler(op.schema, op.namespace);\n const table = this.getTable(op.schema, op.table);\n const idColumn = table.getIdColumn();\n const versionColumn = table.getVersionColumn();\n\n const externalId = op.id.externalId;\n const version = op.id.version;\n\n // Build a SELECT 1 query to check if the row exists with the correct version\n const condition = buildCondition(table.columns, (eb) =>\n eb.and(eb(idColumn.name, \"=\", externalId), eb(versionColumn.name, \"=\", version)),\n );\n\n if (typeof condition === \"boolean\") {\n throw new Error(\"Condition is a boolean, but should be a condition object.\");\n }\n\n return {\n query: sqlCompiler.compileCheck(table, condition),\n operation: op,\n op: \"check\",\n expectedAffectedRows: null,\n expectedReturnedRows: 1, // Check that exactly 1 row was returned\n };\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"select-builder.js","names":["out: string[]","extendedKeys: string[]"],"sources":["../../../../src/adapters/generic-sql/query/select-builder.ts"],"sourcesContent":["import type { AnyTable } from \"../../../schema/create\";\nimport type { AnySelectClause } from \"../../../query/simple-query-interface\";\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\n\n/**\n * Maps a select clause to SQL column names with optional aliases.\n *\n * Converts application-level select clauses (either array of keys or \"select all\")\n * into SQL-compatible column selections with proper aliasing for relations.\n *\n * @param select - The select clause (array of keys or true for all columns)\n * @param table - The table schema containing column definitions\n * @param options - Optional configuration\n * @param options.relation - Relation name to prefix in aliases (for joined data)\n * @param options.tableName - Override the table name in the SQL (defaults to table.name)\n * @returns Array of SQL select strings in the format \"tableName.columnName as alias\"\n * @internal\n */\nexport function mapSelect(\n select: AnySelectClause,\n table: AnyTable,\n resolver: NamingResolver | undefined,\n options: {\n relation?: string;\n tableName?: string;\n } = {},\n): string[] {\n const { relation, tableName = table.name } = options;\n const out: string[] = [];\n const keys = Array.isArray(select) ? select : Object.keys(table.columns);\n\n for (const key of keys) {\n const col = table.columns[key];\n\n // Skip hidden columns when explicitly selecting\n if (Array.isArray(select) && col.isHidden) {\n continue;\n }\n\n // Add the column to the select list\n const name = relation ? `${relation}:${key}` : key;\n const columnName = resolver ? resolver.getColumnName(table.name, col.name) : col.name;\n out.push(`${tableName}.${columnName} as ${name}`);\n }\n\n // Always include hidden columns (for FragnoId construction with internal ID and version)\n for (const key in table.columns) {\n const col = table.columns[key];\n if (col.isHidden && !keys.includes(key)) {\n const name = relation ? `${relation}:${key}` : key;\n const columnName = resolver ? resolver.getColumnName(table.name, col.name) : col.name;\n out.push(`${tableName}.${columnName} as ${name}`);\n }\n }\n\n return out;\n}\n\n/**\n * Result type from compiling a select clause with extensions.\n * @internal\n */\nexport interface CompiledSelect {\n /**\n * The final select clause to use in the query\n */\n result: AnySelectClause;\n\n /**\n * Keys that were added to the select clause (not originally requested)\n */\n extendedKeys: string[];\n\n /**\n * Removes the extended keys from a record (mutates the record).\n * Used to clean up keys that were only needed for join operations.\n *\n * @param record - The record to remove extended keys from\n * @returns The same record with extended keys removed\n */\n removeExtendedKeys: (record: Record<string, unknown>) => Record<string, unknown>;\n}\n\n/**\n * Builder for extending a select clause with additional keys.\n * @internal\n */\nexport interface SelectBuilder {\n /**\n * Adds a key to the select clause if not already present.\n * Tracks which keys were added for later removal.\n *\n * @param key - The key to add to the select clause\n */\n extend: (key: string) => void;\n\n /**\n * Compiles the select clause into its final form.\n *\n * @returns The compiled select information\n */\n compile: () => CompiledSelect;\n}\n\n/**\n * Creates a builder that can extend a select clause with additional keys.\n *\n * This is useful when you need to temporarily include columns for join operations\n * or other internal processing, but don't want them in the final result.\n *\n * @param original - The original select clause from the user\n * @returns A select builder with extend() and compile() methods\n * @internal\n */\nexport function extendSelect(original: AnySelectClause): SelectBuilder {\n const select = Array.isArray(original) ? new Set(original) : true;\n const extendedKeys: string[] = [];\n\n return {\n extend(key) {\n if (select === true || select.has(key)) {\n return;\n }\n\n select.add(key);\n extendedKeys.push(key);\n },\n compile() {\n return {\n result: select instanceof Set ? Array.from(select) : true,\n extendedKeys,\n removeExtendedKeys(record) {\n for (const key of extendedKeys) {\n delete record[key];\n }\n return record;\n },\n };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,SAAgB,UACd,QACA,OACA,UACA,UAGI,EAAE,EACI;CACV,MAAM,EAAE,UAAU,YAAY,MAAM,SAAS;CAC7C,MAAMA,MAAgB,EAAE;CACxB,MAAM,OAAO,MAAM,QAAQ,OAAO,GAAG,SAAS,OAAO,KAAK,MAAM,QAAQ;AAExE,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,MAAM,MAAM,QAAQ;AAG1B,MAAI,MAAM,QAAQ,OAAO,IAAI,IAAI,SAC/B;EAIF,MAAM,OAAO,WAAW,GAAG,SAAS,GAAG,QAAQ;EAC/C,MAAM,aAAa,WAAW,SAAS,cAAc,MAAM,MAAM,IAAI,KAAK,GAAG,IAAI;AACjF,MAAI,KAAK,GAAG,UAAU,GAAG,WAAW,MAAM,OAAO;;AAInD,MAAK,MAAM,OAAO,MAAM,SAAS;EAC/B,MAAM,MAAM,MAAM,QAAQ;AAC1B,MAAI,IAAI,YAAY,CAAC,KAAK,SAAS,IAAI,EAAE;GACvC,MAAM,OAAO,WAAW,GAAG,SAAS,GAAG,QAAQ;GAC/C,MAAM,aAAa,WAAW,SAAS,cAAc,MAAM,MAAM,IAAI,KAAK,GAAG,IAAI;AACjF,OAAI,KAAK,GAAG,UAAU,GAAG,WAAW,MAAM,OAAO;;;AAIrD,QAAO;;;;;;;;;;;;AA2DT,SAAgB,aAAa,UAA0C;CACrE,MAAM,SAAS,MAAM,QAAQ,SAAS,GAAG,IAAI,IAAI,SAAS,GAAG;CAC7D,MAAMC,eAAyB,EAAE;AAEjC,QAAO;EACL,OAAO,KAAK;AACV,OAAI,WAAW,QAAQ,OAAO,IAAI,IAAI,CACpC;AAGF,UAAO,IAAI,IAAI;AACf,gBAAa,KAAK,IAAI;;EAExB,UAAU;AACR,UAAO;IACL,QAAQ,kBAAkB,MAAM,MAAM,KAAK,OAAO,GAAG;IACrD;IACA,mBAAmB,QAAQ;AACzB,UAAK,MAAM,OAAO,aAChB,QAAO,OAAO;AAEhB,YAAO;;IAEV;;EAEJ"}
1
+ {"version":3,"file":"select-builder.js","names":["out: string[]","extendedKeys: string[]"],"sources":["../../../../src/adapters/generic-sql/query/select-builder.ts"],"sourcesContent":["import type { NamingResolver } from \"../../../naming/sql-naming\";\nimport type { AnySelectClause } from \"../../../query/simple-query-interface\";\nimport type { AnyTable } from \"../../../schema/create\";\n\n/**\n * Maps a select clause to SQL column names with optional aliases.\n *\n * Converts application-level select clauses (either array of keys or \"select all\")\n * into SQL-compatible column selections with proper aliasing for relations.\n *\n * @param select - The select clause (array of keys or true for all columns)\n * @param table - The table schema containing column definitions\n * @param options - Optional configuration\n * @param options.relation - Relation name to prefix in aliases (for joined data)\n * @param options.tableName - Override the table name in the SQL (defaults to table.name)\n * @returns Array of SQL select strings in the format \"tableName.columnName as alias\"\n * @internal\n */\nexport function mapSelect(\n select: AnySelectClause,\n table: AnyTable,\n resolver: NamingResolver | undefined,\n options: {\n relation?: string;\n tableName?: string;\n } = {},\n): string[] {\n const { relation, tableName = table.name } = options;\n const out: string[] = [];\n const keys = Array.isArray(select) ? select : Object.keys(table.columns);\n\n for (const key of keys) {\n const col = table.columns[key];\n\n // Skip hidden columns when explicitly selecting\n if (Array.isArray(select) && col.isHidden) {\n continue;\n }\n\n // Add the column to the select list\n const name = relation ? `${relation}:${key}` : key;\n const columnName = resolver ? resolver.getColumnName(table.name, col.name) : col.name;\n out.push(`${tableName}.${columnName} as ${name}`);\n }\n\n // Always include hidden columns (for FragnoId construction with internal ID and version)\n for (const key in table.columns) {\n const col = table.columns[key];\n if (col.isHidden && !keys.includes(key)) {\n const name = relation ? `${relation}:${key}` : key;\n const columnName = resolver ? resolver.getColumnName(table.name, col.name) : col.name;\n out.push(`${tableName}.${columnName} as ${name}`);\n }\n }\n\n return out;\n}\n\n/**\n * Result type from compiling a select clause with extensions.\n * @internal\n */\nexport interface CompiledSelect {\n /**\n * The final select clause to use in the query\n */\n result: AnySelectClause;\n\n /**\n * Keys that were added to the select clause (not originally requested)\n */\n extendedKeys: string[];\n\n /**\n * Removes the extended keys from a record (mutates the record).\n * Used to clean up keys that were only needed for join operations.\n *\n * @param record - The record to remove extended keys from\n * @returns The same record with extended keys removed\n */\n removeExtendedKeys: (record: Record<string, unknown>) => Record<string, unknown>;\n}\n\n/**\n * Builder for extending a select clause with additional keys.\n * @internal\n */\nexport interface SelectBuilder {\n /**\n * Adds a key to the select clause if not already present.\n * Tracks which keys were added for later removal.\n *\n * @param key - The key to add to the select clause\n */\n extend: (key: string) => void;\n\n /**\n * Compiles the select clause into its final form.\n *\n * @returns The compiled select information\n */\n compile: () => CompiledSelect;\n}\n\n/**\n * Creates a builder that can extend a select clause with additional keys.\n *\n * This is useful when you need to temporarily include columns for join operations\n * or other internal processing, but don't want them in the final result.\n *\n * @param original - The original select clause from the user\n * @returns A select builder with extend() and compile() methods\n * @internal\n */\nexport function extendSelect(original: AnySelectClause): SelectBuilder {\n const select = Array.isArray(original) ? new Set(original) : true;\n const extendedKeys: string[] = [];\n\n return {\n extend(key) {\n if (select === true || select.has(key)) {\n return;\n }\n\n select.add(key);\n extendedKeys.push(key);\n },\n compile() {\n return {\n result: select instanceof Set ? Array.from(select) : true,\n extendedKeys,\n removeExtendedKeys(record) {\n for (const key of extendedKeys) {\n delete record[key];\n }\n return record;\n },\n };\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,SAAgB,UACd,QACA,OACA,UACA,UAGI,EAAE,EACI;CACV,MAAM,EAAE,UAAU,YAAY,MAAM,SAAS;CAC7C,MAAMA,MAAgB,EAAE;CACxB,MAAM,OAAO,MAAM,QAAQ,OAAO,GAAG,SAAS,OAAO,KAAK,MAAM,QAAQ;AAExE,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,MAAM,MAAM,QAAQ;AAG1B,MAAI,MAAM,QAAQ,OAAO,IAAI,IAAI,SAC/B;EAIF,MAAM,OAAO,WAAW,GAAG,SAAS,GAAG,QAAQ;EAC/C,MAAM,aAAa,WAAW,SAAS,cAAc,MAAM,MAAM,IAAI,KAAK,GAAG,IAAI;AACjF,MAAI,KAAK,GAAG,UAAU,GAAG,WAAW,MAAM,OAAO;;AAInD,MAAK,MAAM,OAAO,MAAM,SAAS;EAC/B,MAAM,MAAM,MAAM,QAAQ;AAC1B,MAAI,IAAI,YAAY,CAAC,KAAK,SAAS,IAAI,EAAE;GACvC,MAAM,OAAO,WAAW,GAAG,SAAS,GAAG,QAAQ;GAC/C,MAAM,aAAa,WAAW,SAAS,cAAc,MAAM,MAAM,IAAI,KAAK,GAAG,IAAI;AACjF,OAAI,KAAK,GAAG,UAAU,GAAG,WAAW,MAAM,OAAO;;;AAIrD,QAAO;;;;;;;;;;;;AA2DT,SAAgB,aAAa,UAA0C;CACrE,MAAM,SAAS,MAAM,QAAQ,SAAS,GAAG,IAAI,IAAI,SAAS,GAAG;CAC7D,MAAMC,eAAyB,EAAE;AAEjC,QAAO;EACL,OAAO,KAAK;AACV,OAAI,WAAW,QAAQ,OAAO,IAAI,IAAI,CACpC;AAGF,UAAO,IAAI,IAAI;AACf,gBAAa,KAAK,IAAI;;EAExB,UAAU;AACR,UAAO;IACL,QAAQ,kBAAkB,MAAM,MAAM,KAAK,OAAO,GAAG;IACrD;IACA,mBAAmB,QAAQ;AACzB,UAAK,MAAM,OAAO,aAChB,QAAO,OAAO;AAEhB,YAAO;;IAEV;;EAEJ"}
@@ -1,6 +1,6 @@
1
1
  import { buildWhere, fullSQLName } from "./where-builder.js";
2
- import { extendSelect, mapSelect } from "./select-builder.js";
3
2
  import { UnitOfWorkEncoder } from "../uow-encoder.js";
3
+ import { extendSelect, mapSelect } from "./select-builder.js";
4
4
  import { sql } from "kysely";
5
5
 
6
6
  //#region src/adapters/generic-sql/query/sql-query-compiler.ts
@@ -37,13 +37,13 @@ var SQLQueryCompiler = class {
37
37
  /**
38
38
  * Build WHERE clause from a condition tree.
39
39
  */
40
- buildWhereClause(condition, eb, table) {
41
- return buildWhere(condition, eb, this.driverConfig, this.sqliteStorageMode, this.resolver, table);
40
+ buildWhereClause(condition, eb, table, tableAlias) {
41
+ return buildWhere(condition, eb, this.driverConfig, this.sqliteStorageMode, this.resolver, table, tableAlias);
42
42
  }
43
43
  /**
44
44
  * Process joins recursively to support nested joins.
45
45
  */
46
- processJoins(query, joins, parentTable, parentTableName, mappedSelect, parentPath = "") {
46
+ processJoins(query, joins, parentTable, parentTableName, mappedSelect, parentPath = "", aliasCollector, readTracking) {
47
47
  let result = query;
48
48
  for (const join of joins) {
49
49
  const { options: joinOptions, relation } = join;
@@ -51,24 +51,51 @@ var SQLQueryCompiler = class {
51
51
  const targetTable = relation.table;
52
52
  const fullPath = parentPath ? `${parentPath}:${relation.name}` : relation.name;
53
53
  const joinName = fullPath.replace(/:/g, "_");
54
- mappedSelect.push(...mapSelect(joinOptions.select, targetTable, this.resolver, {
54
+ if (aliasCollector) aliasCollector.push({
55
+ table: targetTable,
56
+ alias: joinName
57
+ });
58
+ const joinSelectBuilder = extendSelect(joinOptions.select);
59
+ if (readTracking) joinSelectBuilder.extend(targetTable.getIdColumn().name);
60
+ const compiledJoinSelect = joinSelectBuilder.compile();
61
+ mappedSelect.push(...mapSelect(compiledJoinSelect.result, targetTable, this.resolver, {
55
62
  relation: fullPath,
56
63
  tableName: joinName
57
64
  }));
58
65
  result = result.leftJoin(`${this.getTableName(targetTable)} as ${joinName}`, (b) => b.on((eb) => {
59
66
  const conditions = [];
60
67
  for (const [left, right] of relation.on) {
68
+ const actualLeft = parentTable.columns[left]?.role === "external-id" ? parentTable.getInternalIdColumn().name : left;
69
+ const actualLeftCol = parentTable.columns[actualLeft];
61
70
  const actualRight = targetTable.columns[right]?.role === "external-id" ? "_internalId" : right;
62
- conditions.push(eb(`${parentTableName}.${this.resolver ? this.resolver.getColumnName(parentTable.name, parentTable.columns[left].name) : parentTable.columns[left].name}`, "=", eb.ref(`${joinName}.${this.resolver ? this.resolver.getColumnName(targetTable.name, targetTable.columns[actualRight].name) : targetTable.columns[actualRight].name}`)));
71
+ conditions.push(eb(`${parentTableName}.${this.resolver ? this.resolver.getColumnName(parentTable.name, actualLeftCol ? actualLeftCol.name : parentTable.columns[left].name) : (actualLeftCol ?? parentTable.columns[left]).name}`, "=", eb.ref(`${joinName}.${this.resolver ? this.resolver.getColumnName(targetTable.name, targetTable.columns[actualRight].name) : targetTable.columns[actualRight].name}`)));
63
72
  }
64
- if (joinOptions.where) conditions.push(this.buildWhereClause(joinOptions.where, eb, targetTable));
73
+ if (joinOptions.where) conditions.push(this.buildWhereClause(joinOptions.where, eb, targetTable, joinName));
65
74
  return eb.and(conditions);
66
75
  }));
67
- if (joinOptions.join && joinOptions.join.length > 0) result = this.processJoins(result, joinOptions.join, targetTable, joinName, mappedSelect, fullPath);
76
+ if (joinOptions.join && joinOptions.join.length > 0) result = this.processJoins(result, joinOptions.join, targetTable, joinName, mappedSelect, fullPath, aliasCollector, readTracking);
68
77
  }
69
78
  return result;
70
79
  }
71
80
  /**
81
+ * Build a select query with joins applied, returning a list of table aliases used.
82
+ * Intended for conflict checks that need to mirror the join tree from queries.
83
+ */
84
+ buildJoinQuery(table, options) {
85
+ const tableName = this.getTableName(table);
86
+ let query = this.db.selectFrom(tableName);
87
+ const aliases = [{
88
+ table,
89
+ alias: tableName
90
+ }];
91
+ if (options.where) query = query.where((eb) => this.buildWhereClause(options.where, eb, table));
92
+ if (options.join && options.join.length > 0) query = this.processJoins(query, options.join, table, tableName, [], "", aliases);
93
+ return {
94
+ query,
95
+ aliases
96
+ };
97
+ }
98
+ /**
72
99
  * Compile a COUNT query.
73
100
  */
74
101
  compileCount(table, options) {
@@ -87,8 +114,9 @@ var SQLQueryCompiler = class {
87
114
  if (options.limit !== void 0) query = this.applyLimit(query, options.limit);
88
115
  if (options.orderBy) for (const [col, mode] of options.orderBy) query = query.orderBy(fullSQLName(col, this.resolver), mode);
89
116
  const selectBuilder = extendSelect(options.select);
117
+ if (options.readTracking) selectBuilder.extend(table.getIdColumn().name);
90
118
  const mappedSelect = [];
91
- if (options.join && options.join.length > 0) query = this.processJoins(query, options.join, table, this.getTableName(table), mappedSelect);
119
+ if (options.join && options.join.length > 0) query = this.processJoins(query, options.join, table, this.getTableName(table), mappedSelect, "", void 0, options.readTracking);
92
120
  const compiledSelect = selectBuilder.compile();
93
121
  mappedSelect.push(...mapSelect(compiledSelect.result, table, this.resolver, { tableName: this.getTableName(table) }));
94
122
  return query.select(mappedSelect).compile();
@@ -1 +1 @@
1
- {"version":3,"file":"sql-query-compiler.js","names":["mappedSelect: string[]","insert: AnyInsertQueryBuilder"],"sources":["../../../../src/adapters/generic-sql/query/sql-query-compiler.ts"],"sourcesContent":["import type {\n CompiledQuery,\n Kysely,\n ExpressionBuilder,\n ExpressionWrapper,\n SelectQueryBuilder,\n InsertQueryBuilder,\n} from \"kysely\";\nimport { sql } from \"kysely\";\nimport type { SqlBool } from \"kysely\";\nimport type { AnyColumn, AnyTable } from \"../../../schema/create\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport type { DriverConfig, SupportedDatabase } from \"../driver-config\";\nimport type { SQLiteStorageMode } from \"../sqlite-storage\";\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\nimport { buildWhere, fullSQLName } from \"./where-builder\";\nimport { mapSelect, extendSelect } from \"./select-builder\";\nimport type { CompiledJoin } from \"../../../query/orm/orm\";\nimport { UnitOfWorkEncoder } from \"../uow-encoder\";\n\n/**\n * Type helpers for Kysely query builders.\n *\n * These use `any` for database schema types because at this abstraction layer,\n * we cannot know the specific database schema - we work with generic query\n * compilation that needs to work across any schema.\n */\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyKysely = Kysely<any>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyExpressionBuilder = ExpressionBuilder<any, any>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyExpressionWrapper = ExpressionWrapper<any, any, SqlBool>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnySelectQueryBuilder<O = any> = SelectQueryBuilder<any, any, O>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyInsertQueryBuilder<O = any> = InsertQueryBuilder<any, any, O>;\n\n/**\n * Options for compiling a find operation\n */\nexport interface FindManyCompilerOptions {\n select: true | string[];\n where?: Condition;\n orderBy?: [AnyColumn, \"asc\" | \"desc\"][];\n limit?: number;\n offset?: number;\n join?: CompiledJoin[];\n}\n\n/**\n * Options for compiling a count operation\n */\nexport interface CountCompilerOptions {\n where?: Condition;\n}\n\n/**\n * Options for compiling an update operation\n */\nexport interface UpdateCompilerOptions {\n where?: Condition;\n set: Record<string, unknown>;\n /**\n * Whether to add RETURNING clause to the UPDATE query.\n * Used for version conflict detection when driver supports RETURNING but not affected rows.\n */\n returning?: boolean;\n}\n\n/**\n * Options for compiling a delete operation\n */\nexport interface DeleteCompilerOptions {\n where?: Condition;\n /**\n * Whether to add RETURNING clause to the DELETE query.\n * Used for version conflict detection when driver supports RETURNING but not affected rows.\n */\n returning?: boolean;\n}\n\n/**\n * Abstract base class for SQL query compilation.\n *\n * Similar to SQLGenerator for migrations, this class provides a framework\n * for compiling runtime queries with dialect-specific behavior.\n *\n * Each database dialect extends this class and implements the abstract methods\n * to handle database-specific SQL generation (like .limit() vs .top()).\n */\nexport abstract class SQLQueryCompiler {\n protected readonly db: AnyKysely;\n protected readonly driverConfig: DriverConfig;\n protected readonly database: SupportedDatabase;\n protected readonly resolver?: NamingResolver;\n protected readonly encoder: UnitOfWorkEncoder;\n protected readonly sqliteStorageMode?: SQLiteStorageMode;\n\n constructor(\n db: AnyKysely,\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n resolver?: NamingResolver,\n ) {\n this.db = db;\n this.driverConfig = driverConfig;\n this.database = driverConfig.databaseType;\n this.resolver = resolver;\n this.sqliteStorageMode = sqliteStorageMode;\n this.encoder = new UnitOfWorkEncoder(driverConfig, db, sqliteStorageMode, resolver);\n }\n\n /**\n * Apply LIMIT clause to a query.\n * Different databases use different syntax (.limit() vs .top()).\n */\n protected abstract applyLimit<T>(query: T & { limit(limit: number): T }, limit: number): T;\n\n /**\n * Apply OFFSET clause to a query.\n * Some databases may not support offset.\n */\n protected abstract applyOffset<T>(query: T & { offset(offset: number): T }, offset: number): T;\n\n /**\n * Apply RETURNING clause to an insert/update query.\n * Returns the query with RETURNING if supported, otherwise returns as-is.\n */\n protected abstract applyReturning<T>(\n query: T & { returning(columns: string[]): T },\n columns: string[],\n ): T;\n\n /**\n * Get the physical table name, applying namespace mapping if provided.\n */\n protected getTableName(table: AnyTable): string {\n return this.resolver ? this.resolver.getTableName(table.name) : table.name;\n }\n\n /**\n * Build WHERE clause from a condition tree.\n */\n protected buildWhereClause(condition: Condition, eb: AnyExpressionBuilder, table: AnyTable) {\n return buildWhere(\n condition,\n eb,\n this.driverConfig,\n this.sqliteStorageMode,\n this.resolver,\n table,\n );\n }\n\n /**\n * Process joins recursively to support nested joins.\n */\n protected processJoins<O>(\n query: AnySelectQueryBuilder<O>,\n joins: CompiledJoin[],\n parentTable: AnyTable,\n parentTableName: string,\n mappedSelect: string[],\n parentPath: string = \"\",\n ): AnySelectQueryBuilder<O> {\n let result = query;\n\n for (const join of joins) {\n const { options: joinOptions, relation } = join;\n\n if (joinOptions === false) {\n continue;\n }\n\n const targetTable = relation.table;\n // Build the full path for this join (e.g., \"author:inviter\")\n const fullPath = parentPath ? `${parentPath}:${relation.name}` : relation.name;\n // SQL table alias uses underscores (e.g., \"author_inviter\")\n const joinName = fullPath.replace(/:/g, \"_\");\n\n // Update select\n mappedSelect.push(\n ...mapSelect(joinOptions.select, targetTable, this.resolver, {\n relation: fullPath, // Use full path with colons for column aliases\n tableName: joinName, // Use underscore version for table name\n }),\n );\n\n result = result.leftJoin(`${this.getTableName(targetTable)} as ${joinName}`, (b) =>\n b.on((eb) => {\n const conditions = [];\n for (const [left, right] of relation.on) {\n // Foreign keys always use internal IDs\n // If the relation references an external ID column (any name), translate to \"_internalId\"\n const rightCol = targetTable.columns[right];\n const actualRight = rightCol?.role === \"external-id\" ? \"_internalId\" : right;\n\n conditions.push(\n eb(\n `${parentTableName}.${\n this.resolver\n ? this.resolver.getColumnName(parentTable.name, parentTable.columns[left].name)\n : parentTable.columns[left].name\n }`,\n \"=\",\n eb.ref(\n `${joinName}.${\n this.resolver\n ? this.resolver.getColumnName(\n targetTable.name,\n targetTable.columns[actualRight].name,\n )\n : targetTable.columns[actualRight].name\n }`,\n ),\n ),\n );\n }\n\n if (joinOptions.where) {\n conditions.push(this.buildWhereClause(joinOptions.where, eb, targetTable));\n }\n\n return eb.and(conditions);\n }),\n );\n\n // Recursively process nested joins with the full path\n if (joinOptions.join && joinOptions.join.length > 0) {\n result = this.processJoins(\n result,\n joinOptions.join,\n targetTable,\n joinName,\n mappedSelect,\n fullPath,\n );\n }\n }\n\n return result;\n }\n\n /**\n * Compile a COUNT query.\n */\n compileCount(table: AnyTable, options: CountCompilerOptions): CompiledQuery {\n let query = this.db\n .selectFrom(this.getTableName(table))\n .select(this.db.fn.countAll().as(\"count\"));\n\n if (options.where) {\n query = query.where((b) => this.buildWhereClause(options.where!, b, table));\n }\n\n return query.compile();\n }\n\n /**\n * Compile a FIND MANY query.\n */\n compileFindMany(table: AnyTable, options: FindManyCompilerOptions): CompiledQuery {\n let query = this.db.selectFrom(this.getTableName(table));\n\n // Apply WHERE clause\n const whereQuery = options.where;\n if (whereQuery) {\n query = query.where((eb) => this.buildWhereClause(whereQuery, eb, table));\n }\n\n // Apply OFFSET\n if (options.offset !== undefined) {\n query = this.applyOffset(query, options.offset);\n }\n\n // Apply LIMIT\n if (options.limit !== undefined) {\n query = this.applyLimit(query, options.limit);\n }\n\n // Apply ORDER BY\n if (options.orderBy) {\n for (const [col, mode] of options.orderBy) {\n query = query.orderBy(fullSQLName(col, this.resolver), mode);\n }\n }\n\n // Build SELECT with joins\n const selectBuilder = extendSelect(options.select);\n const mappedSelect: string[] = [];\n\n // Process joins if provided\n if (options.join && options.join.length > 0) {\n query = this.processJoins(query, options.join, table, this.getTableName(table), mappedSelect);\n }\n\n const compiledSelect = selectBuilder.compile();\n mappedSelect.push(\n ...mapSelect(compiledSelect.result, table, this.resolver, {\n tableName: this.getTableName(table),\n }),\n );\n\n return query.select(mappedSelect).compile();\n }\n\n /**\n * Compile a CREATE (INSERT) query.\n */\n compileCreate(table: AnyTable, values: Record<string, unknown>): CompiledQuery {\n // Encode application values to database format (resolves FragnoId, generates defaults, serializes)\n const encodedValues = this.encoder.encodeForDatabase({\n values,\n table,\n generateDefaults: true,\n });\n\n let insert: AnyInsertQueryBuilder = this.db\n .insertInto(this.getTableName(table))\n .values(encodedValues);\n\n // Apply RETURNING if supported\n if (this.driverConfig.supportsReturning) {\n const columns = mapSelect(true, table, this.resolver, {\n tableName: this.getTableName(table),\n });\n insert = this.applyReturning(insert, columns);\n }\n\n return insert.compile();\n }\n\n /**\n * Compile an UPDATE query.\n */\n compileUpdate(table: AnyTable, options: UpdateCompilerOptions): CompiledQuery {\n const encoded = this.encoder.encodeForDatabase({\n values: options.set,\n table,\n generateDefaults: false,\n });\n\n // Add version increment (must be added after encoding, as a raw SQL expression)\n const versionCol = table.getVersionColumn();\n const versionColumnName = this.resolver\n ? this.resolver.getColumnName(table.name, versionCol.name)\n : versionCol.name;\n encoded[versionColumnName] = sql`coalesce(${sql.ref(versionColumnName)}, 0) + 1`;\n\n let query = this.db.updateTable(this.getTableName(table)).set(encoded);\n\n if (options.where) {\n query = query.where((eb) => this.buildWhereClause(options.where!, eb, table));\n }\n\n // Apply RETURNING if requested and supported\n // Use sql template tag for literal value (not a column name)\n if (options.returning && this.driverConfig.supportsReturning) {\n return query.returning(sql<number>`1`.as(\"_returned\")).compile();\n }\n\n return query.compile();\n }\n\n /**\n * Compile a DELETE query.\n */\n compileDelete(table: AnyTable, options: DeleteCompilerOptions): CompiledQuery {\n let query = this.db.deleteFrom(this.getTableName(table));\n\n if (options.where) {\n query = query.where((eb) => this.buildWhereClause(options.where!, eb, table));\n }\n\n // Apply RETURNING if requested and supported\n // Use sql template tag for literal value (not a column name)\n if (options.returning && this.driverConfig.supportsReturning) {\n return query.returning(sql<number>`1`.as(\"_returned\")).compile();\n }\n\n return query.compile();\n }\n\n /**\n * Compile a CHECK query (SELECT 1 to verify a row exists).\n */\n compileCheck(table: AnyTable, where: Condition): CompiledQuery {\n const query = this.db\n .selectFrom(this.getTableName(table))\n .select(sql<number>`1`.as(\"exists\"))\n .where((eb) => this.buildWhereClause(where, eb, table))\n .limit(1);\n\n return query.compile();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"sql-query-compiler.js","names":["aliases: JoinAliasInfo[]","mappedSelect: string[]","insert: AnyInsertQueryBuilder"],"sources":["../../../../src/adapters/generic-sql/query/sql-query-compiler.ts"],"sourcesContent":["import type {\n CompiledQuery,\n Kysely,\n ExpressionBuilder,\n ExpressionWrapper,\n SelectQueryBuilder,\n InsertQueryBuilder,\n} from \"kysely\";\nimport { sql } from \"kysely\";\nimport type { SqlBool } from \"kysely\";\n\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport type { CompiledJoin } from \"../../../query/orm/orm\";\nimport type { AnyColumn, AnyTable } from \"../../../schema/create\";\nimport type { DriverConfig, SupportedDatabase } from \"../driver-config\";\nimport type { SQLiteStorageMode } from \"../sqlite-storage\";\nimport { UnitOfWorkEncoder } from \"../uow-encoder\";\nimport { mapSelect, extendSelect } from \"./select-builder\";\nimport { buildWhere, fullSQLName } from \"./where-builder\";\n\n/**\n * Type helpers for Kysely query builders.\n *\n * These use `any` for database schema types because at this abstraction layer,\n * we cannot know the specific database schema - we work with generic query\n * compilation that needs to work across any schema.\n */\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyKysely = Kysely<any>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyExpressionBuilder = ExpressionBuilder<any, any>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyExpressionWrapper = ExpressionWrapper<any, any, SqlBool>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnySelectQueryBuilder<O = any> = SelectQueryBuilder<any, any, O>;\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyInsertQueryBuilder<O = any> = InsertQueryBuilder<any, any, O>;\n\n/**\n * Options for compiling a find operation\n */\nexport interface FindManyCompilerOptions {\n select: true | readonly string[];\n where?: Condition;\n orderBy?: [AnyColumn, \"asc\" | \"desc\"][];\n limit?: number;\n offset?: number;\n join?: CompiledJoin[];\n readTracking?: boolean;\n}\n\n/**\n * Options for compiling a count operation\n */\nexport interface CountCompilerOptions {\n where?: Condition;\n}\n\n/**\n * Options for compiling an update operation\n */\nexport interface UpdateCompilerOptions {\n where?: Condition;\n set: Record<string, unknown>;\n /**\n * Whether to add RETURNING clause to the UPDATE query.\n * Used for version conflict detection when driver supports RETURNING but not affected rows.\n */\n returning?: boolean;\n}\n\n/**\n * Options for compiling a delete operation\n */\nexport interface DeleteCompilerOptions {\n where?: Condition;\n /**\n * Whether to add RETURNING clause to the DELETE query.\n * Used for version conflict detection when driver supports RETURNING but not affected rows.\n */\n returning?: boolean;\n}\n\nexport type JoinAliasInfo = {\n table: AnyTable;\n alias: string;\n};\n\n/**\n * Abstract base class for SQL query compilation.\n *\n * Similar to SQLGenerator for migrations, this class provides a framework\n * for compiling runtime queries with dialect-specific behavior.\n *\n * Each database dialect extends this class and implements the abstract methods\n * to handle database-specific SQL generation (like .limit() vs .top()).\n */\nexport abstract class SQLQueryCompiler {\n protected readonly db: AnyKysely;\n protected readonly driverConfig: DriverConfig;\n protected readonly database: SupportedDatabase;\n protected readonly resolver?: NamingResolver;\n protected readonly encoder: UnitOfWorkEncoder;\n protected readonly sqliteStorageMode?: SQLiteStorageMode;\n\n constructor(\n db: AnyKysely,\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n resolver?: NamingResolver,\n ) {\n this.db = db;\n this.driverConfig = driverConfig;\n this.database = driverConfig.databaseType;\n this.resolver = resolver;\n this.sqliteStorageMode = sqliteStorageMode;\n this.encoder = new UnitOfWorkEncoder(driverConfig, db, sqliteStorageMode, resolver);\n }\n\n /**\n * Apply LIMIT clause to a query.\n * Different databases use different syntax (.limit() vs .top()).\n */\n protected abstract applyLimit<T>(query: T & { limit(limit: number): T }, limit: number): T;\n\n /**\n * Apply OFFSET clause to a query.\n * Some databases may not support offset.\n */\n protected abstract applyOffset<T>(query: T & { offset(offset: number): T }, offset: number): T;\n\n /**\n * Apply RETURNING clause to an insert/update query.\n * Returns the query with RETURNING if supported, otherwise returns as-is.\n */\n protected abstract applyReturning<T>(\n query: T & { returning(columns: string[]): T },\n columns: string[],\n ): T;\n\n /**\n * Get the physical table name, applying namespace mapping if provided.\n */\n protected getTableName(table: AnyTable): string {\n return this.resolver ? this.resolver.getTableName(table.name) : table.name;\n }\n\n /**\n * Build WHERE clause from a condition tree.\n */\n protected buildWhereClause(\n condition: Condition,\n eb: AnyExpressionBuilder,\n table: AnyTable,\n tableAlias?: string,\n ) {\n return buildWhere(\n condition,\n eb,\n this.driverConfig,\n this.sqliteStorageMode,\n this.resolver,\n table,\n tableAlias,\n );\n }\n\n /**\n * Process joins recursively to support nested joins.\n */\n protected processJoins<O>(\n query: AnySelectQueryBuilder<O>,\n joins: CompiledJoin[],\n parentTable: AnyTable,\n parentTableName: string,\n mappedSelect: string[],\n parentPath: string = \"\",\n aliasCollector?: JoinAliasInfo[],\n readTracking?: boolean,\n ): AnySelectQueryBuilder<O> {\n let result = query;\n\n for (const join of joins) {\n const { options: joinOptions, relation } = join;\n\n if (joinOptions === false) {\n continue;\n }\n\n const targetTable = relation.table;\n // Build the full path for this join (e.g., \"author:inviter\")\n const fullPath = parentPath ? `${parentPath}:${relation.name}` : relation.name;\n // SQL table alias uses underscores (e.g., \"author_inviter\")\n const joinName = fullPath.replace(/:/g, \"_\");\n if (aliasCollector) {\n aliasCollector.push({ table: targetTable, alias: joinName });\n }\n\n const joinSelectBuilder = extendSelect(joinOptions.select);\n if (readTracking) {\n joinSelectBuilder.extend(targetTable.getIdColumn().name);\n }\n const compiledJoinSelect = joinSelectBuilder.compile();\n mappedSelect.push(\n ...mapSelect(compiledJoinSelect.result, targetTable, this.resolver, {\n relation: fullPath, // Use full path with colons for column aliases\n tableName: joinName, // Use underscore version for table name\n }),\n );\n\n result = result.leftJoin(`${this.getTableName(targetTable)} as ${joinName}`, (b) =>\n b.on((eb) => {\n const conditions = [];\n for (const [left, right] of relation.on) {\n const leftCol = parentTable.columns[left];\n const actualLeft =\n leftCol?.role === \"external-id\" ? parentTable.getInternalIdColumn().name : left;\n const actualLeftCol = parentTable.columns[actualLeft];\n // Foreign keys always use internal IDs\n // If the relation references an external ID column (any name), translate to \"_internalId\"\n const rightCol = targetTable.columns[right];\n const actualRight = rightCol?.role === \"external-id\" ? \"_internalId\" : right;\n\n conditions.push(\n eb(\n `${parentTableName}.${\n this.resolver\n ? this.resolver.getColumnName(\n parentTable.name,\n actualLeftCol ? actualLeftCol.name : parentTable.columns[left].name,\n )\n : (actualLeftCol ?? parentTable.columns[left]).name\n }`,\n \"=\",\n eb.ref(\n `${joinName}.${\n this.resolver\n ? this.resolver.getColumnName(\n targetTable.name,\n targetTable.columns[actualRight].name,\n )\n : targetTable.columns[actualRight].name\n }`,\n ),\n ),\n );\n }\n\n if (joinOptions.where) {\n conditions.push(this.buildWhereClause(joinOptions.where, eb, targetTable, joinName));\n }\n\n return eb.and(conditions);\n }),\n );\n\n // Recursively process nested joins with the full path\n if (joinOptions.join && joinOptions.join.length > 0) {\n result = this.processJoins(\n result,\n joinOptions.join,\n targetTable,\n joinName,\n mappedSelect,\n fullPath,\n aliasCollector,\n readTracking,\n );\n }\n }\n\n return result;\n }\n\n /**\n * Build a select query with joins applied, returning a list of table aliases used.\n * Intended for conflict checks that need to mirror the join tree from queries.\n */\n buildJoinQuery(\n table: AnyTable,\n options: { where?: Condition; join?: CompiledJoin[] },\n ): {\n query: AnySelectQueryBuilder;\n aliases: JoinAliasInfo[];\n } {\n const tableName = this.getTableName(table);\n let query = this.db.selectFrom(tableName);\n const aliases: JoinAliasInfo[] = [{ table, alias: tableName }];\n\n if (options.where) {\n query = query.where((eb) => this.buildWhereClause(options.where!, eb, table));\n }\n\n if (options.join && options.join.length > 0) {\n const mappedSelect: string[] = [];\n query = this.processJoins(query, options.join, table, tableName, mappedSelect, \"\", aliases);\n }\n\n return { query, aliases };\n }\n\n /**\n * Compile a COUNT query.\n */\n compileCount(table: AnyTable, options: CountCompilerOptions): CompiledQuery {\n let query = this.db\n .selectFrom(this.getTableName(table))\n .select(this.db.fn.countAll().as(\"count\"));\n\n if (options.where) {\n query = query.where((b) => this.buildWhereClause(options.where!, b, table));\n }\n\n return query.compile();\n }\n\n /**\n * Compile a FIND MANY query.\n */\n compileFindMany(table: AnyTable, options: FindManyCompilerOptions): CompiledQuery {\n let query = this.db.selectFrom(this.getTableName(table));\n\n // Apply WHERE clause\n const whereQuery = options.where;\n if (whereQuery) {\n query = query.where((eb) => this.buildWhereClause(whereQuery, eb, table));\n }\n\n // Apply OFFSET\n if (options.offset !== undefined) {\n query = this.applyOffset(query, options.offset);\n }\n\n // Apply LIMIT\n if (options.limit !== undefined) {\n query = this.applyLimit(query, options.limit);\n }\n\n // Apply ORDER BY\n if (options.orderBy) {\n for (const [col, mode] of options.orderBy) {\n query = query.orderBy(fullSQLName(col, this.resolver), mode);\n }\n }\n\n // Build SELECT with joins\n const selectBuilder = extendSelect(options.select);\n if (options.readTracking) {\n selectBuilder.extend(table.getIdColumn().name);\n }\n const mappedSelect: string[] = [];\n\n // Process joins if provided\n if (options.join && options.join.length > 0) {\n query = this.processJoins(\n query,\n options.join,\n table,\n this.getTableName(table),\n mappedSelect,\n \"\",\n undefined,\n options.readTracking,\n );\n }\n\n const compiledSelect = selectBuilder.compile();\n mappedSelect.push(\n ...mapSelect(compiledSelect.result, table, this.resolver, {\n tableName: this.getTableName(table),\n }),\n );\n\n return query.select(mappedSelect).compile();\n }\n\n /**\n * Compile a CREATE (INSERT) query.\n */\n compileCreate(table: AnyTable, values: Record<string, unknown>): CompiledQuery {\n // Encode application values to database format (resolves FragnoId, generates defaults, serializes)\n const encodedValues = this.encoder.encodeForDatabase({\n values,\n table,\n generateDefaults: true,\n });\n\n let insert: AnyInsertQueryBuilder = this.db\n .insertInto(this.getTableName(table))\n .values(encodedValues);\n\n // Apply RETURNING if supported\n if (this.driverConfig.supportsReturning) {\n const columns = mapSelect(true, table, this.resolver, {\n tableName: this.getTableName(table),\n });\n insert = this.applyReturning(insert, columns);\n }\n\n return insert.compile();\n }\n\n /**\n * Compile an UPDATE query.\n */\n compileUpdate(table: AnyTable, options: UpdateCompilerOptions): CompiledQuery {\n const encoded = this.encoder.encodeForDatabase({\n values: options.set,\n table,\n generateDefaults: false,\n });\n\n // Add version increment (must be added after encoding, as a raw SQL expression)\n const versionCol = table.getVersionColumn();\n const versionColumnName = this.resolver\n ? this.resolver.getColumnName(table.name, versionCol.name)\n : versionCol.name;\n encoded[versionColumnName] = sql`coalesce(${sql.ref(versionColumnName)}, 0) + 1`;\n\n let query = this.db.updateTable(this.getTableName(table)).set(encoded);\n\n if (options.where) {\n query = query.where((eb) => this.buildWhereClause(options.where!, eb, table));\n }\n\n // Apply RETURNING if requested and supported\n // Use sql template tag for literal value (not a column name)\n if (options.returning && this.driverConfig.supportsReturning) {\n return query.returning(sql<number>`1`.as(\"_returned\")).compile();\n }\n\n return query.compile();\n }\n\n /**\n * Compile a DELETE query.\n */\n compileDelete(table: AnyTable, options: DeleteCompilerOptions): CompiledQuery {\n let query = this.db.deleteFrom(this.getTableName(table));\n\n if (options.where) {\n query = query.where((eb) => this.buildWhereClause(options.where!, eb, table));\n }\n\n // Apply RETURNING if requested and supported\n // Use sql template tag for literal value (not a column name)\n if (options.returning && this.driverConfig.supportsReturning) {\n return query.returning(sql<number>`1`.as(\"_returned\")).compile();\n }\n\n return query.compile();\n }\n\n /**\n * Compile a CHECK query (SELECT 1 to verify a row exists).\n */\n compileCheck(table: AnyTable, where: Condition): CompiledQuery {\n const query = this.db\n .selectFrom(this.getTableName(table))\n .select(sql<number>`1`.as(\"exists\"))\n .where((eb) => this.buildWhereClause(where, eb, table))\n .limit(1);\n\n return query.compile();\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
+ import { getDbNowOffsetMs, isDbNow } from "../../../query/db-now.js";
1
2
  import { Column, FragnoId, FragnoReference } from "../../../schema/create.js";
2
- import { sqliteStorageDefault } from "../sqlite-storage.js";
3
3
  import { createSQLSerializer } from "../../../query/serialize/create-sql-serializer.js";
4
4
  import { ReferenceSubquery, resolveFragnoIdValue } from "../../../query/value-encoding.js";
5
- import { isDbNow } from "../../../query/db-now.js";
5
+ import { buildDbNowSql } from "./db-now-sql.js";
6
6
  import { sql } from "kysely";
7
7
 
8
8
  //#region src/adapters/generic-sql/query/where-builder.ts
@@ -17,6 +17,10 @@ import { sql } from "kysely";
17
17
  function fullSQLName(column, resolver) {
18
18
  return `${resolver ? resolver.getTableName(column.tableName) : column.tableName}.${resolver ? resolver.getColumnName(column.tableName, column.name) : column.name}`;
19
19
  }
20
+ function fullSQLNameWithAlias(column, resolver, table, tableAlias) {
21
+ if (table && tableAlias && column.tableName === table.name) return `${tableAlias}.${resolver ? resolver.getColumnName(column.tableName, column.name) : column.name}`;
22
+ return fullSQLName(column, resolver);
23
+ }
20
24
  /**
21
25
  * Builds a WHERE clause expression from a Condition tree.
22
26
  *
@@ -32,18 +36,18 @@ function fullSQLName(column, resolver) {
32
36
  * @returns A Kysely expression wrapper representing the WHERE clause
33
37
  * @internal
34
38
  */
35
- function buildWhere(condition, eb, driverConfig, sqliteStorageMode, resolver, table) {
39
+ function buildWhere(condition, eb, driverConfig, sqliteStorageMode, resolver, table, tableAlias) {
36
40
  const serializer = createSQLSerializer(driverConfig, sqliteStorageMode);
37
41
  if (condition.type === "compare") {
38
42
  const left = condition.a;
39
43
  const op = condition.operator;
40
44
  let val = condition.b;
41
- if (!(val instanceof Column)) if (isDbNow(val)) if (driverConfig.databaseType === "sqlite") {
42
- const storageMode = sqliteStorageMode ?? sqliteStorageDefault;
43
- const storage = left.type === "date" ? storageMode.dateStorage : storageMode.timestampStorage;
44
- if ((left.type === "timestamp" || left.type === "date") && storage === "epoch-ms") val = sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`;
45
- else val = sql`CURRENT_TIMESTAMP`;
46
- } else val = sql`CURRENT_TIMESTAMP`;
45
+ if (!(val instanceof Column)) if (isDbNow(val)) val = buildDbNowSql({
46
+ driverConfig,
47
+ columnType: left.type,
48
+ offsetMs: getDbNowOffsetMs(val),
49
+ sqliteStorageMode
50
+ });
47
51
  else if (left.role === "reference" && table) if (typeof val === "string") {
48
52
  const relation = Object.values(table.relations).find((rel) => rel.on.some(([localCol]) => localCol === left.name));
49
53
  if (relation) {
@@ -77,37 +81,37 @@ function buildWhere(condition, eb, driverConfig, sqliteStorageMode, resolver, ta
77
81
  switch (op) {
78
82
  case "contains":
79
83
  v = "like";
80
- rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))}, '%')` : `%${val}%`;
84
+ rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))}, '%')` : `%${val}%`;
81
85
  break;
82
86
  case "not contains":
83
87
  v = "not like";
84
- rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))}, '%')` : `%${val}%`;
88
+ rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))}, '%')` : `%${val}%`;
85
89
  break;
86
90
  case "starts with":
87
91
  v = "like";
88
- rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLName(val, resolver))}, '%')` : `${val}%`;
92
+ rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))}, '%')` : `${val}%`;
89
93
  break;
90
94
  case "not starts with":
91
95
  v = "not like";
92
- rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLName(val, resolver))}, '%')` : `${val}%`;
96
+ rhs = val instanceof Column ? sql`concat(${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))}, '%')` : `${val}%`;
93
97
  break;
94
98
  case "ends with":
95
99
  v = "like";
96
- rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))})` : `%${val}`;
100
+ rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))})` : `%${val}`;
97
101
  break;
98
102
  case "not ends with":
99
103
  v = "not like";
100
- rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))})` : `%${val}`;
104
+ rhs = val instanceof Column ? sql`concat('%', ${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))})` : `%${val}`;
101
105
  break;
102
106
  default:
103
107
  v = op;
104
- rhs = val instanceof Column ? eb.ref(fullSQLName(val, resolver)) : val;
108
+ rhs = val instanceof Column ? eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias)) : val;
105
109
  }
106
- return eb(fullSQLName(left, resolver), v, rhs);
110
+ return eb(fullSQLNameWithAlias(left, resolver, table, tableAlias), v, rhs);
107
111
  }
108
- if (condition.type === "and") return eb.and(condition.items.map((v) => buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table)));
109
- if (condition.type === "not") return eb.not(buildWhere(condition.item, eb, driverConfig, sqliteStorageMode, resolver, table));
110
- return eb.or(condition.items.map((v) => buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table)));
112
+ if (condition.type === "and") return eb.and(condition.items.map((v) => buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table, tableAlias)));
113
+ if (condition.type === "not") return eb.not(buildWhere(condition.item, eb, driverConfig, sqliteStorageMode, resolver, table, tableAlias));
114
+ return eb.or(condition.items.map((v) => buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table, tableAlias)));
111
115
  }
112
116
  /**
113
117
  * Process reference subqueries in encoded values, converting them to Kysely SQL subqueries
@@ -1 +1 @@
1
- {"version":3,"file":"where-builder.js","names":["v: BinaryOperator","rhs: unknown","processed: Record<string, unknown>"],"sources":["../../../../src/adapters/generic-sql/query/where-builder.ts"],"sourcesContent":["import { sql, type BinaryOperator } from \"kysely\";\nimport {\n type AnyColumn,\n type AnyTable,\n Column,\n FragnoId,\n FragnoReference,\n} from \"../../../schema/create\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport { createSQLSerializer } from \"../../../query/serialize/create-sql-serializer\";\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\nimport type { DriverConfig } from \"../driver-config\";\nimport { sqliteStorageDefault, type SQLiteStorageMode } from \"../sqlite-storage\";\nimport { ReferenceSubquery, resolveFragnoIdValue } from \"../../../query/value-encoding\";\nimport { isDbNow } from \"../../../query/db-now\";\nimport type { AnyKysely, AnyExpressionBuilder, AnyExpressionWrapper } from \"./sql-query-compiler\";\n\n/**\n * Returns the fully qualified SQL name for a column (table.column).\n *\n * @param column - The column to get the full name for\n * @param resolver - Optional naming resolver for namespace prefixing\n * @returns The fully qualified SQL name in the format \"tableName.columnName\"\n * @internal\n */\nexport function fullSQLName(column: AnyColumn, resolver?: NamingResolver): string {\n const tableName = resolver ? resolver.getTableName(column.tableName) : column.tableName;\n const columnName = resolver ? resolver.getColumnName(column.tableName, column.name) : column.name;\n return `${tableName}.${columnName}`;\n}\n\n/**\n * Builds a WHERE clause expression from a Condition tree.\n *\n * Recursively processes condition objects to build Kysely WHERE expressions.\n * Handles comparison operators, logical AND/OR/NOT, and special string operators\n * like \"contains\", \"starts with\", and \"ends with\".\n *\n * @param condition - The condition tree to build the WHERE clause from\n * @param eb - Kysely expression builder for constructing SQL expressions\n * @param database - The database type (affects SQL generation)\n * @param resolver - Optional naming resolver for namespace prefixing\n * @param table - The table being queried (used for resolving reference columns)\n * @returns A Kysely expression wrapper representing the WHERE clause\n * @internal\n */\nexport function buildWhere(\n condition: Condition,\n eb: AnyExpressionBuilder,\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n resolver?: NamingResolver,\n table?: AnyTable,\n): AnyExpressionWrapper {\n const serializer = createSQLSerializer(driverConfig, sqliteStorageMode);\n\n if (condition.type === \"compare\") {\n const left = condition.a;\n const op = condition.operator;\n let val = condition.b;\n\n if (!(val instanceof Column)) {\n if (isDbNow(val)) {\n if (driverConfig.databaseType === \"sqlite\") {\n const storageMode = sqliteStorageMode ?? sqliteStorageDefault;\n const storage =\n left.type === \"date\" ? storageMode.dateStorage : storageMode.timestampStorage;\n if ((left.type === \"timestamp\" || left.type === \"date\") && storage === \"epoch-ms\") {\n val = sql`(cast((julianday('now') - 2440587.5)*86400000 as integer))`;\n } else {\n val = sql`CURRENT_TIMESTAMP`;\n }\n } else {\n val = sql`CURRENT_TIMESTAMP`;\n }\n } else if (left.role === \"reference\" && table) {\n // Handle reference columns specially\n if (typeof val === \"string\") {\n // String external ID - create subquery to lookup internal ID\n const relation = Object.values(table.relations).find((rel) =>\n rel.on.some(([localCol]) => localCol === left.name),\n );\n if (relation) {\n const refTable = relation.table;\n const internalIdCol = refTable.getInternalIdColumn();\n const idCol = refTable.getIdColumn();\n const physicalTableName = resolver\n ? resolver.getTableName(refTable.name)\n : refTable.name;\n\n val = eb\n .selectFrom(physicalTableName)\n .select(\n resolver\n ? resolver.getColumnName(refTable.name, internalIdCol.name)\n : internalIdCol.name,\n )\n .where(\n resolver ? resolver.getColumnName(refTable.name, idCol.name) : idCol.name,\n \"=\",\n val,\n )\n .limit(1);\n }\n } else if (val instanceof FragnoId && val.internalId !== undefined) {\n // FragnoId with internal ID - use it directly (no serialization needed)\n val = val.internalId;\n } else if (val instanceof FragnoId && val.internalId === undefined) {\n // FragnoId without internal ID - create subquery using external ID\n const relation = Object.values(table.relations).find((rel) =>\n rel.on.some(([localCol]) => localCol === left.name),\n );\n if (relation) {\n const refTable = relation.table;\n const internalIdCol = refTable.getInternalIdColumn();\n const idCol = refTable.getIdColumn();\n const physicalTableName = resolver\n ? resolver.getTableName(refTable.name)\n : refTable.name;\n\n val = eb\n .selectFrom(physicalTableName)\n .select(\n resolver\n ? resolver.getColumnName(refTable.name, internalIdCol.name)\n : internalIdCol.name,\n )\n .where(\n resolver ? resolver.getColumnName(refTable.name, idCol.name) : idCol.name,\n \"=\",\n val.externalId,\n )\n .limit(1);\n }\n } else if (val instanceof FragnoReference) {\n // FragnoReference - use internal ID directly (no serialization needed)\n val = val.internalId;\n } else {\n // Other values - resolve and serialize\n const resolvedVal = resolveFragnoIdValue(val, left);\n val = serializer.serialize(resolvedVal, left);\n }\n } else {\n // Non-reference columns - resolve FragnoId/FragnoReference and serialize\n const resolvedVal = resolveFragnoIdValue(val, left);\n val = serializer.serialize(resolvedVal, left);\n }\n }\n\n let v: BinaryOperator;\n let rhs: unknown;\n\n switch (op) {\n case \"contains\":\n v = \"like\";\n rhs =\n val instanceof Column\n ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))}, '%')`\n : `%${val}%`;\n break;\n case \"not contains\":\n v = \"not like\";\n rhs =\n val instanceof Column\n ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))}, '%')`\n : `%${val}%`;\n break;\n case \"starts with\":\n v = \"like\";\n rhs =\n val instanceof Column\n ? sql`concat(${eb.ref(fullSQLName(val, resolver))}, '%')`\n : `${val}%`;\n break;\n case \"not starts with\":\n v = \"not like\";\n rhs =\n val instanceof Column\n ? sql`concat(${eb.ref(fullSQLName(val, resolver))}, '%')`\n : `${val}%`;\n break;\n case \"ends with\":\n v = \"like\";\n rhs =\n val instanceof Column\n ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))})`\n : `%${val}`;\n break;\n case \"not ends with\":\n v = \"not like\";\n rhs =\n val instanceof Column\n ? sql`concat('%', ${eb.ref(fullSQLName(val, resolver))})`\n : `%${val}`;\n break;\n default:\n v = op;\n rhs = val instanceof Column ? eb.ref(fullSQLName(val, resolver)) : val;\n }\n\n return eb(fullSQLName(left, resolver), v, rhs);\n }\n\n // Nested conditions\n if (condition.type === \"and\") {\n return eb.and(\n condition.items.map((v) =>\n buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table),\n ),\n );\n }\n\n if (condition.type === \"not\") {\n return eb.not(buildWhere(condition.item, eb, driverConfig, sqliteStorageMode, resolver, table));\n }\n\n return eb.or(\n condition.items.map((v) => buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table)),\n );\n}\n\n/**\n * Process reference subqueries in encoded values, converting them to Kysely SQL subqueries\n *\n * @param values - The encoded values that may contain ReferenceSubquery objects\n * @param kysely - The Kysely database instance for building subqueries\n * @param resolver - Optional naming resolver for namespace prefixing\n * @returns Processed values with subqueries in place of ReferenceSubquery markers\n * @internal\n */\nexport function processReferenceSubqueries(\n values: Record<string, unknown>,\n kysely: AnyKysely,\n resolver?: NamingResolver,\n): Record<string, unknown> {\n const processed: Record<string, unknown> = {};\n const getTableName = (table: AnyTable) =>\n resolver ? resolver.getTableName(table.name) : table.name;\n\n for (const [key, value] of Object.entries(values)) {\n if (value instanceof ReferenceSubquery) {\n const refTable = value.referencedTable;\n const externalId = value.externalIdValue;\n const tableName = getTableName(refTable);\n const internalIdCol = refTable.getInternalIdColumn().name;\n const idCol = refTable.getIdColumn().name;\n const internalIdColumnName = resolver\n ? resolver.getColumnName(refTable.name, internalIdCol)\n : internalIdCol;\n const idColumnName = resolver ? resolver.getColumnName(refTable.name, idCol) : idCol;\n\n processed[key] = kysely\n .selectFrom(tableName)\n .select(internalIdColumnName)\n .where(idColumnName, \"=\", externalId)\n .limit(1);\n } else {\n processed[key] = value;\n }\n }\n\n return processed;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"where-builder.js","names":["v: BinaryOperator","rhs: unknown","processed: Record<string, unknown>"],"sources":["../../../../src/adapters/generic-sql/query/where-builder.ts"],"sourcesContent":["import { sql, type BinaryOperator } from \"kysely\";\n\nimport type { NamingResolver } from \"../../../naming/sql-naming\";\nimport type { Condition } from \"../../../query/condition-builder\";\nimport { getDbNowOffsetMs, isDbNow } from \"../../../query/db-now\";\nimport { createSQLSerializer } from \"../../../query/serialize/create-sql-serializer\";\nimport { ReferenceSubquery, resolveFragnoIdValue } from \"../../../query/value-encoding\";\nimport {\n type AnyColumn,\n type AnyTable,\n Column,\n FragnoId,\n FragnoReference,\n} from \"../../../schema/create\";\nimport type { DriverConfig } from \"../driver-config\";\nimport type { SQLiteStorageMode } from \"../sqlite-storage\";\nimport { buildDbNowSql } from \"./db-now-sql\";\nimport type { AnyKysely, AnyExpressionBuilder, AnyExpressionWrapper } from \"./sql-query-compiler\";\n\n/**\n * Returns the fully qualified SQL name for a column (table.column).\n *\n * @param column - The column to get the full name for\n * @param resolver - Optional naming resolver for namespace prefixing\n * @returns The fully qualified SQL name in the format \"tableName.columnName\"\n * @internal\n */\nexport function fullSQLName(column: AnyColumn, resolver?: NamingResolver): string {\n const tableName = resolver ? resolver.getTableName(column.tableName) : column.tableName;\n const columnName = resolver ? resolver.getColumnName(column.tableName, column.name) : column.name;\n return `${tableName}.${columnName}`;\n}\n\nfunction fullSQLNameWithAlias(\n column: AnyColumn,\n resolver?: NamingResolver,\n table?: AnyTable,\n tableAlias?: string,\n): string {\n if (table && tableAlias && column.tableName === table.name) {\n const columnName = resolver\n ? resolver.getColumnName(column.tableName, column.name)\n : column.name;\n return `${tableAlias}.${columnName}`;\n }\n return fullSQLName(column, resolver);\n}\n\n/**\n * Builds a WHERE clause expression from a Condition tree.\n *\n * Recursively processes condition objects to build Kysely WHERE expressions.\n * Handles comparison operators, logical AND/OR/NOT, and special string operators\n * like \"contains\", \"starts with\", and \"ends with\".\n *\n * @param condition - The condition tree to build the WHERE clause from\n * @param eb - Kysely expression builder for constructing SQL expressions\n * @param database - The database type (affects SQL generation)\n * @param resolver - Optional naming resolver for namespace prefixing\n * @param table - The table being queried (used for resolving reference columns)\n * @returns A Kysely expression wrapper representing the WHERE clause\n * @internal\n */\nexport function buildWhere(\n condition: Condition,\n eb: AnyExpressionBuilder,\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n resolver?: NamingResolver,\n table?: AnyTable,\n tableAlias?: string,\n): AnyExpressionWrapper {\n const serializer = createSQLSerializer(driverConfig, sqliteStorageMode);\n\n if (condition.type === \"compare\") {\n const left = condition.a;\n const op = condition.operator;\n let val = condition.b;\n\n if (!(val instanceof Column)) {\n if (isDbNow(val)) {\n val = buildDbNowSql({\n driverConfig,\n columnType: left.type,\n offsetMs: getDbNowOffsetMs(val),\n sqliteStorageMode,\n });\n } else if (left.role === \"reference\" && table) {\n // Handle reference columns specially\n if (typeof val === \"string\") {\n // String external ID - create subquery to lookup internal ID\n const relation = Object.values(table.relations).find((rel) =>\n rel.on.some(([localCol]) => localCol === left.name),\n );\n if (relation) {\n const refTable = relation.table;\n const internalIdCol = refTable.getInternalIdColumn();\n const idCol = refTable.getIdColumn();\n const physicalTableName = resolver\n ? resolver.getTableName(refTable.name)\n : refTable.name;\n\n val = eb\n .selectFrom(physicalTableName)\n .select(\n resolver\n ? resolver.getColumnName(refTable.name, internalIdCol.name)\n : internalIdCol.name,\n )\n .where(\n resolver ? resolver.getColumnName(refTable.name, idCol.name) : idCol.name,\n \"=\",\n val,\n )\n .limit(1);\n }\n } else if (val instanceof FragnoId && val.internalId !== undefined) {\n // FragnoId with internal ID - use it directly (no serialization needed)\n val = val.internalId;\n } else if (val instanceof FragnoId && val.internalId === undefined) {\n // FragnoId without internal ID - create subquery using external ID\n const relation = Object.values(table.relations).find((rel) =>\n rel.on.some(([localCol]) => localCol === left.name),\n );\n if (relation) {\n const refTable = relation.table;\n const internalIdCol = refTable.getInternalIdColumn();\n const idCol = refTable.getIdColumn();\n const physicalTableName = resolver\n ? resolver.getTableName(refTable.name)\n : refTable.name;\n\n val = eb\n .selectFrom(physicalTableName)\n .select(\n resolver\n ? resolver.getColumnName(refTable.name, internalIdCol.name)\n : internalIdCol.name,\n )\n .where(\n resolver ? resolver.getColumnName(refTable.name, idCol.name) : idCol.name,\n \"=\",\n val.externalId,\n )\n .limit(1);\n }\n } else if (val instanceof FragnoReference) {\n // FragnoReference - use internal ID directly (no serialization needed)\n val = val.internalId;\n } else {\n // Other values - resolve and serialize\n const resolvedVal = resolveFragnoIdValue(val, left);\n val = serializer.serialize(resolvedVal, left);\n }\n } else {\n // Non-reference columns - resolve FragnoId/FragnoReference and serialize\n const resolvedVal = resolveFragnoIdValue(val, left);\n val = serializer.serialize(resolvedVal, left);\n }\n }\n\n let v: BinaryOperator;\n let rhs: unknown;\n\n switch (op) {\n case \"contains\":\n v = \"like\";\n rhs =\n val instanceof Column\n ? sql`concat('%', ${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))}, '%')`\n : `%${val}%`;\n break;\n case \"not contains\":\n v = \"not like\";\n rhs =\n val instanceof Column\n ? sql`concat('%', ${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))}, '%')`\n : `%${val}%`;\n break;\n case \"starts with\":\n v = \"like\";\n rhs =\n val instanceof Column\n ? sql`concat(${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))}, '%')`\n : `${val}%`;\n break;\n case \"not starts with\":\n v = \"not like\";\n rhs =\n val instanceof Column\n ? sql`concat(${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))}, '%')`\n : `${val}%`;\n break;\n case \"ends with\":\n v = \"like\";\n rhs =\n val instanceof Column\n ? sql`concat('%', ${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))})`\n : `%${val}`;\n break;\n case \"not ends with\":\n v = \"not like\";\n rhs =\n val instanceof Column\n ? sql`concat('%', ${eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))})`\n : `%${val}`;\n break;\n default:\n v = op;\n rhs =\n val instanceof Column\n ? eb.ref(fullSQLNameWithAlias(val, resolver, table, tableAlias))\n : val;\n }\n\n return eb(fullSQLNameWithAlias(left, resolver, table, tableAlias), v, rhs);\n }\n\n // Nested conditions\n if (condition.type === \"and\") {\n return eb.and(\n condition.items.map((v) =>\n buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table, tableAlias),\n ),\n );\n }\n\n if (condition.type === \"not\") {\n return eb.not(\n buildWhere(condition.item, eb, driverConfig, sqliteStorageMode, resolver, table, tableAlias),\n );\n }\n\n return eb.or(\n condition.items.map((v) =>\n buildWhere(v, eb, driverConfig, sqliteStorageMode, resolver, table, tableAlias),\n ),\n );\n}\n\n/**\n * Process reference subqueries in encoded values, converting them to Kysely SQL subqueries\n *\n * @param values - The encoded values that may contain ReferenceSubquery objects\n * @param kysely - The Kysely database instance for building subqueries\n * @param resolver - Optional naming resolver for namespace prefixing\n * @returns Processed values with subqueries in place of ReferenceSubquery markers\n * @internal\n */\nexport function processReferenceSubqueries(\n values: Record<string, unknown>,\n kysely: AnyKysely,\n resolver?: NamingResolver,\n): Record<string, unknown> {\n const processed: Record<string, unknown> = {};\n const getTableName = (table: AnyTable) =>\n resolver ? resolver.getTableName(table.name) : table.name;\n\n for (const [key, value] of Object.entries(values)) {\n if (value instanceof ReferenceSubquery) {\n const refTable = value.referencedTable;\n const externalId = value.externalIdValue;\n const tableName = getTableName(refTable);\n const internalIdCol = refTable.getInternalIdColumn().name;\n const idCol = refTable.getIdColumn().name;\n const internalIdColumnName = resolver\n ? resolver.getColumnName(refTable.name, internalIdCol)\n : internalIdCol;\n const idColumnName = resolver ? resolver.getColumnName(refTable.name, idCol) : idCol;\n\n processed[key] = kysely\n .selectFrom(tableName)\n .select(internalIdColumnName)\n .where(idColumnName, \"=\", externalId)\n .limit(1);\n } else {\n processed[key] = value;\n }\n }\n\n return processed;\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { decodeResult } from "../../query/value-decoding.js";
2
1
  import { createCursorFromRecord } from "../../query/cursor.js";
2
+ import { decodeResult } from "../../query/value-decoding.js";
3
3
 
4
4
  //#region src/adapters/generic-sql/uow-decoder.ts
5
5
  /**