@fragno-dev/db 0.1.15 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (407) hide show
  1. package/.turbo/turbo-build.log +242 -179
  2. package/CHANGELOG.md +23 -0
  3. package/README.md +123 -8
  4. package/dist/adapters/adapters.d.ts +5 -5
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts +6 -21
  8. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  9. package/dist/adapters/drizzle/drizzle-adapter.js +7 -54
  10. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  11. package/dist/adapters/drizzle/generate.d.ts +3 -0
  12. package/dist/adapters/drizzle/generate.d.ts.map +1 -1
  13. package/dist/adapters/drizzle/generate.js +36 -28
  14. package/dist/adapters/drizzle/generate.js.map +1 -1
  15. package/dist/adapters/generic-sql/driver-config.d.ts +74 -0
  16. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -0
  17. package/dist/adapters/generic-sql/driver-config.js +94 -0
  18. package/dist/adapters/generic-sql/driver-config.js.map +1 -0
  19. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +43 -0
  20. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -0
  21. package/dist/adapters/generic-sql/generic-sql-adapter.js +87 -0
  22. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -0
  23. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +67 -0
  24. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -0
  25. package/dist/adapters/generic-sql/migration/cold-kysely.js +33 -0
  26. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -0
  27. package/dist/adapters/generic-sql/migration/dialect/mysql.js +60 -0
  28. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -0
  29. package/dist/adapters/generic-sql/migration/dialect/postgres.js +59 -0
  30. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -0
  31. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +96 -0
  32. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -0
  33. package/dist/adapters/generic-sql/migration/executor.d.ts +15 -0
  34. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  35. package/dist/adapters/generic-sql/migration/executor.js +18 -0
  36. package/dist/adapters/generic-sql/migration/executor.js.map +1 -0
  37. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  38. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  39. package/dist/adapters/generic-sql/migration/prepared-migrations.js +68 -0
  40. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -0
  41. package/dist/adapters/generic-sql/migration/sql-generator.js +212 -0
  42. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -0
  43. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +32 -0
  44. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -0
  45. package/dist/adapters/generic-sql/query/cursor-utils.js +37 -0
  46. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -0
  47. package/dist/adapters/generic-sql/query/dialect/mysql.js +33 -0
  48. package/dist/adapters/generic-sql/query/dialect/mysql.js.map +1 -0
  49. package/dist/adapters/generic-sql/query/dialect/postgres.js +32 -0
  50. package/dist/adapters/generic-sql/query/dialect/postgres.js.map +1 -0
  51. package/dist/adapters/generic-sql/query/dialect/sqlite.js +32 -0
  52. package/dist/adapters/generic-sql/query/dialect/sqlite.js.map +1 -0
  53. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +152 -0
  54. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -0
  55. package/dist/adapters/generic-sql/query/select-builder.js +69 -0
  56. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -0
  57. package/dist/adapters/generic-sql/query/sql-query-compiler.js +145 -0
  58. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -0
  59. package/dist/adapters/generic-sql/query/where-builder.js +129 -0
  60. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -0
  61. package/dist/adapters/generic-sql/result-interpreter.js +74 -0
  62. package/dist/adapters/generic-sql/result-interpreter.js.map +1 -0
  63. package/dist/adapters/generic-sql/uow-decoder.js +105 -0
  64. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -0
  65. package/dist/adapters/generic-sql/uow-encoder.js +93 -0
  66. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -0
  67. package/dist/adapters/kysely/kysely-adapter.d.ts +5 -18
  68. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  69. package/dist/adapters/kysely/kysely-adapter.js +6 -165
  70. package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
  71. package/dist/adapters/{drizzle/drizzle-query.js → shared/from-unit-of-work-compiler.js} +47 -61
  72. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -0
  73. package/dist/adapters/{drizzle/shared.d.ts → shared/table-name-mapper.d.ts} +2 -4
  74. package/dist/adapters/shared/table-name-mapper.d.ts.map +1 -0
  75. package/dist/adapters/shared/table-name-mapper.js +43 -0
  76. package/dist/adapters/shared/table-name-mapper.js.map +1 -0
  77. package/dist/adapters/shared/uow-operation-compiler.js +105 -0
  78. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -0
  79. package/dist/db-fragment-definition-builder.d.ts +53 -19
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  81. package/dist/db-fragment-definition-builder.js +89 -19
  82. package/dist/db-fragment-definition-builder.js.map +1 -1
  83. package/dist/fragments/internal-fragment.d.ts +39 -5
  84. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  85. package/dist/fragments/internal-fragment.js +82 -10
  86. package/dist/fragments/internal-fragment.js.map +1 -1
  87. package/dist/hooks/hooks.d.ts +51 -0
  88. package/dist/hooks/hooks.d.ts.map +1 -0
  89. package/dist/hooks/hooks.js +88 -0
  90. package/dist/hooks/hooks.js.map +1 -0
  91. package/dist/migration-engine/generation-engine.d.ts +0 -2
  92. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  93. package/dist/migration-engine/generation-engine.js +23 -61
  94. package/dist/migration-engine/generation-engine.js.map +1 -1
  95. package/dist/mod.d.ts +34 -10
  96. package/dist/mod.d.ts.map +1 -1
  97. package/dist/mod.js +47 -16
  98. package/dist/mod.js.map +1 -1
  99. package/dist/node_modules/.pnpm/{rou3@0.7.8 → rou3@0.7.10}/node_modules/rou3/dist/index.js +1 -1
  100. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +1 -0
  101. package/dist/packages/fragno/dist/api/fragment-instantiator.js +69 -31
  102. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -1
  103. package/dist/query/column-defaults.js +27 -0
  104. package/dist/query/column-defaults.js.map +1 -0
  105. package/dist/query/cursor.d.ts +4 -4
  106. package/dist/query/cursor.d.ts.map +1 -1
  107. package/dist/query/cursor.js +8 -6
  108. package/dist/query/cursor.js.map +1 -1
  109. package/dist/query/orm/orm.d.ts +1 -1
  110. package/dist/query/orm/orm.js.map +1 -1
  111. package/dist/query/serialize/create-sql-serializer.js +30 -0
  112. package/dist/query/serialize/create-sql-serializer.js.map +1 -0
  113. package/dist/query/serialize/dialect/mysql-serializer.js +87 -0
  114. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -0
  115. package/dist/query/serialize/dialect/postgres-serializer.js +80 -0
  116. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -0
  117. package/dist/query/serialize/dialect/sqlite-serializer.js +93 -0
  118. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -0
  119. package/dist/query/serialize/sql-serializer.js +67 -0
  120. package/dist/query/serialize/sql-serializer.js.map +1 -0
  121. package/dist/query/{query.d.ts → simple-query-interface.d.ts} +5 -5
  122. package/dist/query/simple-query-interface.d.ts.map +1 -0
  123. package/dist/query/{execute-unit-of-work.d.ts → unit-of-work/execute-unit-of-work.d.ts} +13 -3
  124. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  125. package/dist/query/{execute-unit-of-work.js → unit-of-work/execute-unit-of-work.js} +17 -4
  126. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  127. package/dist/query/{retry-policy.d.ts → unit-of-work/retry-policy.d.ts} +1 -1
  128. package/dist/query/unit-of-work/retry-policy.d.ts.map +1 -0
  129. package/dist/query/{retry-policy.js → unit-of-work/retry-policy.js} +1 -1
  130. package/dist/query/unit-of-work/retry-policy.js.map +1 -0
  131. package/dist/query/{unit-of-work.d.ts → unit-of-work/unit-of-work.d.ts} +51 -18
  132. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  133. package/dist/query/{unit-of-work.js → unit-of-work/unit-of-work.js} +58 -11
  134. package/dist/query/unit-of-work/unit-of-work.js.map +1 -0
  135. package/dist/query/value-decoding.js +71 -0
  136. package/dist/query/value-decoding.js.map +1 -0
  137. package/dist/query/value-encoding.js +124 -0
  138. package/dist/query/value-encoding.js.map +1 -0
  139. package/dist/schema/create.d.ts +3 -0
  140. package/dist/schema/create.d.ts.map +1 -1
  141. package/dist/schema/create.js +4 -0
  142. package/dist/schema/create.js.map +1 -1
  143. package/dist/schema/type-conversion/create-sql-type-mapper.js +29 -0
  144. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -0
  145. package/dist/schema/type-conversion/dialect/mysql.js +57 -0
  146. package/dist/schema/type-conversion/dialect/mysql.js.map +1 -0
  147. package/dist/schema/type-conversion/dialect/postgres.js +56 -0
  148. package/dist/schema/type-conversion/dialect/postgres.js.map +1 -0
  149. package/dist/schema/type-conversion/dialect/sqlite.js +52 -0
  150. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -0
  151. package/dist/schema/type-conversion/type-mapping.js +63 -0
  152. package/dist/schema/type-conversion/type-mapping.js.map +1 -0
  153. package/dist/sql-driver/connection/connection-provider.d.ts +13 -0
  154. package/dist/sql-driver/connection/connection-provider.d.ts.map +1 -0
  155. package/dist/sql-driver/connection/connection-provider.js +19 -0
  156. package/dist/sql-driver/connection/connection-provider.js.map +1 -0
  157. package/dist/sql-driver/connection/single-connection-provider.js +23 -0
  158. package/dist/sql-driver/connection/single-connection-provider.js.map +1 -0
  159. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  160. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  161. package/dist/sql-driver/dialects/dialects.d.ts +2 -0
  162. package/dist/sql-driver/dialects/dialects.js +3 -0
  163. package/dist/sql-driver/dialects/durable-object-dialect.d.ts +72 -0
  164. package/dist/sql-driver/dialects/durable-object-dialect.d.ts.map +1 -0
  165. package/dist/sql-driver/dialects/durable-object-dialect.js +130 -0
  166. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -0
  167. package/dist/sql-driver/driver/runtime-driver.d.ts +23 -0
  168. package/dist/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  169. package/dist/sql-driver/driver/runtime-driver.js +56 -0
  170. package/dist/sql-driver/driver/runtime-driver.js.map +1 -0
  171. package/dist/sql-driver/query-executor/default-query-executor.js +26 -0
  172. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -0
  173. package/dist/sql-driver/query-executor/plugin.d.ts +17 -0
  174. package/dist/sql-driver/query-executor/plugin.d.ts.map +1 -0
  175. package/dist/sql-driver/query-executor/query-executor-base.js +25 -0
  176. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -0
  177. package/dist/sql-driver/query-executor/query-executor.d.ts +36 -0
  178. package/dist/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  179. package/dist/sql-driver/sql-driver-adapter.d.ts +29 -0
  180. package/dist/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  181. package/dist/sql-driver/sql-driver-adapter.js +68 -0
  182. package/dist/sql-driver/sql-driver-adapter.js.map +1 -0
  183. package/dist/sql-driver/sql-driver.d.ts +38 -0
  184. package/dist/sql-driver/sql-driver.d.ts.map +1 -0
  185. package/dist/sql-driver/sql-driver.js +1 -0
  186. package/dist/sql-driver/sql.js +50 -0
  187. package/dist/sql-driver/sql.js.map +1 -0
  188. package/dist/with-database.d.ts +6 -2
  189. package/dist/with-database.d.ts.map +1 -1
  190. package/dist/with-database.js +1 -1
  191. package/dist/with-database.js.map +1 -1
  192. package/package.json +37 -10
  193. package/src/adapters/adapters.ts +8 -5
  194. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +60 -169
  195. package/src/adapters/drizzle/{drizzle-adapter-sqlite.test.ts → drizzle-adapter-sqlite3.test.ts} +31 -55
  196. package/src/adapters/drizzle/drizzle-adapter.ts +15 -107
  197. package/src/adapters/drizzle/generate.test.ts +2 -2
  198. package/src/adapters/drizzle/generate.ts +78 -34
  199. package/src/adapters/drizzle/migrate-drizzle.test.ts +19 -0
  200. package/src/adapters/drizzle/shared.ts +0 -34
  201. package/src/adapters/drizzle/test-utils.ts +3 -3
  202. package/src/adapters/generic-sql/README.md +14 -0
  203. package/src/adapters/generic-sql/driver-config.ts +144 -0
  204. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +50 -0
  205. package/src/adapters/generic-sql/generic-sql-adapter.ts +146 -0
  206. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +130 -0
  207. package/src/adapters/generic-sql/migration/cold-kysely.ts +55 -0
  208. package/src/adapters/{kysely/migration/execute-mysql.test.ts → generic-sql/migration/dialect/mysql.test.ts} +342 -484
  209. package/src/adapters/generic-sql/migration/dialect/mysql.ts +104 -0
  210. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +1008 -0
  211. package/src/adapters/generic-sql/migration/dialect/postgres.ts +113 -0
  212. package/src/adapters/{kysely/migration/execute-sqlite.test.ts → generic-sql/migration/dialect/sqlite.test.ts} +307 -510
  213. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +189 -0
  214. package/src/adapters/generic-sql/migration/executor.ts +33 -0
  215. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +661 -0
  216. package/src/adapters/generic-sql/migration/prepared-migrations.ts +214 -0
  217. package/src/adapters/generic-sql/migration/sql-generator.ts +413 -0
  218. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +36 -0
  219. package/src/adapters/generic-sql/query/cursor-utils.ts +56 -0
  220. package/src/adapters/generic-sql/query/dialect/mysql.ts +34 -0
  221. package/src/adapters/generic-sql/query/dialect/postgres.ts +32 -0
  222. package/src/adapters/generic-sql/query/dialect/sqlite.ts +32 -0
  223. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +1568 -0
  224. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +314 -0
  225. package/src/adapters/generic-sql/query/select-builder.test.ts +256 -0
  226. package/src/adapters/generic-sql/query/select-builder.ts +137 -0
  227. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +195 -0
  228. package/src/adapters/generic-sql/query/sql-query-compiler.ts +367 -0
  229. package/src/adapters/generic-sql/query/where-builder.test.ts +744 -0
  230. package/src/adapters/generic-sql/query/where-builder.ts +211 -0
  231. package/src/adapters/generic-sql/result-interpreter.ts +102 -0
  232. package/src/adapters/generic-sql/test/generic-drizzle-adapter-sqlite3.test.ts +899 -0
  233. package/src/adapters/generic-sql/uow-decoder.test.ts +399 -0
  234. package/src/adapters/generic-sql/uow-decoder.ts +152 -0
  235. package/src/adapters/generic-sql/uow-encoder.test.ts +183 -0
  236. package/src/adapters/generic-sql/uow-encoder.ts +131 -0
  237. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +26 -76
  238. package/src/adapters/kysely/{kysely-adapter-sqlite.test.ts → kysely-adapter-sqlocal.test.ts} +76 -17
  239. package/src/adapters/kysely/kysely-adapter.ts +10 -250
  240. package/src/adapters/{drizzle/drizzle-query.ts → shared/from-unit-of-work-compiler.ts} +110 -104
  241. package/src/adapters/shared/table-name-mapper.ts +50 -0
  242. package/src/adapters/shared/uow-operation-compiler.ts +211 -0
  243. package/src/db-fragment-definition-builder.test.ts +2 -2
  244. package/src/db-fragment-definition-builder.ts +281 -50
  245. package/src/db-fragment-instantiator.test.ts +78 -2
  246. package/src/db-fragment-integration.test.ts +14 -16
  247. package/src/fragments/internal-fragment.test.ts +434 -45
  248. package/src/fragments/internal-fragment.ts +184 -20
  249. package/src/hooks/hooks.test.ts +575 -0
  250. package/src/hooks/hooks.ts +179 -0
  251. package/src/migration-engine/generation-engine.test.ts +44 -54
  252. package/src/migration-engine/generation-engine.ts +48 -94
  253. package/src/mod.ts +117 -29
  254. package/src/query/column-defaults.ts +49 -0
  255. package/src/query/cursor.test.ts +31 -6
  256. package/src/query/cursor.ts +11 -7
  257. package/src/query/orm/orm.ts +1 -1
  258. package/src/query/query-type.test.ts +9 -9
  259. package/src/query/serialize/create-sql-serializer.ts +34 -0
  260. package/src/query/serialize/dialect/mysql-serializer.ts +142 -0
  261. package/src/query/serialize/dialect/postgres-serializer.ts +129 -0
  262. package/src/query/serialize/dialect/sqlite-serializer.test.ts +251 -0
  263. package/src/query/serialize/dialect/sqlite-serializer.ts +156 -0
  264. package/src/query/serialize/sql-serializer.ts +143 -0
  265. package/src/query/{query.ts → simple-query-interface.ts} +2 -2
  266. package/src/query/{execute-unit-of-work.test.ts → unit-of-work/execute-unit-of-work.test.ts} +16 -16
  267. package/src/query/{execute-unit-of-work.ts → unit-of-work/execute-unit-of-work.ts} +49 -8
  268. package/src/query/{unit-of-work-coordinator.test.ts → unit-of-work/unit-of-work-coordinator.test.ts} +41 -43
  269. package/src/query/{unit-of-work-types.test.ts → unit-of-work/unit-of-work-types.test.ts} +5 -3
  270. package/src/query/{unit-of-work.test.ts → unit-of-work/unit-of-work.test.ts} +100 -9
  271. package/src/query/{unit-of-work.ts → unit-of-work/unit-of-work.ts} +135 -32
  272. package/src/query/{result-transform.test.ts → value-decoding.test.ts} +45 -427
  273. package/src/query/value-decoding.ts +113 -0
  274. package/src/query/value-encoding.test.ts +390 -0
  275. package/src/query/value-encoding.ts +168 -0
  276. package/src/schema/create.test.ts +5 -1
  277. package/src/schema/create.ts +5 -0
  278. package/src/schema/serialize.test.ts +165 -407
  279. package/src/schema/type-conversion/create-sql-type-mapper.ts +28 -0
  280. package/src/schema/type-conversion/dialect/mysql.ts +64 -0
  281. package/src/schema/type-conversion/dialect/postgres.ts +62 -0
  282. package/src/schema/type-conversion/dialect/sqlite.ts +63 -0
  283. package/src/schema/type-conversion/type-mapping.test.ts +137 -0
  284. package/src/schema/type-conversion/type-mapping.ts +153 -0
  285. package/src/shared/connection-pool.ts +5 -5
  286. package/src/sql-driver/better-sqlite3.test.ts +126 -0
  287. package/src/sql-driver/connection/connection-provider.ts +27 -0
  288. package/src/sql-driver/connection/single-connection-provider.ts +42 -0
  289. package/src/sql-driver/dialect-adapter/dialect-adapter.ts +9 -0
  290. package/src/sql-driver/dialect-adapter/sqlite-dialect-adapter.ts +7 -0
  291. package/src/sql-driver/dialects/dialects.ts +1 -0
  292. package/src/sql-driver/dialects/durable-object-dialect.ts +260 -0
  293. package/src/sql-driver/driver/runtime-driver.ts +91 -0
  294. package/src/sql-driver/query-executor/default-query-executor.ts +38 -0
  295. package/src/sql-driver/query-executor/plugin.ts +22 -0
  296. package/src/sql-driver/query-executor/query-executor-base.ts +53 -0
  297. package/src/sql-driver/query-executor/query-executor.ts +44 -0
  298. package/src/sql-driver/sql-driver-adapter.ts +96 -0
  299. package/src/sql-driver/sql-driver.ts +53 -0
  300. package/src/sql-driver/sql.ts +57 -0
  301. package/src/sql-driver/sqlocal.test.ts +117 -0
  302. package/src/with-database.ts +35 -23
  303. package/tsdown.config.ts +7 -2
  304. package/dist/adapters/drizzle/drizzle-connection-pool.js +0 -40
  305. package/dist/adapters/drizzle/drizzle-connection-pool.js.map +0 -1
  306. package/dist/adapters/drizzle/drizzle-query.d.ts +0 -23
  307. package/dist/adapters/drizzle/drizzle-query.d.ts.map +0 -1
  308. package/dist/adapters/drizzle/drizzle-query.js.map +0 -1
  309. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -10
  310. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +0 -1
  311. package/dist/adapters/drizzle/drizzle-uow-compiler.js +0 -334
  312. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +0 -1
  313. package/dist/adapters/drizzle/drizzle-uow-decoder.js +0 -123
  314. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +0 -1
  315. package/dist/adapters/drizzle/drizzle-uow-executor.js +0 -160
  316. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +0 -1
  317. package/dist/adapters/drizzle/join-column-utils.js +0 -28
  318. package/dist/adapters/drizzle/join-column-utils.js.map +0 -1
  319. package/dist/adapters/drizzle/shared.d.ts.map +0 -1
  320. package/dist/adapters/drizzle/shared.js +0 -35
  321. package/dist/adapters/drizzle/shared.js.map +0 -1
  322. package/dist/adapters/kysely/kysely-connection-pool.js +0 -41
  323. package/dist/adapters/kysely/kysely-connection-pool.js.map +0 -1
  324. package/dist/adapters/kysely/kysely-query-builder.js +0 -321
  325. package/dist/adapters/kysely/kysely-query-builder.js.map +0 -1
  326. package/dist/adapters/kysely/kysely-query-compiler.js +0 -67
  327. package/dist/adapters/kysely/kysely-query-compiler.js.map +0 -1
  328. package/dist/adapters/kysely/kysely-query.d.ts +0 -23
  329. package/dist/adapters/kysely/kysely-query.d.ts.map +0 -1
  330. package/dist/adapters/kysely/kysely-query.js +0 -230
  331. package/dist/adapters/kysely/kysely-query.js.map +0 -1
  332. package/dist/adapters/kysely/kysely-shared.d.ts +0 -14
  333. package/dist/adapters/kysely/kysely-shared.d.ts.map +0 -1
  334. package/dist/adapters/kysely/kysely-shared.js +0 -33
  335. package/dist/adapters/kysely/kysely-shared.js.map +0 -1
  336. package/dist/adapters/kysely/kysely-uow-compiler.js +0 -193
  337. package/dist/adapters/kysely/kysely-uow-compiler.js.map +0 -1
  338. package/dist/adapters/kysely/kysely-uow-executor.js +0 -93
  339. package/dist/adapters/kysely/kysely-uow-executor.js.map +0 -1
  340. package/dist/adapters/kysely/migration/execute-base.js +0 -128
  341. package/dist/adapters/kysely/migration/execute-base.js.map +0 -1
  342. package/dist/adapters/kysely/migration/execute-factory.js +0 -34
  343. package/dist/adapters/kysely/migration/execute-factory.js.map +0 -1
  344. package/dist/adapters/kysely/migration/execute-mssql.js +0 -112
  345. package/dist/adapters/kysely/migration/execute-mssql.js.map +0 -1
  346. package/dist/adapters/kysely/migration/execute-mysql.js +0 -93
  347. package/dist/adapters/kysely/migration/execute-mysql.js.map +0 -1
  348. package/dist/adapters/kysely/migration/execute-postgres.js +0 -104
  349. package/dist/adapters/kysely/migration/execute-postgres.js.map +0 -1
  350. package/dist/adapters/kysely/migration/execute-sqlite.js +0 -123
  351. package/dist/adapters/kysely/migration/execute-sqlite.js.map +0 -1
  352. package/dist/adapters/kysely/migration/execute.js +0 -34
  353. package/dist/adapters/kysely/migration/execute.js.map +0 -1
  354. package/dist/migration-engine/create.d.ts +0 -37
  355. package/dist/migration-engine/create.d.ts.map +0 -1
  356. package/dist/migration-engine/create.js +0 -58
  357. package/dist/migration-engine/create.js.map +0 -1
  358. package/dist/migration-engine/shared.d.ts +0 -112
  359. package/dist/migration-engine/shared.d.ts.map +0 -1
  360. package/dist/node_modules/.pnpm/rou3@0.7.8/node_modules/rou3/dist/index.js.map +0 -1
  361. package/dist/query/execute-unit-of-work.d.ts.map +0 -1
  362. package/dist/query/execute-unit-of-work.js.map +0 -1
  363. package/dist/query/query.d.ts.map +0 -1
  364. package/dist/query/result-transform.js +0 -170
  365. package/dist/query/result-transform.js.map +0 -1
  366. package/dist/query/retry-policy.d.ts.map +0 -1
  367. package/dist/query/retry-policy.js.map +0 -1
  368. package/dist/query/unit-of-work.d.ts.map +0 -1
  369. package/dist/query/unit-of-work.js.map +0 -1
  370. package/dist/schema/serialize.js +0 -111
  371. package/dist/schema/serialize.js.map +0 -1
  372. package/src/adapters/drizzle/drizzle-adapter.test.ts +0 -122
  373. package/src/adapters/drizzle/drizzle-connection-pool.ts +0 -66
  374. package/src/adapters/drizzle/drizzle-query.test.ts +0 -499
  375. package/src/adapters/drizzle/drizzle-uow-compiler-mysql.test.ts +0 -1442
  376. package/src/adapters/drizzle/drizzle-uow-compiler-sqlite.test.ts +0 -1414
  377. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +0 -1400
  378. package/src/adapters/drizzle/drizzle-uow-compiler.ts +0 -677
  379. package/src/adapters/drizzle/drizzle-uow-decoder.ts +0 -228
  380. package/src/adapters/drizzle/drizzle-uow-executor.ts +0 -309
  381. package/src/adapters/drizzle/join-column-utils.test.ts +0 -79
  382. package/src/adapters/drizzle/join-column-utils.ts +0 -39
  383. package/src/adapters/kysely/kysely-connection-pool.ts +0 -70
  384. package/src/adapters/kysely/kysely-query-builder.test.ts +0 -1344
  385. package/src/adapters/kysely/kysely-query-builder.ts +0 -666
  386. package/src/adapters/kysely/kysely-query-compiler.ts +0 -127
  387. package/src/adapters/kysely/kysely-query.test.ts +0 -498
  388. package/src/adapters/kysely/kysely-query.ts +0 -399
  389. package/src/adapters/kysely/kysely-shared.ts +0 -57
  390. package/src/adapters/kysely/kysely-uow-compiler.test.ts +0 -986
  391. package/src/adapters/kysely/kysely-uow-compiler.ts +0 -350
  392. package/src/adapters/kysely/kysely-uow-executor.ts +0 -164
  393. package/src/adapters/kysely/kysely-uow-joins.test.ts +0 -794
  394. package/src/adapters/kysely/migration/execute-base.ts +0 -256
  395. package/src/adapters/kysely/migration/execute-factory.ts +0 -53
  396. package/src/adapters/kysely/migration/execute-mssql.ts +0 -250
  397. package/src/adapters/kysely/migration/execute-mysql.ts +0 -211
  398. package/src/adapters/kysely/migration/execute-postgres.test.ts +0 -2657
  399. package/src/adapters/kysely/migration/execute-postgres.ts +0 -234
  400. package/src/adapters/kysely/migration/execute-sqlite.ts +0 -247
  401. package/src/adapters/kysely/migration/execute.ts +0 -50
  402. package/src/adapters/kysely/migration/kysely-migrator.test.ts +0 -261
  403. package/src/query/result-transform.ts +0 -274
  404. package/src/schema/serialize.ts +0 -407
  405. /package/dist/query/{query.js → simple-query-interface.js} +0 -0
  406. /package/src/query/{retry-policy.test.ts → unit-of-work/retry-policy.test.ts} +0 -0
  407. /package/src/query/{retry-policy.ts → unit-of-work/retry-policy.ts} +0 -0
@@ -0,0 +1,399 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { schema, idColumn, column, FragnoId } from "../../schema/create";
3
+ import { UnitOfWorkDecoder } from "./uow-decoder";
4
+ import { SQLocalDriverConfig } from "./driver-config";
5
+ import type { RetrievalOperation } from "../../query/unit-of-work/unit-of-work";
6
+ import type { AnySchema } from "../../schema/create";
7
+
8
+ describe("UnitOfWorkDecoder", () => {
9
+ const driverConfig = new SQLocalDriverConfig();
10
+
11
+ const testSchema = schema((s) => {
12
+ return s
13
+ .addTable("users", (t) => {
14
+ return t
15
+ .addColumn("id", idColumn())
16
+ .addColumn("name", column("string"))
17
+ .addColumn("email", column("string"))
18
+ .addColumn("age", column("integer").nullable())
19
+ .createIndex("idx_email", ["email"], { unique: true });
20
+ })
21
+ .addTable("posts", (t) => {
22
+ return t
23
+ .addColumn("id", idColumn())
24
+ .addColumn("title", column("string"))
25
+ .addColumn("content", column("string"))
26
+ .createIndex("idx_title", ["title"]);
27
+ });
28
+ });
29
+
30
+ const decoder = new UnitOfWorkDecoder(driverConfig);
31
+
32
+ describe("decode", () => {
33
+ it("should decode regular find operations", () => {
34
+ const operation: RetrievalOperation<AnySchema> = {
35
+ type: "find",
36
+ schema: testSchema,
37
+ table: testSchema.tables.users,
38
+ indexName: "_primary",
39
+ options: {
40
+ useIndex: "_primary",
41
+ },
42
+ };
43
+
44
+ const rawResults = [
45
+ [
46
+ { id: "user1", name: "Alice", email: "alice@example.com", age: 30 },
47
+ { id: "user2", name: "Bob", email: "bob@example.com", age: null },
48
+ ],
49
+ ];
50
+
51
+ const results = decoder.decode(rawResults, [operation]);
52
+
53
+ expect(results).toHaveLength(1);
54
+ expect(results[0]).toEqual([
55
+ { id: "user1", name: "Alice", email: "alice@example.com", age: 30 },
56
+ { id: "user2", name: "Bob", email: "bob@example.com", age: null },
57
+ ]);
58
+ });
59
+
60
+ it("should decode count operations", () => {
61
+ const operation: RetrievalOperation<AnySchema> = {
62
+ type: "count",
63
+ schema: testSchema,
64
+ table: testSchema.tables.users,
65
+ indexName: "_primary",
66
+ options: {
67
+ useIndex: "_primary",
68
+ },
69
+ };
70
+
71
+ const rawResults = [[{ count: 42 }]];
72
+
73
+ const results = decoder.decode(rawResults, [operation]);
74
+
75
+ expect(results).toHaveLength(1);
76
+ expect(results[0]).toBe(42);
77
+ });
78
+
79
+ it("should decode cursor-paginated operations", () => {
80
+ const operation: RetrievalOperation<AnySchema> = {
81
+ type: "find",
82
+ schema: testSchema,
83
+ table: testSchema.tables.users,
84
+ indexName: "_primary",
85
+ options: {
86
+ useIndex: "_primary",
87
+ pageSize: 2,
88
+ orderByIndex: {
89
+ indexName: "_primary",
90
+ direction: "asc",
91
+ },
92
+ },
93
+ withCursor: true,
94
+ };
95
+
96
+ // Fetch pageSize + 1 to detect hasNextPage
97
+ const rawResults = [
98
+ [
99
+ { id: "user1", name: "Alice", email: "alice@example.com", age: 30 },
100
+ { id: "user2", name: "Bob", email: "bob@example.com", age: 25 },
101
+ { id: "user3", name: "Charlie", email: "charlie@example.com", age: 35 },
102
+ ],
103
+ ];
104
+
105
+ const results = decoder.decode(rawResults, [operation]);
106
+
107
+ expect(results).toHaveLength(1);
108
+ const cursorResult = results[0] as {
109
+ items: unknown[];
110
+ cursor?: unknown;
111
+ hasNextPage: boolean;
112
+ };
113
+
114
+ expect(cursorResult.items).toHaveLength(2);
115
+ expect(cursorResult.items).toEqual([
116
+ { id: "user1", name: "Alice", email: "alice@example.com", age: 30 },
117
+ { id: "user2", name: "Bob", email: "bob@example.com", age: 25 },
118
+ ]);
119
+ expect(cursorResult.hasNextPage).toBe(true);
120
+ expect(cursorResult.cursor).toBeDefined();
121
+ });
122
+
123
+ it("should decode cursor-paginated operations without hasNextPage when exactly pageSize rows", () => {
124
+ const operation: RetrievalOperation<AnySchema> = {
125
+ type: "find",
126
+ schema: testSchema,
127
+ table: testSchema.tables.users,
128
+ indexName: "_primary",
129
+ options: {
130
+ useIndex: "_primary",
131
+ pageSize: 2,
132
+ orderByIndex: {
133
+ indexName: "_primary",
134
+ direction: "asc",
135
+ },
136
+ },
137
+ withCursor: true,
138
+ };
139
+
140
+ const rawResults = [
141
+ [
142
+ { id: "user1", name: "Alice", email: "alice@example.com", age: 30 },
143
+ { id: "user2", name: "Bob", email: "bob@example.com", age: 25 },
144
+ ],
145
+ ];
146
+
147
+ const results = decoder.decode(rawResults, [operation]);
148
+
149
+ expect(results).toHaveLength(1);
150
+ const cursorResult = results[0] as {
151
+ items: unknown[];
152
+ cursor?: unknown;
153
+ hasNextPage: boolean;
154
+ };
155
+
156
+ expect(cursorResult.items).toHaveLength(2);
157
+ expect(cursorResult.hasNextPage).toBe(false);
158
+ expect(cursorResult.cursor).toBeUndefined();
159
+ });
160
+
161
+ it("should decode multiple operations", () => {
162
+ const findOperation: RetrievalOperation<AnySchema> = {
163
+ type: "find",
164
+ schema: testSchema,
165
+ table: testSchema.tables.users,
166
+ indexName: "_primary",
167
+ options: {
168
+ useIndex: "_primary",
169
+ },
170
+ };
171
+
172
+ const countOperation: RetrievalOperation<AnySchema> = {
173
+ type: "count",
174
+ schema: testSchema,
175
+ table: testSchema.tables.posts,
176
+ indexName: "_primary",
177
+ options: {
178
+ useIndex: "_primary",
179
+ },
180
+ };
181
+
182
+ const rawResults = [
183
+ [{ id: "user1", name: "Alice", email: "alice@example.com", age: 30 }],
184
+ [{ count: 5 }],
185
+ ];
186
+
187
+ const results = decoder.decode(rawResults, [findOperation, countOperation]);
188
+
189
+ expect(results).toHaveLength(2);
190
+ expect(results[0]).toEqual([
191
+ { id: "user1", name: "Alice", email: "alice@example.com", age: 30 },
192
+ ]);
193
+ expect(results[1]).toBe(5);
194
+ });
195
+
196
+ it("should throw error when rawResults and operations lengths don't match", () => {
197
+ const operation: RetrievalOperation<AnySchema> = {
198
+ type: "find",
199
+ schema: testSchema,
200
+ table: testSchema.tables.users,
201
+ indexName: "_primary",
202
+ options: {
203
+ useIndex: "_primary",
204
+ },
205
+ };
206
+
207
+ const rawResults = [[{ id: "user1", name: "Alice" }], [{ id: "user2", name: "Bob" }]];
208
+
209
+ expect(() => decoder.decode(rawResults, [operation])).toThrow(
210
+ "rawResults and ops must have the same length",
211
+ );
212
+ });
213
+
214
+ it("should handle empty results for regular find", () => {
215
+ const operation: RetrievalOperation<AnySchema> = {
216
+ type: "find",
217
+ schema: testSchema,
218
+ table: testSchema.tables.users,
219
+ indexName: "_primary",
220
+ options: {
221
+ useIndex: "_primary",
222
+ },
223
+ };
224
+
225
+ const rawResults = [[]];
226
+
227
+ const results = decoder.decode(rawResults, [operation]);
228
+
229
+ expect(results).toHaveLength(1);
230
+ expect(results[0]).toEqual([]);
231
+ });
232
+
233
+ it("should handle count result with no rows", () => {
234
+ const operation: RetrievalOperation<AnySchema> = {
235
+ type: "count",
236
+ schema: testSchema,
237
+ table: testSchema.tables.users,
238
+ indexName: "_primary",
239
+ options: {
240
+ useIndex: "_primary",
241
+ },
242
+ };
243
+
244
+ const rawResults = [[]];
245
+
246
+ const results = decoder.decode(rawResults, [operation]);
247
+
248
+ expect(results).toHaveLength(1);
249
+ expect(results[0]).toBe(0);
250
+ });
251
+
252
+ it("should generate cursor for custom index", () => {
253
+ const operation: RetrievalOperation<AnySchema> = {
254
+ type: "find",
255
+ schema: testSchema,
256
+ table: testSchema.tables.users,
257
+ indexName: "idx_email",
258
+ options: {
259
+ useIndex: "idx_email",
260
+ pageSize: 1,
261
+ orderByIndex: {
262
+ indexName: "idx_email",
263
+ direction: "asc",
264
+ },
265
+ },
266
+ withCursor: true,
267
+ };
268
+
269
+ const rawResults = [
270
+ [
271
+ { id: "user1", name: "Alice", email: "alice@example.com", age: 30 },
272
+ { id: "user2", name: "Bob", email: "bob@example.com", age: 25 },
273
+ ],
274
+ ];
275
+
276
+ const results = decoder.decode(rawResults, [operation]);
277
+
278
+ expect(results).toHaveLength(1);
279
+ const cursorResult = results[0] as {
280
+ items: unknown[];
281
+ cursor?: unknown;
282
+ hasNextPage: boolean;
283
+ };
284
+
285
+ expect(cursorResult.items).toHaveLength(1);
286
+ expect(cursorResult.hasNextPage).toBe(true);
287
+ expect(cursorResult.cursor).toBeDefined();
288
+ });
289
+
290
+ it("should handle cursor pagination without orderByIndex", () => {
291
+ const operation: RetrievalOperation<AnySchema> = {
292
+ type: "find",
293
+ schema: testSchema,
294
+ table: testSchema.tables.users,
295
+ indexName: "_primary",
296
+ options: {
297
+ useIndex: "_primary",
298
+ pageSize: 2,
299
+ },
300
+ withCursor: true,
301
+ };
302
+
303
+ const rawResults = [
304
+ [
305
+ { id: "user1", name: "Alice", email: "alice@example.com", age: 30 },
306
+ { id: "user2", name: "Bob", email: "bob@example.com", age: 25 },
307
+ { id: "user3", name: "Charlie", email: "charlie@example.com", age: 35 },
308
+ ],
309
+ ];
310
+
311
+ const results = decoder.decode(rawResults, [operation]);
312
+
313
+ expect(results).toHaveLength(1);
314
+ const cursorResult = results[0] as {
315
+ items: unknown[];
316
+ cursor?: unknown;
317
+ hasNextPage: boolean;
318
+ };
319
+
320
+ expect(cursorResult.items).toHaveLength(2);
321
+ expect(cursorResult.hasNextPage).toBe(true);
322
+ expect(cursorResult.cursor).toBeUndefined(); // No cursor when orderByIndex is missing
323
+ });
324
+
325
+ it("should throw error for invalid count value", () => {
326
+ const operation: RetrievalOperation<AnySchema> = {
327
+ type: "count",
328
+ schema: testSchema,
329
+ table: testSchema.tables.users,
330
+ indexName: "_primary",
331
+ options: {
332
+ useIndex: "_primary",
333
+ },
334
+ };
335
+
336
+ const rawResults = [[{ count: "invalid" }]];
337
+
338
+ expect(() => decoder.decode(rawResults, [operation])).toThrow(
339
+ "Unexpected result for count, received: NaN",
340
+ );
341
+ });
342
+
343
+ it("should handle cursor pagination with FragnoId in cursor", () => {
344
+ const operation: RetrievalOperation<AnySchema> = {
345
+ type: "find",
346
+ schema: testSchema,
347
+ table: testSchema.tables.users,
348
+ indexName: "_primary",
349
+ options: {
350
+ useIndex: "_primary",
351
+ pageSize: 1,
352
+ orderByIndex: {
353
+ indexName: "_primary",
354
+ direction: "asc",
355
+ },
356
+ },
357
+ withCursor: true,
358
+ };
359
+
360
+ const rawResults = [
361
+ [
362
+ {
363
+ id: "user1",
364
+ _internalId: BigInt(123),
365
+ _version: 1,
366
+ name: "Alice",
367
+ email: "alice@example.com",
368
+ age: 30,
369
+ },
370
+ {
371
+ id: "user2",
372
+ _internalId: BigInt(456),
373
+ _version: 1,
374
+ name: "Bob",
375
+ email: "bob@example.com",
376
+ age: 25,
377
+ },
378
+ ],
379
+ ];
380
+
381
+ const results = decoder.decode(rawResults, [operation]);
382
+
383
+ expect(results).toHaveLength(1);
384
+ const cursorResult = results[0] as {
385
+ items: unknown[];
386
+ cursor?: unknown;
387
+ hasNextPage: boolean;
388
+ };
389
+
390
+ expect(cursorResult.items).toHaveLength(1);
391
+ expect(cursorResult.hasNextPage).toBe(true);
392
+ expect(cursorResult.cursor).toBeDefined();
393
+
394
+ // Verify the item has FragnoId
395
+ const firstItem = cursorResult.items[0] as Record<string, unknown>;
396
+ expect(firstItem["id"]).toBeInstanceOf(FragnoId);
397
+ });
398
+ });
399
+ });
@@ -0,0 +1,152 @@
1
+ import type { UOWDecoder } from "../../query/unit-of-work/unit-of-work";
2
+ import type { RetrievalOperation } from "../../query/unit-of-work/unit-of-work";
3
+ import type { AnySchema, AnyTable } from "../../schema/create";
4
+ import { decodeResult } from "../../query/value-decoding";
5
+ import { createCursorFromRecord, type Cursor, type CursorResult } from "../../query/cursor";
6
+ import type { DriverConfig } from "./driver-config";
7
+
8
+ /**
9
+ * Decoder class for Unit of Work retrieval results.
10
+ *
11
+ * Transforms raw database results into application format (e.g., converting raw columns
12
+ * into FragnoId objects with external ID, internal ID, and version).
13
+ */
14
+ export class UnitOfWorkDecoder implements UOWDecoder<unknown> {
15
+ readonly #driverConfig: DriverConfig;
16
+
17
+ constructor(driverConfig: DriverConfig) {
18
+ this.#driverConfig = driverConfig;
19
+ }
20
+
21
+ /**
22
+ * Decode raw database results from the retrieval phase
23
+ *
24
+ * @param rawResults - Array of raw result sets from database queries
25
+ * @param operations - Array of retrieval operations that produced these results
26
+ * @returns Decoded results in application format
27
+ */
28
+ decode(rawResults: unknown[], operations: RetrievalOperation<AnySchema>[]): unknown[] {
29
+ if (rawResults.length !== operations.length) {
30
+ throw new Error("rawResults and ops must have the same length");
31
+ }
32
+
33
+ return rawResults.map((rows, index) => {
34
+ const op = operations[index];
35
+ if (!op) {
36
+ throw new Error("op must be defined");
37
+ }
38
+
39
+ const rowArray = rows as Record<string, unknown>[];
40
+ return this.decodeResultSet(rowArray, op);
41
+ });
42
+ }
43
+
44
+ /**
45
+ * Decodes a result set based on the operation type.
46
+ *
47
+ * This is the main entry point for decoding query results, routing to the
48
+ * appropriate decoder based on whether it's a count, cursor, or regular query.
49
+ *
50
+ * @param rows - The raw database rows
51
+ * @param operation - The retrieval operation defining how to decode the result
52
+ * @returns The decoded result (number for count, CursorResult for cursor, array otherwise)
53
+ */
54
+ private decodeResultSet(
55
+ rows: Record<string, unknown>[],
56
+ operation: RetrievalOperation<AnySchema>,
57
+ ): number | Record<string, unknown>[] | CursorResult<unknown> {
58
+ // Handle count operations
59
+ if (operation.type === "count") {
60
+ return this.decodeCountResult(rows);
61
+ }
62
+
63
+ const decodedRows = rows.map((row) => decodeResult(row, operation.table, this.#driverConfig));
64
+
65
+ if (operation.withCursor) {
66
+ return this.decodeCursorResult(decodedRows, operation.table, operation);
67
+ }
68
+
69
+ return decodedRows;
70
+ }
71
+
72
+ /**
73
+ * Decodes a count query result to a number.
74
+ *
75
+ * @param rows - The raw database rows (should contain a single row with a count column)
76
+ * @returns The count as a number
77
+ * @throws If the count value is invalid or missing
78
+ */
79
+ private decodeCountResult(rows: Record<string, unknown>[]): number {
80
+ const firstRow = rows[0];
81
+ if (!firstRow) {
82
+ return 0;
83
+ }
84
+ const count = Number(firstRow["count"]);
85
+ if (Number.isNaN(count)) {
86
+ throw new Error(`Unexpected result for count, received: ${count}`);
87
+ }
88
+ return count;
89
+ }
90
+
91
+ /**
92
+ * Handles cursor generation and hasNextPage detection for cursor-paginated queries.
93
+ *
94
+ * Checks if we received more rows than the requested pageSize (we fetch pageSize + 1).
95
+ *
96
+ * @param decodedRows - The already-decoded database rows (pageSize + 1 rows)
97
+ * @param table - The table schema definition (needed for cursor generation)
98
+ * @param operation - The find operation containing pagination options
99
+ * @returns A CursorResult with items, cursor, and hasNextPage
100
+ */
101
+ private decodeCursorResult(
102
+ decodedRows: Record<string, unknown>[],
103
+ table: AnyTable,
104
+ operation: Extract<RetrievalOperation<AnySchema>, { type: "find" }>,
105
+ ): CursorResult<unknown> {
106
+ let cursor: Cursor | undefined;
107
+ let hasNextPage = false;
108
+ let items = decodedRows;
109
+
110
+ // Check if there are more results (we fetched pageSize + 1)
111
+ if (
112
+ operation.options.pageSize &&
113
+ operation.options.pageSize > 0 &&
114
+ decodedRows.length > operation.options.pageSize
115
+ ) {
116
+ hasNextPage = true;
117
+ // Trim to requested pageSize
118
+ items = decodedRows.slice(0, operation.options.pageSize);
119
+
120
+ // Generate cursor from the last item we're returning
121
+ if (operation.options.orderByIndex) {
122
+ const lastItem = items[items.length - 1];
123
+ const indexName = operation.options.orderByIndex.indexName;
124
+
125
+ // Get index columns
126
+ let indexColumns;
127
+ if (indexName === "_primary") {
128
+ indexColumns = [table.getIdColumn()];
129
+ } else {
130
+ const index = table.indexes[indexName];
131
+ if (index) {
132
+ indexColumns = index.columns;
133
+ }
134
+ }
135
+
136
+ if (indexColumns && lastItem) {
137
+ cursor = createCursorFromRecord(lastItem, indexColumns, {
138
+ indexName: operation.options.orderByIndex.indexName,
139
+ orderDirection: operation.options.orderByIndex.direction,
140
+ pageSize: operation.options.pageSize,
141
+ });
142
+ }
143
+ }
144
+ }
145
+
146
+ return {
147
+ items,
148
+ cursor,
149
+ hasNextPage,
150
+ };
151
+ }
152
+ }