@fragno-dev/db 0.1.14 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (445) hide show
  1. package/.turbo/turbo-build.log +242 -139
  2. package/CHANGELOG.md +47 -0
  3. package/README.md +123 -8
  4. package/dist/adapters/adapters.d.ts +19 -5
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/drizzle/drizzle-adapter.d.ts +6 -19
  8. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +1 -1
  9. package/dist/adapters/drizzle/drizzle-adapter.js +7 -47
  10. package/dist/adapters/drizzle/drizzle-adapter.js.map +1 -1
  11. package/dist/adapters/drizzle/generate.d.ts +7 -1
  12. package/dist/adapters/drizzle/generate.d.ts.map +1 -1
  13. package/dist/adapters/drizzle/generate.js +46 -45
  14. package/dist/adapters/drizzle/generate.js.map +1 -1
  15. package/dist/adapters/generic-sql/driver-config.d.ts +74 -0
  16. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -0
  17. package/dist/adapters/generic-sql/driver-config.js +94 -0
  18. package/dist/adapters/generic-sql/driver-config.js.map +1 -0
  19. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +43 -0
  20. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -0
  21. package/dist/adapters/generic-sql/generic-sql-adapter.js +87 -0
  22. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -0
  23. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +67 -0
  24. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -0
  25. package/dist/adapters/generic-sql/migration/cold-kysely.js +33 -0
  26. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -0
  27. package/dist/adapters/generic-sql/migration/dialect/mysql.js +60 -0
  28. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -0
  29. package/dist/adapters/generic-sql/migration/dialect/postgres.js +59 -0
  30. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -0
  31. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +96 -0
  32. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -0
  33. package/dist/adapters/generic-sql/migration/executor.d.ts +15 -0
  34. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  35. package/dist/adapters/generic-sql/migration/executor.js +18 -0
  36. package/dist/adapters/generic-sql/migration/executor.js.map +1 -0
  37. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  38. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  39. package/dist/adapters/generic-sql/migration/prepared-migrations.js +68 -0
  40. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -0
  41. package/dist/adapters/generic-sql/migration/sql-generator.js +212 -0
  42. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -0
  43. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +32 -0
  44. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -0
  45. package/dist/adapters/generic-sql/query/cursor-utils.js +37 -0
  46. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -0
  47. package/dist/adapters/generic-sql/query/dialect/mysql.js +33 -0
  48. package/dist/adapters/generic-sql/query/dialect/mysql.js.map +1 -0
  49. package/dist/adapters/generic-sql/query/dialect/postgres.js +32 -0
  50. package/dist/adapters/generic-sql/query/dialect/postgres.js.map +1 -0
  51. package/dist/adapters/generic-sql/query/dialect/sqlite.js +32 -0
  52. package/dist/adapters/generic-sql/query/dialect/sqlite.js.map +1 -0
  53. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +152 -0
  54. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -0
  55. package/dist/adapters/generic-sql/query/select-builder.js +69 -0
  56. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -0
  57. package/dist/adapters/generic-sql/query/sql-query-compiler.js +145 -0
  58. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -0
  59. package/dist/adapters/generic-sql/query/where-builder.js +129 -0
  60. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -0
  61. package/dist/adapters/generic-sql/result-interpreter.js +74 -0
  62. package/dist/adapters/generic-sql/result-interpreter.js.map +1 -0
  63. package/dist/adapters/generic-sql/uow-decoder.js +105 -0
  64. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -0
  65. package/dist/adapters/generic-sql/uow-encoder.js +93 -0
  66. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -0
  67. package/dist/adapters/kysely/kysely-adapter.d.ts +5 -16
  68. package/dist/adapters/kysely/kysely-adapter.d.ts.map +1 -1
  69. package/dist/adapters/kysely/kysely-adapter.js +6 -159
  70. package/dist/adapters/kysely/kysely-adapter.js.map +1 -1
  71. package/dist/adapters/{drizzle/drizzle-query.js → shared/from-unit-of-work-compiler.js} +48 -62
  72. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -0
  73. package/dist/adapters/{kysely/kysely-shared.d.ts → shared/table-name-mapper.d.ts} +3 -2
  74. package/dist/adapters/shared/table-name-mapper.d.ts.map +1 -0
  75. package/dist/adapters/shared/table-name-mapper.js +43 -0
  76. package/dist/adapters/shared/table-name-mapper.js.map +1 -0
  77. package/dist/adapters/shared/uow-operation-compiler.js +105 -0
  78. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -0
  79. package/dist/db-fragment-definition-builder.d.ts +186 -0
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -0
  81. package/dist/db-fragment-definition-builder.js +207 -0
  82. package/dist/db-fragment-definition-builder.js.map +1 -0
  83. package/dist/fragments/internal-fragment.d.ts +53 -0
  84. package/dist/fragments/internal-fragment.d.ts.map +1 -0
  85. package/dist/fragments/internal-fragment.js +111 -0
  86. package/dist/fragments/internal-fragment.js.map +1 -0
  87. package/dist/hooks/hooks.d.ts +51 -0
  88. package/dist/hooks/hooks.d.ts.map +1 -0
  89. package/dist/hooks/hooks.js +88 -0
  90. package/dist/hooks/hooks.js.map +1 -0
  91. package/dist/migration-engine/generation-engine.d.ts +0 -2
  92. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  93. package/dist/migration-engine/generation-engine.js +38 -56
  94. package/dist/migration-engine/generation-engine.js.map +1 -1
  95. package/dist/mod.d.ts +35 -23
  96. package/dist/mod.d.ts.map +1 -1
  97. package/dist/mod.js +48 -45
  98. package/dist/mod.js.map +1 -1
  99. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +165 -0
  100. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +1 -0
  101. package/dist/packages/fragno/dist/api/bind-services.js +20 -0
  102. package/dist/packages/fragno/dist/api/bind-services.js.map +1 -0
  103. package/dist/packages/fragno/dist/api/error.js +48 -0
  104. package/dist/packages/fragno/dist/api/error.js.map +1 -0
  105. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +320 -0
  106. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -0
  107. package/dist/packages/fragno/dist/api/fragment-instantiator.js +525 -0
  108. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -0
  109. package/dist/packages/fragno/dist/api/fragno-response.js +73 -0
  110. package/dist/packages/fragno/dist/api/fragno-response.js.map +1 -0
  111. package/dist/packages/fragno/dist/api/internal/response-stream.js +81 -0
  112. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +1 -0
  113. package/dist/packages/fragno/dist/api/internal/route.js +10 -0
  114. package/dist/packages/fragno/dist/api/internal/route.js.map +1 -0
  115. package/dist/packages/fragno/dist/api/mutable-request-state.js +97 -0
  116. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +1 -0
  117. package/dist/packages/fragno/dist/api/request-context-storage.js +43 -0
  118. package/dist/packages/fragno/dist/api/request-context-storage.js.map +1 -0
  119. package/dist/packages/fragno/dist/api/request-input-context.js +118 -0
  120. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -0
  121. package/dist/packages/fragno/dist/api/request-middleware.js +83 -0
  122. package/dist/packages/fragno/dist/api/request-middleware.js.map +1 -0
  123. package/dist/packages/fragno/dist/api/request-output-context.js +119 -0
  124. package/dist/packages/fragno/dist/api/request-output-context.js.map +1 -0
  125. package/dist/packages/fragno/dist/api/route.js +17 -0
  126. package/dist/packages/fragno/dist/api/route.js.map +1 -0
  127. package/dist/packages/fragno/dist/internal/symbols.js +10 -0
  128. package/dist/packages/fragno/dist/internal/symbols.js.map +1 -0
  129. package/dist/query/column-defaults.js +27 -0
  130. package/dist/query/column-defaults.js.map +1 -0
  131. package/dist/query/cursor.d.ts +14 -6
  132. package/dist/query/cursor.d.ts.map +1 -1
  133. package/dist/query/cursor.js +16 -7
  134. package/dist/query/cursor.js.map +1 -1
  135. package/dist/query/orm/orm.d.ts +1 -1
  136. package/dist/query/orm/orm.js.map +1 -1
  137. package/dist/query/serialize/create-sql-serializer.js +30 -0
  138. package/dist/query/serialize/create-sql-serializer.js.map +1 -0
  139. package/dist/query/serialize/dialect/mysql-serializer.js +87 -0
  140. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -0
  141. package/dist/query/serialize/dialect/postgres-serializer.js +80 -0
  142. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -0
  143. package/dist/query/serialize/dialect/sqlite-serializer.js +93 -0
  144. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -0
  145. package/dist/query/serialize/sql-serializer.js +67 -0
  146. package/dist/query/serialize/sql-serializer.js.map +1 -0
  147. package/dist/query/{query.d.ts → simple-query-interface.d.ts} +6 -6
  148. package/dist/query/simple-query-interface.d.ts.map +1 -0
  149. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +133 -0
  150. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  151. package/dist/query/unit-of-work/execute-unit-of-work.js +197 -0
  152. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  153. package/dist/query/unit-of-work/retry-policy.d.ts +88 -0
  154. package/dist/query/unit-of-work/retry-policy.d.ts.map +1 -0
  155. package/dist/query/unit-of-work/retry-policy.js +61 -0
  156. package/dist/query/unit-of-work/retry-policy.js.map +1 -0
  157. package/dist/query/{unit-of-work.d.ts → unit-of-work/unit-of-work.d.ts} +145 -58
  158. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  159. package/dist/query/{unit-of-work.js → unit-of-work/unit-of-work.js} +435 -198
  160. package/dist/query/unit-of-work/unit-of-work.js.map +1 -0
  161. package/dist/query/value-decoding.js +71 -0
  162. package/dist/query/value-decoding.js.map +1 -0
  163. package/dist/query/value-encoding.js +124 -0
  164. package/dist/query/value-encoding.js.map +1 -0
  165. package/dist/schema/create.d.ts +3 -0
  166. package/dist/schema/create.d.ts.map +1 -1
  167. package/dist/schema/create.js +4 -0
  168. package/dist/schema/create.js.map +1 -1
  169. package/dist/schema/type-conversion/create-sql-type-mapper.js +29 -0
  170. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -0
  171. package/dist/schema/type-conversion/dialect/mysql.js +57 -0
  172. package/dist/schema/type-conversion/dialect/mysql.js.map +1 -0
  173. package/dist/schema/type-conversion/dialect/postgres.js +56 -0
  174. package/dist/schema/type-conversion/dialect/postgres.js.map +1 -0
  175. package/dist/schema/type-conversion/dialect/sqlite.js +52 -0
  176. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -0
  177. package/dist/schema/type-conversion/type-mapping.js +63 -0
  178. package/dist/schema/type-conversion/type-mapping.js.map +1 -0
  179. package/dist/sql-driver/connection/connection-provider.d.ts +13 -0
  180. package/dist/sql-driver/connection/connection-provider.d.ts.map +1 -0
  181. package/dist/sql-driver/connection/connection-provider.js +19 -0
  182. package/dist/sql-driver/connection/connection-provider.js.map +1 -0
  183. package/dist/sql-driver/connection/single-connection-provider.js +23 -0
  184. package/dist/sql-driver/connection/single-connection-provider.js.map +1 -0
  185. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  186. package/dist/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  187. package/dist/sql-driver/dialects/dialects.d.ts +2 -0
  188. package/dist/sql-driver/dialects/dialects.js +3 -0
  189. package/dist/sql-driver/dialects/durable-object-dialect.d.ts +72 -0
  190. package/dist/sql-driver/dialects/durable-object-dialect.d.ts.map +1 -0
  191. package/dist/sql-driver/dialects/durable-object-dialect.js +130 -0
  192. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -0
  193. package/dist/sql-driver/driver/runtime-driver.d.ts +23 -0
  194. package/dist/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  195. package/dist/sql-driver/driver/runtime-driver.js +56 -0
  196. package/dist/sql-driver/driver/runtime-driver.js.map +1 -0
  197. package/dist/sql-driver/query-executor/default-query-executor.js +26 -0
  198. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -0
  199. package/dist/sql-driver/query-executor/plugin.d.ts +17 -0
  200. package/dist/sql-driver/query-executor/plugin.d.ts.map +1 -0
  201. package/dist/sql-driver/query-executor/query-executor-base.js +25 -0
  202. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -0
  203. package/dist/sql-driver/query-executor/query-executor.d.ts +36 -0
  204. package/dist/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  205. package/dist/sql-driver/sql-driver-adapter.d.ts +29 -0
  206. package/dist/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  207. package/dist/sql-driver/sql-driver-adapter.js +68 -0
  208. package/dist/sql-driver/sql-driver-adapter.js.map +1 -0
  209. package/dist/sql-driver/sql-driver.d.ts +38 -0
  210. package/dist/sql-driver/sql-driver.d.ts.map +1 -0
  211. package/dist/sql-driver/sql-driver.js +1 -0
  212. package/dist/sql-driver/sql.js +50 -0
  213. package/dist/sql-driver/sql.js.map +1 -0
  214. package/dist/with-database.d.ts +32 -0
  215. package/dist/with-database.d.ts.map +1 -0
  216. package/dist/with-database.js +34 -0
  217. package/dist/with-database.js.map +1 -0
  218. package/package.json +43 -9
  219. package/src/adapters/adapters.ts +23 -4
  220. package/src/adapters/drizzle/drizzle-adapter-pglite.test.ts +140 -185
  221. package/src/adapters/drizzle/{drizzle-adapter-sqlite.test.ts → drizzle-adapter-sqlite3.test.ts} +187 -55
  222. package/src/adapters/drizzle/drizzle-adapter.ts +14 -93
  223. package/src/adapters/drizzle/generate.test.ts +102 -269
  224. package/src/adapters/drizzle/generate.ts +89 -63
  225. package/src/adapters/drizzle/migrate-drizzle.test.ts +19 -0
  226. package/src/adapters/drizzle/shared.ts +0 -34
  227. package/src/adapters/drizzle/test-utils.ts +36 -5
  228. package/src/adapters/generic-sql/README.md +14 -0
  229. package/src/adapters/generic-sql/driver-config.ts +144 -0
  230. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +50 -0
  231. package/src/adapters/generic-sql/generic-sql-adapter.ts +146 -0
  232. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +130 -0
  233. package/src/adapters/generic-sql/migration/cold-kysely.ts +55 -0
  234. package/src/adapters/{kysely/migration/execute-mysql.test.ts → generic-sql/migration/dialect/mysql.test.ts} +342 -484
  235. package/src/adapters/generic-sql/migration/dialect/mysql.ts +104 -0
  236. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +1008 -0
  237. package/src/adapters/generic-sql/migration/dialect/postgres.ts +113 -0
  238. package/src/adapters/{kysely/migration/execute-sqlite.test.ts → generic-sql/migration/dialect/sqlite.test.ts} +307 -510
  239. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +189 -0
  240. package/src/adapters/generic-sql/migration/executor.ts +33 -0
  241. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +661 -0
  242. package/src/adapters/generic-sql/migration/prepared-migrations.ts +214 -0
  243. package/src/adapters/generic-sql/migration/sql-generator.ts +413 -0
  244. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +36 -0
  245. package/src/adapters/generic-sql/query/cursor-utils.ts +56 -0
  246. package/src/adapters/generic-sql/query/dialect/mysql.ts +34 -0
  247. package/src/adapters/generic-sql/query/dialect/postgres.ts +32 -0
  248. package/src/adapters/generic-sql/query/dialect/sqlite.ts +32 -0
  249. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +1568 -0
  250. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +314 -0
  251. package/src/adapters/generic-sql/query/select-builder.test.ts +256 -0
  252. package/src/adapters/generic-sql/query/select-builder.ts +137 -0
  253. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +195 -0
  254. package/src/adapters/generic-sql/query/sql-query-compiler.ts +367 -0
  255. package/src/adapters/generic-sql/query/where-builder.test.ts +744 -0
  256. package/src/adapters/generic-sql/query/where-builder.ts +211 -0
  257. package/src/adapters/generic-sql/result-interpreter.ts +102 -0
  258. package/src/adapters/generic-sql/test/generic-drizzle-adapter-sqlite3.test.ts +899 -0
  259. package/src/adapters/generic-sql/uow-decoder.test.ts +399 -0
  260. package/src/adapters/generic-sql/uow-decoder.ts +152 -0
  261. package/src/adapters/generic-sql/uow-encoder.test.ts +183 -0
  262. package/src/adapters/generic-sql/uow-encoder.ts +131 -0
  263. package/src/adapters/kysely/kysely-adapter-pglite.test.ts +90 -96
  264. package/src/adapters/kysely/kysely-adapter-sqlocal.test.ts +215 -0
  265. package/src/adapters/kysely/kysely-adapter.ts +10 -242
  266. package/src/adapters/{drizzle/drizzle-query.ts → shared/from-unit-of-work-compiler.ts} +111 -106
  267. package/src/adapters/shared/table-name-mapper.ts +50 -0
  268. package/src/adapters/shared/uow-operation-compiler.ts +211 -0
  269. package/src/db-fragment-definition-builder.test.ts +887 -0
  270. package/src/db-fragment-definition-builder.ts +737 -0
  271. package/src/db-fragment-instantiator.test.ts +543 -0
  272. package/src/db-fragment-integration.test.ts +406 -0
  273. package/src/fragments/internal-fragment.test.ts +549 -0
  274. package/src/fragments/internal-fragment.ts +249 -0
  275. package/src/hooks/hooks.test.ts +575 -0
  276. package/src/hooks/hooks.ts +179 -0
  277. package/src/migration-engine/generation-engine.test.ts +60 -27
  278. package/src/migration-engine/generation-engine.ts +99 -92
  279. package/src/mod.ts +139 -78
  280. package/src/query/column-defaults.ts +49 -0
  281. package/src/query/cursor.test.ts +147 -3
  282. package/src/query/cursor.ts +25 -8
  283. package/src/query/orm/orm.ts +1 -1
  284. package/src/query/query-type.test.ts +9 -9
  285. package/src/query/serialize/create-sql-serializer.ts +34 -0
  286. package/src/query/serialize/dialect/mysql-serializer.ts +142 -0
  287. package/src/query/serialize/dialect/postgres-serializer.ts +129 -0
  288. package/src/query/serialize/dialect/sqlite-serializer.test.ts +251 -0
  289. package/src/query/serialize/dialect/sqlite-serializer.ts +156 -0
  290. package/src/query/serialize/sql-serializer.ts +143 -0
  291. package/src/query/{query.ts → simple-query-interface.ts} +4 -4
  292. package/src/query/unit-of-work/execute-unit-of-work.test.ts +1310 -0
  293. package/src/query/unit-of-work/execute-unit-of-work.ts +504 -0
  294. package/src/query/unit-of-work/retry-policy.test.ts +217 -0
  295. package/src/query/unit-of-work/retry-policy.ts +141 -0
  296. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +831 -0
  297. package/src/query/{unit-of-work-types.test.ts → unit-of-work/unit-of-work-types.test.ts} +7 -5
  298. package/src/query/unit-of-work/unit-of-work.test.ts +1716 -0
  299. package/src/query/{unit-of-work.ts → unit-of-work/unit-of-work.ts} +716 -420
  300. package/src/query/{result-transform.test.ts → value-decoding.test.ts} +45 -298
  301. package/src/query/value-decoding.ts +113 -0
  302. package/src/query/value-encoding.test.ts +390 -0
  303. package/src/query/value-encoding.ts +168 -0
  304. package/src/schema/create.test.ts +5 -1
  305. package/src/schema/create.ts +5 -0
  306. package/src/schema/serialize.test.ts +165 -407
  307. package/src/schema/type-conversion/create-sql-type-mapper.ts +28 -0
  308. package/src/schema/type-conversion/dialect/mysql.ts +64 -0
  309. package/src/schema/type-conversion/dialect/postgres.ts +62 -0
  310. package/src/schema/type-conversion/dialect/sqlite.ts +63 -0
  311. package/src/schema/type-conversion/type-mapping.test.ts +137 -0
  312. package/src/schema/type-conversion/type-mapping.ts +153 -0
  313. package/src/shared/connection-pool.ts +5 -5
  314. package/src/sql-driver/better-sqlite3.test.ts +126 -0
  315. package/src/sql-driver/connection/connection-provider.ts +27 -0
  316. package/src/sql-driver/connection/single-connection-provider.ts +42 -0
  317. package/src/sql-driver/dialect-adapter/dialect-adapter.ts +9 -0
  318. package/src/sql-driver/dialect-adapter/sqlite-dialect-adapter.ts +7 -0
  319. package/src/sql-driver/dialects/dialects.ts +1 -0
  320. package/src/sql-driver/dialects/durable-object-dialect.ts +260 -0
  321. package/src/sql-driver/driver/runtime-driver.ts +91 -0
  322. package/src/sql-driver/query-executor/default-query-executor.ts +38 -0
  323. package/src/sql-driver/query-executor/plugin.ts +22 -0
  324. package/src/sql-driver/query-executor/query-executor-base.ts +53 -0
  325. package/src/sql-driver/query-executor/query-executor.ts +44 -0
  326. package/src/sql-driver/sql-driver-adapter.ts +96 -0
  327. package/src/sql-driver/sql-driver.ts +53 -0
  328. package/src/sql-driver/sql.ts +57 -0
  329. package/src/sql-driver/sqlocal.test.ts +117 -0
  330. package/src/with-database.ts +152 -0
  331. package/tsdown.config.ts +8 -2
  332. package/dist/adapters/drizzle/drizzle-connection-pool.js +0 -40
  333. package/dist/adapters/drizzle/drizzle-connection-pool.js.map +0 -1
  334. package/dist/adapters/drizzle/drizzle-query.d.ts +0 -23
  335. package/dist/adapters/drizzle/drizzle-query.d.ts.map +0 -1
  336. package/dist/adapters/drizzle/drizzle-query.js.map +0 -1
  337. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts +0 -10
  338. package/dist/adapters/drizzle/drizzle-uow-compiler.d.ts.map +0 -1
  339. package/dist/adapters/drizzle/drizzle-uow-compiler.js +0 -315
  340. package/dist/adapters/drizzle/drizzle-uow-compiler.js.map +0 -1
  341. package/dist/adapters/drizzle/drizzle-uow-decoder.js +0 -116
  342. package/dist/adapters/drizzle/drizzle-uow-decoder.js.map +0 -1
  343. package/dist/adapters/drizzle/drizzle-uow-executor.js +0 -149
  344. package/dist/adapters/drizzle/drizzle-uow-executor.js.map +0 -1
  345. package/dist/adapters/drizzle/join-column-utils.js +0 -28
  346. package/dist/adapters/drizzle/join-column-utils.js.map +0 -1
  347. package/dist/adapters/drizzle/shared.d.ts +0 -14
  348. package/dist/adapters/drizzle/shared.d.ts.map +0 -1
  349. package/dist/adapters/drizzle/shared.js +0 -35
  350. package/dist/adapters/drizzle/shared.js.map +0 -1
  351. package/dist/adapters/kysely/kysely-connection-pool.js +0 -41
  352. package/dist/adapters/kysely/kysely-connection-pool.js.map +0 -1
  353. package/dist/adapters/kysely/kysely-query-builder.js +0 -321
  354. package/dist/adapters/kysely/kysely-query-builder.js.map +0 -1
  355. package/dist/adapters/kysely/kysely-query-compiler.js +0 -66
  356. package/dist/adapters/kysely/kysely-query-compiler.js.map +0 -1
  357. package/dist/adapters/kysely/kysely-query.d.ts +0 -22
  358. package/dist/adapters/kysely/kysely-query.d.ts.map +0 -1
  359. package/dist/adapters/kysely/kysely-query.js +0 -223
  360. package/dist/adapters/kysely/kysely-query.js.map +0 -1
  361. package/dist/adapters/kysely/kysely-shared.d.ts.map +0 -1
  362. package/dist/adapters/kysely/kysely-shared.js +0 -18
  363. package/dist/adapters/kysely/kysely-shared.js.map +0 -1
  364. package/dist/adapters/kysely/kysely-uow-compiler.js +0 -170
  365. package/dist/adapters/kysely/kysely-uow-compiler.js.map +0 -1
  366. package/dist/adapters/kysely/kysely-uow-executor.js +0 -89
  367. package/dist/adapters/kysely/kysely-uow-executor.js.map +0 -1
  368. package/dist/adapters/kysely/migration/execute-base.js +0 -128
  369. package/dist/adapters/kysely/migration/execute-base.js.map +0 -1
  370. package/dist/adapters/kysely/migration/execute-factory.js +0 -34
  371. package/dist/adapters/kysely/migration/execute-factory.js.map +0 -1
  372. package/dist/adapters/kysely/migration/execute-mssql.js +0 -112
  373. package/dist/adapters/kysely/migration/execute-mssql.js.map +0 -1
  374. package/dist/adapters/kysely/migration/execute-mysql.js +0 -93
  375. package/dist/adapters/kysely/migration/execute-mysql.js.map +0 -1
  376. package/dist/adapters/kysely/migration/execute-postgres.js +0 -104
  377. package/dist/adapters/kysely/migration/execute-postgres.js.map +0 -1
  378. package/dist/adapters/kysely/migration/execute-sqlite.js +0 -123
  379. package/dist/adapters/kysely/migration/execute-sqlite.js.map +0 -1
  380. package/dist/adapters/kysely/migration/execute.js +0 -34
  381. package/dist/adapters/kysely/migration/execute.js.map +0 -1
  382. package/dist/bind-services.d.ts +0 -7
  383. package/dist/bind-services.d.ts.map +0 -1
  384. package/dist/bind-services.js +0 -14
  385. package/dist/bind-services.js.map +0 -1
  386. package/dist/fragment.d.ts +0 -173
  387. package/dist/fragment.d.ts.map +0 -1
  388. package/dist/fragment.js +0 -191
  389. package/dist/fragment.js.map +0 -1
  390. package/dist/migration-engine/create.d.ts +0 -37
  391. package/dist/migration-engine/create.d.ts.map +0 -1
  392. package/dist/migration-engine/create.js +0 -58
  393. package/dist/migration-engine/create.js.map +0 -1
  394. package/dist/migration-engine/shared.d.ts +0 -112
  395. package/dist/migration-engine/shared.d.ts.map +0 -1
  396. package/dist/query/query.d.ts.map +0 -1
  397. package/dist/query/result-transform.js +0 -168
  398. package/dist/query/result-transform.js.map +0 -1
  399. package/dist/query/unit-of-work.d.ts.map +0 -1
  400. package/dist/query/unit-of-work.js.map +0 -1
  401. package/dist/schema/serialize.js +0 -106
  402. package/dist/schema/serialize.js.map +0 -1
  403. package/dist/shared/settings-schema.js +0 -36
  404. package/dist/shared/settings-schema.js.map +0 -1
  405. package/src/adapters/drizzle/drizzle-adapter.test.ts +0 -170
  406. package/src/adapters/drizzle/drizzle-connection-pool.ts +0 -66
  407. package/src/adapters/drizzle/drizzle-query.test.ts +0 -499
  408. package/src/adapters/drizzle/drizzle-uow-compiler.test.ts +0 -1383
  409. package/src/adapters/drizzle/drizzle-uow-compiler.ts +0 -636
  410. package/src/adapters/drizzle/drizzle-uow-decoder.ts +0 -218
  411. package/src/adapters/drizzle/drizzle-uow-executor.ts +0 -276
  412. package/src/adapters/drizzle/join-column-utils.test.ts +0 -79
  413. package/src/adapters/drizzle/join-column-utils.ts +0 -39
  414. package/src/adapters/kysely/kysely-connection-pool.ts +0 -70
  415. package/src/adapters/kysely/kysely-query-builder.test.ts +0 -1344
  416. package/src/adapters/kysely/kysely-query-builder.ts +0 -666
  417. package/src/adapters/kysely/kysely-query-compiler.ts +0 -132
  418. package/src/adapters/kysely/kysely-query.test.ts +0 -498
  419. package/src/adapters/kysely/kysely-query.ts +0 -390
  420. package/src/adapters/kysely/kysely-shared.ts +0 -23
  421. package/src/adapters/kysely/kysely-uow-compiler.test.ts +0 -998
  422. package/src/adapters/kysely/kysely-uow-compiler.ts +0 -318
  423. package/src/adapters/kysely/kysely-uow-executor.ts +0 -145
  424. package/src/adapters/kysely/kysely-uow-joins.test.ts +0 -811
  425. package/src/adapters/kysely/migration/execute-base.ts +0 -256
  426. package/src/adapters/kysely/migration/execute-factory.ts +0 -53
  427. package/src/adapters/kysely/migration/execute-mssql.ts +0 -250
  428. package/src/adapters/kysely/migration/execute-mysql.ts +0 -211
  429. package/src/adapters/kysely/migration/execute-postgres.test.ts +0 -2657
  430. package/src/adapters/kysely/migration/execute-postgres.ts +0 -234
  431. package/src/adapters/kysely/migration/execute-sqlite.ts +0 -247
  432. package/src/adapters/kysely/migration/execute.ts +0 -50
  433. package/src/adapters/kysely/migration/kysely-migrator.test.ts +0 -261
  434. package/src/bind-services.test.ts +0 -214
  435. package/src/bind-services.ts +0 -37
  436. package/src/db-fragment.test.ts +0 -800
  437. package/src/fragment.ts +0 -727
  438. package/src/query/result-transform.ts +0 -271
  439. package/src/query/unit-of-work-multi-schema.test.ts +0 -64
  440. package/src/query/unit-of-work.test.ts +0 -943
  441. package/src/schema/serialize.ts +0 -396
  442. package/src/shared/settings-schema.ts +0 -61
  443. package/src/uow-context-integration.test.ts +0 -102
  444. package/src/uow-context.test.ts +0 -182
  445. /package/dist/query/{query.js → simple-query-interface.js} +0 -0
@@ -1,943 +0,0 @@
1
- import { describe, it, expect, assert, expectTypeOf } from "vitest";
2
- import { column, schema, idColumn } from "../schema/create";
3
- import {
4
- UnitOfWork,
5
- type UOWCompiler,
6
- type UOWDecoder,
7
- createUnitOfWork,
8
- type InferIdColumnName,
9
- type IndexColumns,
10
- } from "./unit-of-work";
11
- import { createIndexedBuilder } from "./condition-builder";
12
- import type { AbstractQuery } from "./query";
13
-
14
- // Mock compiler and executor for testing
15
- function createMockCompiler(): UOWCompiler<unknown> {
16
- return {
17
- compileRetrievalOperation: () => null,
18
- compileMutationOperation: () => null,
19
- };
20
- }
21
-
22
- function createMockExecutor() {
23
- return {
24
- executeRetrievalPhase: async () => [],
25
- executeMutationPhase: async () => ({ success: true, createdInternalIds: [] }),
26
- };
27
- }
28
-
29
- function createMockDecoder(): UOWDecoder {
30
- return (rawResults, operations) => {
31
- if (rawResults.length !== operations.length) {
32
- throw new Error("rawResults and operations must have the same length");
33
- }
34
- return rawResults;
35
- };
36
- }
37
-
38
- describe("FindBuilder", () => {
39
- it("should support primary index", () => {
40
- const testSchema = schema((s) =>
41
- s.addTable("users", (t) =>
42
- t
43
- .addColumn("id", idColumn())
44
- .addColumn("email", "string")
45
- .addColumn("name", "string")
46
- .addColumn("age", "integer")
47
- .createIndex("idx_email", ["email"], { unique: true })
48
- .createIndex("idx_name_age", ["name", "age"]),
49
- ),
50
- );
51
-
52
- const uow = new UnitOfWork(
53
- testSchema,
54
- createMockCompiler(),
55
- createMockExecutor(),
56
- createMockDecoder(),
57
- );
58
- uow.find("users", (b) => b.whereIndex("primary"));
59
-
60
- const ops = uow.getRetrievalOperations();
61
- expect(ops).toHaveLength(1);
62
- expect(ops[0].indexName).toBe("_primary");
63
- });
64
-
65
- it("should support custom indexes", () => {
66
- const testSchema = schema((s) =>
67
- s.addTable("users", (t) =>
68
- t
69
- .addColumn("id", idColumn())
70
- .addColumn("email", "string")
71
- .addColumn("name", "string")
72
- .createIndex("idx_email", ["email"], { unique: true }),
73
- ),
74
- );
75
-
76
- const uow = new UnitOfWork(
77
- testSchema,
78
- createMockCompiler(),
79
- createMockExecutor(),
80
- createMockDecoder(),
81
- );
82
- uow.find("users", (b) =>
83
- b.whereIndex("idx_email", (eb) => eb("email", "=", "test@example.com")),
84
- );
85
-
86
- const ops = uow.getRetrievalOperations();
87
- expect(ops).toHaveLength(1);
88
- expect(ops[0].indexName).toBe("idx_email");
89
- });
90
-
91
- it("should support cursor-based pagination", () => {
92
- const testSchema = schema((s) =>
93
- s.addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string")),
94
- );
95
-
96
- const uow = new UnitOfWork(
97
- testSchema,
98
- createMockCompiler(),
99
- createMockExecutor(),
100
- createMockDecoder(),
101
- );
102
-
103
- const cursor = "eyJpbmRleFZhbHVlcyI6eyJpZCI6InVzZXIxMjMifSwiZGlyZWN0aW9uIjoiZm9yd2FyZCJ9";
104
- uow.find("users", (b) => b.whereIndex("primary").after(cursor).pageSize(10));
105
-
106
- const ops = uow.getRetrievalOperations();
107
- expect(ops).toHaveLength(1);
108
- const op = ops[0];
109
- assert(op.type === "find");
110
- expect(op.options.after).toBe(cursor);
111
- expect(op.options.pageSize).toBe(10);
112
- });
113
-
114
- it("should support backward cursor pagination", () => {
115
- const testSchema = schema((s) =>
116
- s.addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string")),
117
- );
118
-
119
- const uow = new UnitOfWork(
120
- testSchema,
121
- createMockCompiler(),
122
- createMockExecutor(),
123
- createMockDecoder(),
124
- );
125
-
126
- const cursor = "eyJpbmRleFZhbHVlcyI6eyJpZCI6InVzZXI0NTYifSwiZGlyZWN0aW9uIjoiYmFja3dhcmQifQ==";
127
- uow.find("users", (b) => b.whereIndex("primary").before(cursor).pageSize(5));
128
-
129
- const ops = uow.getRetrievalOperations();
130
- expect(ops).toHaveLength(1);
131
- const op = ops[0];
132
- assert(op.type === "find");
133
- expect(op.options.before).toBe(cursor);
134
- expect(op.options.pageSize).toBe(5);
135
- });
136
-
137
- it("should throw if index doesn't exist", () => {
138
- const testSchema = schema((s) =>
139
- s.addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string")),
140
- );
141
-
142
- const uow = new UnitOfWork(
143
- testSchema,
144
- createMockCompiler(),
145
- createMockExecutor(),
146
- createMockDecoder(),
147
- );
148
- expect(() => {
149
- uow.find("users", (b) => b.whereIndex("nonexistent" as "primary"));
150
- }).toThrow('Index "nonexistent" not found on table "users"');
151
- });
152
-
153
- it("should throw if finalized without index", () => {
154
- const testSchema = schema((s) =>
155
- s.addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string")),
156
- );
157
-
158
- const uow = new UnitOfWork(
159
- testSchema,
160
- createMockCompiler(),
161
- createMockExecutor(),
162
- createMockDecoder(),
163
- );
164
- expect(() => {
165
- uow.find("users", (b) => b);
166
- }).toThrow(
167
- 'Must specify an index using .whereIndex() before finalizing find operation on table "users"',
168
- );
169
- });
170
-
171
- it("should support count operations", () => {
172
- const testSchema = schema((s) =>
173
- s.addTable("users", (t) =>
174
- t.addColumn("id", idColumn()).addColumn("name", "string").addColumn("age", "integer"),
175
- ),
176
- );
177
-
178
- const uow = new UnitOfWork(
179
- testSchema,
180
- createMockCompiler(),
181
- createMockExecutor(),
182
- createMockDecoder(),
183
- );
184
- uow.find("users", (b) => b.whereIndex("primary").selectCount());
185
-
186
- const ops = uow.getRetrievalOperations();
187
- expect(ops).toHaveLength(1);
188
- expect(ops[0]?.type).toBe("count");
189
- });
190
-
191
- it("should throw when using both select and selectCount", () => {
192
- const testSchema = schema((s) =>
193
- s.addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string")),
194
- );
195
-
196
- const uow = new UnitOfWork(
197
- testSchema,
198
- createMockCompiler(),
199
- createMockExecutor(),
200
- createMockDecoder(),
201
- );
202
-
203
- // select() then selectCount()
204
- expect(() => {
205
- uow.find("users", (b) => b.whereIndex("primary").select(["name"]).selectCount());
206
- }).toThrow(/cannot call selectCount/i);
207
-
208
- // selectCount() then select()
209
- const uow2 = new UnitOfWork(
210
- testSchema,
211
- createMockCompiler(),
212
- createMockExecutor(),
213
- createMockDecoder(),
214
- );
215
- expect(() => {
216
- uow2.find("users", (b) => b.whereIndex("primary").selectCount().select(["name"]));
217
- }).toThrow(/cannot call select/i);
218
- });
219
-
220
- it("should support orderByIndex", () => {
221
- const testSchema = schema((s) =>
222
- s.addTable("users", (t) =>
223
- t
224
- .addColumn("id", idColumn())
225
- .addColumn("name", "string")
226
- .addColumn("createdAt", "integer")
227
- .createIndex("idx_created", ["createdAt"]),
228
- ),
229
- );
230
-
231
- const uow = new UnitOfWork(
232
- testSchema,
233
- createMockCompiler(),
234
- createMockExecutor(),
235
- createMockDecoder(),
236
- );
237
- uow.find("users", (b) => b.whereIndex("primary").orderByIndex("idx_created", "desc"));
238
-
239
- const ops = uow.getRetrievalOperations();
240
- expect(ops).toHaveLength(1);
241
- const op = ops[0];
242
- if (op?.type === "find") {
243
- expect(op.options.orderByIndex).toEqual({
244
- indexName: "idx_created",
245
- direction: "desc",
246
- });
247
- } else {
248
- throw new Error("Expected find operation");
249
- }
250
- });
251
-
252
- it("should support join operations", () => {
253
- const testSchema = schema((s) =>
254
- s
255
- .addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string"))
256
- .addTable("posts", (t) =>
257
- t
258
- .addColumn("id", idColumn())
259
- .addColumn("userId", column("string"))
260
- .addColumn("title", "string")
261
- .createIndex("idx_user", ["userId"]),
262
- )
263
- .addReference("user", {
264
- type: "one",
265
- from: { table: "posts", column: "userId" },
266
- to: { table: "users", column: "id" },
267
- }),
268
- );
269
-
270
- const uow = new UnitOfWork(
271
- testSchema,
272
- createMockCompiler(),
273
- createMockExecutor(),
274
- createMockDecoder(),
275
- );
276
-
277
- uow.find("posts", (b) =>
278
- b.whereIndex("primary").join((jb) => jb["user"]((builder) => builder.select(["name"]))),
279
- );
280
-
281
- const ops = uow.getRetrievalOperations();
282
- expect(ops).toHaveLength(1);
283
- const op = ops[0];
284
- assert(op.type === "find");
285
- expect(op.options.joins).toBeDefined();
286
- expect(op.options.joins).toHaveLength(1);
287
- });
288
-
289
- it("should support join operations without builder function", () => {
290
- const testSchema = schema((s) =>
291
- s
292
- .addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string"))
293
- .addTable("posts", (t) =>
294
- t
295
- .addColumn("id", idColumn())
296
- .addColumn("userId", column("string"))
297
- .addColumn("title", "string")
298
- .createIndex("idx_user", ["userId"]),
299
- )
300
- .addReference("user", {
301
- type: "one",
302
- from: { table: "posts", column: "userId" },
303
- to: { table: "users", column: "id" },
304
- }),
305
- );
306
-
307
- const uow = new UnitOfWork(
308
- testSchema,
309
- createMockCompiler(),
310
- createMockExecutor(),
311
- createMockDecoder(),
312
- );
313
-
314
- // Join without builder function should use default options
315
- uow.find("posts", (b) => b.whereIndex("primary").join((jb) => jb.user()));
316
-
317
- const ops = uow.getRetrievalOperations();
318
- expect(ops).toHaveLength(1);
319
- const op = ops[0];
320
- assert(op.type === "find");
321
- expect(op.options.joins).toBeDefined();
322
- expect(op.options.joins).toHaveLength(1);
323
- const joinOptions = op.options.joins![0]!.options;
324
- assert(joinOptions !== false);
325
- expect(joinOptions.select).toBe(true); // Should default to selecting all columns
326
- });
327
-
328
- it("should support join with whereIndex", () => {
329
- const testSchema = schema((s) =>
330
- s
331
- .addTable("users", (t) =>
332
- t
333
- .addColumn("id", idColumn())
334
- .addColumn("name", "string")
335
- .createIndex("idx_name", ["name"]),
336
- )
337
- .addTable("posts", (t) =>
338
- t
339
- .addColumn("id", idColumn())
340
- .addColumn("userId", column("string"))
341
- .addColumn("title", "string")
342
- .createIndex("idx_user", ["userId"]),
343
- )
344
- .addReference("user", {
345
- type: "one",
346
- from: { table: "posts", column: "userId" },
347
- to: { table: "users", column: "id" },
348
- }),
349
- );
350
-
351
- const uow = new UnitOfWork(
352
- testSchema,
353
- createMockCompiler(),
354
- createMockExecutor(),
355
- createMockDecoder(),
356
- );
357
-
358
- uow.find("posts", (b) =>
359
- b
360
- .whereIndex("primary")
361
- .join((jb) =>
362
- jb["user"]((builder) =>
363
- builder.whereIndex("idx_name", (eb) => eb("name", "=", "Alice")).select(["name"]),
364
- ),
365
- ),
366
- );
367
-
368
- const ops = uow.getRetrievalOperations();
369
- expect(ops).toHaveLength(1);
370
- const op = ops[0];
371
- assert(op.type === "find");
372
- expect(op.options.joins).toBeDefined();
373
- expect(op.options.joins).toHaveLength(1);
374
- const joinOptions = op.options.joins![0]!.options;
375
- assert(joinOptions !== false);
376
- expect(joinOptions.where).toBeDefined();
377
- });
378
-
379
- it("should support join with orderByIndex", () => {
380
- const testSchema = schema((s) =>
381
- s
382
- .addTable("users", (t) =>
383
- t
384
- .addColumn("id", idColumn())
385
- .addColumn("name", "string")
386
- .addColumn("createdAt", "integer")
387
- .createIndex("idx_created", ["createdAt"]),
388
- )
389
- .addTable("posts", (t) =>
390
- t
391
- .addColumn("id", idColumn())
392
- .addColumn("userId", column("string"))
393
- .addColumn("title", "string")
394
- .createIndex("idx_user", ["userId"]),
395
- )
396
- .addReference("user", {
397
- type: "one",
398
- from: { table: "posts", column: "userId" },
399
- to: { table: "users", column: "id" },
400
- }),
401
- );
402
-
403
- const uow = new UnitOfWork(
404
- testSchema,
405
- createMockCompiler(),
406
- createMockExecutor(),
407
- createMockDecoder(),
408
- );
409
-
410
- uow.find("posts", (b) =>
411
- b
412
- .whereIndex("primary")
413
- .join((jb) => jb["user"]((builder) => builder.orderByIndex("idx_created", "desc"))),
414
- );
415
-
416
- const ops = uow.getRetrievalOperations();
417
- expect(ops).toHaveLength(1);
418
- const op = ops[0];
419
- assert(op.type === "find");
420
- expect(op.options.joins).toBeDefined();
421
- const joinOptions = op.options.joins![0]!.options;
422
- assert(joinOptions !== false);
423
- expect(joinOptions.orderBy).toBeDefined();
424
- expect(joinOptions.orderBy).toHaveLength(1);
425
- });
426
-
427
- it("should support join with pageSize", () => {
428
- const testSchema = schema((s) =>
429
- s
430
- .addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string"))
431
- .addTable("posts", (t) =>
432
- t
433
- .addColumn("id", idColumn())
434
- .addColumn("userId", column("string"))
435
- .addColumn("title", "string")
436
- .createIndex("idx_user", ["userId"]),
437
- )
438
- .addReference("user", {
439
- type: "one",
440
- from: { table: "posts", column: "userId" },
441
- to: { table: "users", column: "id" },
442
- }),
443
- );
444
-
445
- const uow = new UnitOfWork(
446
- testSchema,
447
- createMockCompiler(),
448
- createMockExecutor(),
449
- createMockDecoder(),
450
- );
451
-
452
- uow.find("posts", (b) =>
453
- b.whereIndex("primary").join((jb) => jb["user"]((builder) => builder.pageSize(5))),
454
- );
455
-
456
- const ops = uow.getRetrievalOperations();
457
- expect(ops).toHaveLength(1);
458
- const op = ops[0];
459
- assert(op.type === "find");
460
- const joinOptions = op.options.joins![0]!.options;
461
- assert(joinOptions !== false);
462
- expect(joinOptions.limit).toBe(5);
463
- });
464
-
465
- it("should support nested joins", () => {
466
- const testSchema = schema((s) =>
467
- s
468
- .addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string"))
469
- .addTable("posts", (t) =>
470
- t
471
- .addColumn("id", idColumn())
472
- .addColumn("userId", column("string"))
473
- .addColumn("authorId", column("string"))
474
- .addColumn("title", "string")
475
- .createIndex("idx_user", ["userId"])
476
- .createIndex("idx_author", ["authorId"]),
477
- )
478
- .addTable("comments", (t) =>
479
- t
480
- .addColumn("id", idColumn())
481
- .addColumn("postId", column("string"))
482
- .addColumn("text", "string")
483
- .createIndex("idx_post", ["postId"]),
484
- )
485
- .addReference("user", {
486
- type: "one",
487
- from: { table: "posts", column: "userId" },
488
- to: { table: "users", column: "id" },
489
- })
490
- .addReference("post", {
491
- type: "one",
492
- from: { table: "comments", column: "postId" },
493
- to: { table: "posts", column: "id" },
494
- }),
495
- );
496
-
497
- const uow = new UnitOfWork(
498
- testSchema,
499
- createMockCompiler(),
500
- createMockExecutor(),
501
- createMockDecoder(),
502
- );
503
-
504
- uow.find("comments", (b) =>
505
- b
506
- .whereIndex("primary")
507
- .join((jb) =>
508
- jb["post"]((postBuilder) =>
509
- postBuilder
510
- .select(["title"])
511
- .join((jb2) => jb2["user"]((userBuilder) => userBuilder.select(["name"]))),
512
- ),
513
- ),
514
- );
515
-
516
- const ops = uow.getRetrievalOperations();
517
- expect(ops).toHaveLength(1);
518
- const op = ops[0];
519
- assert(op.type === "find");
520
- expect(op.options.joins).toBeDefined();
521
- expect(op.options.joins).toHaveLength(1);
522
-
523
- const postJoin = op.options.joins![0]!;
524
- assert(postJoin.options !== false);
525
- expect(postJoin.options.join).toBeDefined();
526
- expect(postJoin.options.join).toHaveLength(1);
527
-
528
- const userJoin = postJoin.options.join![0]!;
529
- assert(userJoin.options !== false);
530
- expect(userJoin.relation.name).toBe("user");
531
- });
532
- });
533
-
534
- describe("IndexedConditionBuilder", () => {
535
- const testSchema = schema((s) =>
536
- s.addTable("users", (t) =>
537
- t
538
- .addColumn("id", idColumn())
539
- .addColumn("email", column("string"))
540
- .addColumn("name", column("string"))
541
- .addColumn("age", column("integer").nullable())
542
- .addColumn("bio", column("string").nullable()) // Not indexed
543
- .createIndex("_primary", ["id"], { unique: true })
544
- .createIndex("idx_email", ["email"], { unique: true })
545
- .createIndex("idx_name_age", ["name", "age"]),
546
- ),
547
- );
548
-
549
- const usersTable = testSchema.tables.users;
550
-
551
- it("should enforce indexed columns at runtime", () => {
552
- // Collect all indexed column names from all indexes
553
- const indexedColumns = new Set<string>();
554
- for (const index of Object.values(usersTable.indexes)) {
555
- for (const col of index.columns) {
556
- indexedColumns.add(col.ormName);
557
- }
558
- }
559
-
560
- const builder = createIndexedBuilder(usersTable.columns, indexedColumns);
561
-
562
- // Should work with indexed columns
563
- expect(() => builder("id", "=", "123")).not.toThrow();
564
- expect(() => builder("email", "=", "test@example.com")).not.toThrow();
565
- expect(() => builder("name", "=", "Alice")).not.toThrow();
566
- expect(() => builder("age", ">", 18)).not.toThrow();
567
-
568
- // Should throw when using non-indexed column
569
- expect(() => builder("bio" as "email", "=", "Some bio")).toThrow('Column "bio" is not indexed');
570
- });
571
-
572
- it("should work with complex conditions", () => {
573
- const indexedColumns = new Set(["id", "email", "name", "age"]);
574
- const builder = createIndexedBuilder(usersTable.columns, indexedColumns);
575
-
576
- // Complex AND condition with indexed columns
577
- const condition = builder.and(
578
- builder("name", "=", "Alice"),
579
- builder("age", ">", 18),
580
- builder("email", "contains", "example"),
581
- );
582
-
583
- expect(condition).toEqual({
584
- type: "and",
585
- items: [
586
- {
587
- type: "compare",
588
- a: usersTable.columns.name,
589
- operator: "=",
590
- b: "Alice",
591
- },
592
- {
593
- type: "compare",
594
- a: usersTable.columns.age,
595
- operator: ">",
596
- b: 18,
597
- },
598
- {
599
- type: "compare",
600
- a: usersTable.columns.email,
601
- operator: "contains",
602
- b: "example",
603
- },
604
- ],
605
- });
606
- });
607
-
608
- it("should provide helpful error message listing available columns", () => {
609
- const indexedColumns = new Set(["id", "email"]);
610
- const builder = createIndexedBuilder(usersTable.columns, indexedColumns);
611
-
612
- expect(() => builder("name" as "email", "=", "Alice")).toThrow(
613
- "Only indexed columns can be used in Unit of Work queries. Available indexed columns: id, email",
614
- );
615
- });
616
-
617
- it("should work with all builder helper methods", () => {
618
- const indexedColumns = new Set(["id", "email", "age"]);
619
- const builder = createIndexedBuilder(usersTable.columns, indexedColumns);
620
-
621
- // isNull
622
- expect(() => builder.isNull("age")).not.toThrow();
623
- expect(() => builder.isNull("bio" as "age")).toThrow('Column "bio" is not indexed');
624
-
625
- // isNotNull
626
- expect(() => builder.isNotNull("email")).not.toThrow();
627
- expect(() => builder.isNotNull("bio" as "email")).toThrow('Column "bio" is not indexed');
628
-
629
- // not
630
- const notCondition = builder.not(builder("id", "=", "123"));
631
- expect(notCondition).toEqual({
632
- type: "not",
633
- item: {
634
- type: "compare",
635
- a: usersTable.columns.id,
636
- operator: "=",
637
- b: "123",
638
- },
639
- });
640
-
641
- // or
642
- const orCondition = builder.or(builder("email", "contains", "gmail"), builder("age", ">", 30));
643
- expect(orCondition).toEqual({
644
- type: "or",
645
- items: [
646
- {
647
- type: "compare",
648
- a: usersTable.columns.email,
649
- operator: "contains",
650
- b: "gmail",
651
- },
652
- {
653
- type: "compare",
654
- a: usersTable.columns.age,
655
- operator: ">",
656
- b: 30,
657
- },
658
- ],
659
- });
660
- });
661
-
662
- it("should enforce index restrictions in nested conditions", () => {
663
- const indexedColumns = new Set(["id", "email"]);
664
- const builder = createIndexedBuilder(usersTable.columns, indexedColumns);
665
-
666
- // This should throw because "name" is not indexed, even though it's nested
667
- expect(() => {
668
- builder.and(
669
- builder("email", "=", "test@example.com"),
670
- builder("name" as "email", "=", "Alice"),
671
- );
672
- }).toThrow('Column "name" is not indexed');
673
-
674
- // This should throw because "bio" is not indexed, even in OR
675
- expect(() => {
676
- builder.or(builder("id", "=", "123"), builder("bio" as "id", "=", "Some bio"));
677
- }).toThrow('Column "bio" is not indexed');
678
- });
679
-
680
- describe("type safety", () => {
681
- it("should restrict to only indexed columns at type level", () => {
682
- // This schema has "bio" column that is NOT indexed
683
- const typeTestSchema = schema((s) =>
684
- s.addTable("users", (t) =>
685
- t
686
- .addColumn("id", idColumn())
687
- .addColumn("email", column("string"))
688
- .addColumn("name", column("string"))
689
- .addColumn("age", column("integer").nullable())
690
- .addColumn("bio", column("string").nullable()) // Not indexed!
691
- .createIndex("idx_email", ["email"], { unique: true })
692
- .createIndex("idx_name_age", ["name", "age"]),
693
- ),
694
- );
695
-
696
- type _IdColumnName = InferIdColumnName<typeof typeTestSchema.tables.users>;
697
- expectTypeOf<_IdColumnName>().toEqualTypeOf<"id">();
698
- type _IndexColumnNames = IndexColumns<
699
- typeof typeTestSchema.tables.users.indexes.idx_name_age
700
- >;
701
- expectTypeOf<_IndexColumnNames>().toEqualTypeOf<"name" | "age">();
702
-
703
- const uow = createUnitOfWork(
704
- typeTestSchema,
705
- createMockCompiler(),
706
- createMockExecutor(),
707
- createMockDecoder(),
708
- );
709
- expectTypeOf(uow.schema).toEqualTypeOf(typeTestSchema);
710
- expectTypeOf<keyof typeof typeTestSchema.tables>().toEqualTypeOf<"users">();
711
- type _Query = AbstractQuery<typeof typeTestSchema>;
712
- expectTypeOf<Parameters<_Query["create"]>[0]>().toEqualTypeOf<"users">();
713
-
714
- expectTypeOf<Parameters<typeof uow.find>[0]>().toEqualTypeOf<"users">();
715
-
716
- uow.find("users", (b) =>
717
- b.whereIndex("primary", (eb) => {
718
- type _EbFirstParameter = Parameters<typeof eb>[0];
719
- expectTypeOf<_EbFirstParameter>().toEqualTypeOf<"id">();
720
- return eb("id", "=", "123");
721
- }),
722
- );
723
-
724
- uow.find("users", (b) =>
725
- b.whereIndex("idx_email", (eb) => {
726
- expectTypeOf(eb).parameter(0).toEqualTypeOf<"email">();
727
- return eb("email", "=", "123");
728
- }),
729
- );
730
-
731
- uow.find("users", (b) =>
732
- b.whereIndex("idx_name_age", (eb) => {
733
- expectTypeOf(eb).parameter(0).toEqualTypeOf<"name" | "age">();
734
- return eb("name", "=", "123");
735
- }),
736
- );
737
- });
738
- });
739
- });
740
-
741
- describe("UpdateBuilder with string ID", () => {
742
- const testSchema = schema((s) =>
743
- s.addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string")),
744
- );
745
-
746
- it("should allow update with string ID", async () => {
747
- const uow = new UnitOfWork(
748
- testSchema,
749
- createMockCompiler(),
750
- createMockExecutor(),
751
- createMockDecoder(),
752
- );
753
-
754
- // Should work with string ID
755
- uow.update("users", "user-123", (b) => b.set({ name: "New Name" }));
756
-
757
- const ops = uow.getMutationOperations();
758
- expect(ops).toHaveLength(1);
759
- expect(ops).toMatchObject([
760
- {
761
- type: "update",
762
- id: "user-123",
763
- checkVersion: false,
764
- },
765
- ]);
766
- });
767
-
768
- it("should throw when using check() with string ID", async () => {
769
- const uow = new UnitOfWork(
770
- testSchema,
771
- createMockCompiler(),
772
- createMockExecutor(),
773
- createMockDecoder(),
774
- );
775
-
776
- // Should throw because check() is not allowed with string ID
777
- expect(() => {
778
- uow.update("users", "user-123", (b) => b.set({ name: "New Name" }).check());
779
- }).toThrow(
780
- 'Cannot use check() with a string ID on table "users". Version checking requires a FragnoId with version information.',
781
- );
782
- });
783
- });
784
-
785
- describe("DeleteBuilder with string ID", () => {
786
- const testSchema = schema((s) =>
787
- s.addTable("users", (t) => t.addColumn("id", idColumn()).addColumn("name", "string")),
788
- );
789
-
790
- it("should allow delete with string ID", async () => {
791
- const uow = new UnitOfWork(
792
- testSchema,
793
- createMockCompiler(),
794
- createMockExecutor(),
795
- createMockDecoder(),
796
- );
797
-
798
- // Should work with string ID
799
- uow.delete("users", "user-123");
800
-
801
- const ops = uow.getMutationOperations();
802
- expect(ops).toMatchObject([
803
- {
804
- type: "delete",
805
- id: "user-123",
806
- checkVersion: false,
807
- },
808
- ]);
809
- });
810
-
811
- it("should throw when using check() with string ID", async () => {
812
- const uow = new UnitOfWork(
813
- testSchema,
814
- createMockCompiler(),
815
- createMockExecutor(),
816
- createMockDecoder(),
817
- );
818
-
819
- // Should throw because check() is not allowed with string ID
820
- expect(() => {
821
- uow.delete("users", "user-123", (b) => b.check());
822
- }).toThrow(
823
- 'Cannot use check() with a string ID on table "users". Version checking requires a FragnoId with version information.',
824
- );
825
- });
826
- });
827
-
828
- describe("getCreatedIds", () => {
829
- const testSchema = schema((s) =>
830
- s.addTable("users", (t) =>
831
- t.addColumn("id", idColumn()).addColumn("email", "string").addColumn("name", "string"),
832
- ),
833
- );
834
-
835
- it("should return created IDs after executeMutations with internal IDs", async () => {
836
- const executor = {
837
- executeRetrievalPhase: async () => [],
838
- executeMutationPhase: async () => ({
839
- success: true,
840
- createdInternalIds: [1n, 2n],
841
- }),
842
- };
843
-
844
- const uow = new UnitOfWork(testSchema, createMockCompiler(), executor, createMockDecoder());
845
-
846
- uow.create("users", { email: "user1@example.com", name: "User 1" });
847
- uow.create("users", { email: "user2@example.com", name: "User 2" });
848
-
849
- await uow.executeMutations();
850
- const createdIds = uow.getCreatedIds();
851
-
852
- expect(createdIds).toHaveLength(2);
853
- expect(createdIds[0].externalId).toBeDefined();
854
- expect(createdIds[0].internalId).toBe(1n);
855
- expect(createdIds[0].version).toBe(0);
856
- expect(createdIds[1].externalId).toBeDefined();
857
- expect(createdIds[1].internalId).toBe(2n);
858
- expect(createdIds[1].version).toBe(0);
859
- });
860
-
861
- it("should return created IDs without internal IDs when not supported", async () => {
862
- const executor = {
863
- executeRetrievalPhase: async () => [],
864
- executeMutationPhase: async () => ({
865
- success: true,
866
- createdInternalIds: [null, null],
867
- }),
868
- };
869
-
870
- const uow = new UnitOfWork(testSchema, createMockCompiler(), executor, createMockDecoder());
871
-
872
- uow.create("users", { email: "user1@example.com", name: "User 1" });
873
- uow.create("users", { email: "user2@example.com", name: "User 2" });
874
-
875
- await uow.executeMutations();
876
- const createdIds = uow.getCreatedIds();
877
-
878
- expect(createdIds).toHaveLength(2);
879
- expect(createdIds[0].externalId).toBeDefined();
880
- expect(createdIds[0].internalId).toBeUndefined();
881
- expect(createdIds[1].externalId).toBeDefined();
882
- expect(createdIds[1].internalId).toBeUndefined();
883
- });
884
-
885
- it("should preserve user-provided external IDs", async () => {
886
- const executor = {
887
- executeRetrievalPhase: async () => [],
888
- executeMutationPhase: async () => ({
889
- success: true,
890
- createdInternalIds: [1n],
891
- }),
892
- };
893
-
894
- const uow = new UnitOfWork(testSchema, createMockCompiler(), executor, createMockDecoder());
895
-
896
- uow.create("users", { id: "my-custom-id", email: "user@example.com", name: "User" });
897
-
898
- await uow.executeMutations();
899
- const createdIds = uow.getCreatedIds();
900
-
901
- expect(createdIds).toHaveLength(1);
902
- expect(createdIds[0].externalId).toBe("my-custom-id");
903
- expect(createdIds[0].internalId).toBe(1n);
904
- });
905
-
906
- it("should only return IDs for create operations, not updates or deletes", async () => {
907
- const executor = {
908
- executeRetrievalPhase: async () => [],
909
- executeMutationPhase: async () => ({
910
- success: true,
911
- createdInternalIds: [1n],
912
- }),
913
- };
914
-
915
- const uow = new UnitOfWork(testSchema, createMockCompiler(), executor, createMockDecoder());
916
-
917
- uow.create("users", { email: "user@example.com", name: "User" });
918
- uow.update("users", "existing-id", (b) => b.set({ name: "Updated" }));
919
- uow.delete("users", "other-id");
920
-
921
- await uow.executeMutations();
922
- const createdIds = uow.getCreatedIds();
923
-
924
- // Only one create operation, so only one ID returned
925
- expect(createdIds).toHaveLength(1);
926
- expect(createdIds[0].internalId).toBe(1n);
927
- });
928
-
929
- it("should throw when called before executeMutations", () => {
930
- const uow = new UnitOfWork(
931
- testSchema,
932
- createMockCompiler(),
933
- createMockExecutor(),
934
- createMockDecoder(),
935
- );
936
-
937
- uow.create("users", { email: "user@example.com", name: "User" });
938
-
939
- expect(() => uow.getCreatedIds()).toThrow(
940
- "getCreatedIds() can only be called after executeMutations()",
941
- );
942
- });
943
- });