@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,268 +1,11 @@
1
1
  import { assert, describe, expect, it } from "vitest";
2
2
  import { column, idColumn, referenceColumn, schema, FragnoId } from "../schema/create";
3
- import { decodeResult, encodeValues, ReferenceSubquery } from "./result-transform";
4
-
5
- describe("encodeValues", () => {
6
- const testSchema = schema((s) => {
7
- return s
8
- .addTable("users", (t) => {
9
- return t
10
- .addColumn("id", idColumn())
11
- .addColumn("name", column("string"))
12
- .addColumn("email", column("string"))
13
- .addColumn("age", column("integer").nullable())
14
- .addColumn("isActive", column("bool"))
15
- .addColumn("createdAt", column("timestamp"));
16
- })
17
- .addTable("posts", (t) => {
18
- return t
19
- .addColumn("id", idColumn())
20
- .addColumn("title", column("string"))
21
- .addColumn("userId", referenceColumn())
22
- .addColumn("viewCount", column("integer").defaultTo(0))
23
- .addColumn("publishedAt", column("timestamp").nullable());
24
- })
25
- .addReference("author", {
26
- type: "one",
27
- from: { table: "posts", column: "userId" },
28
- to: { table: "users", column: "id" },
29
- });
30
- });
31
-
32
- const usersTable = testSchema.tables.users;
33
- const postsTable = testSchema.tables.posts;
34
-
35
- describe("basic encoding", () => {
36
- it("should encode string values", () => {
37
- const result = encodeValues(
38
- { id: "user1", name: "John", email: "john@example.com" },
39
- usersTable,
40
- false,
41
- "sqlite",
42
- );
43
-
44
- expect(result).toEqual({
45
- id: "user1",
46
- name: "John",
47
- email: "john@example.com",
48
- });
49
- });
50
-
51
- it("should encode integer values", () => {
52
- const result = encodeValues({ age: 25 }, usersTable, false, "sqlite");
53
-
54
- expect(result).toEqual({ age: 25 });
55
- });
56
-
57
- it("should encode boolean values for sqlite", () => {
58
- const result = encodeValues({ isActive: true }, usersTable, false, "sqlite");
59
-
60
- expect(result).toEqual({ isActive: 1 });
61
- });
62
-
63
- it("should encode boolean values for postgresql", () => {
64
- const result = encodeValues({ isActive: true }, usersTable, false, "postgresql");
65
-
66
- expect(result).toEqual({ isActive: true });
67
- });
68
- });
69
-
70
- describe("date encoding", () => {
71
- it("should encode Date to number for sqlite", () => {
72
- const date = new Date("2024-01-15T10:30:00Z");
73
- const result = encodeValues({ createdAt: date }, usersTable, false, "sqlite");
74
-
75
- expect(result).toEqual({ createdAt: date.getTime() });
76
- });
77
-
78
- it("should keep Date as Date for postgresql", () => {
79
- const date = new Date("2024-01-15T10:30:00Z");
80
- const result = encodeValues({ createdAt: date }, usersTable, false, "postgresql");
81
-
82
- expect(result).toEqual({ createdAt: date });
83
- });
84
-
85
- it("should keep Date as Date for mysql", () => {
86
- const date = new Date("2024-01-15T10:30:00Z");
87
- const result = encodeValues({ createdAt: date }, usersTable, false, "mysql");
88
-
89
- expect(result).toEqual({ createdAt: date });
90
- });
91
- });
92
-
93
- describe("nullable columns", () => {
94
- it("should handle null values", () => {
95
- const result = encodeValues({ age: null }, usersTable, false, "sqlite");
96
-
97
- expect(result).toEqual({ age: null });
98
- });
99
-
100
- it("should omit undefined values", () => {
101
- const result = encodeValues({ age: undefined }, usersTable, false, "sqlite");
102
-
103
- expect(result).toEqual({});
104
- });
105
-
106
- it("should handle nullable timestamp", () => {
107
- const result = encodeValues({ publishedAt: null }, postsTable, false, "sqlite");
108
-
109
- expect(result).toEqual({ publishedAt: null });
110
- });
111
- });
112
-
113
- describe("default value generation", () => {
114
- it("should generate runtime defaults when generateDefault is true", () => {
115
- const result = encodeValues(
116
- { title: "Test Post", userId: "user1" },
117
- postsTable,
118
- true,
119
- "sqlite",
120
- );
121
-
122
- expect(result["title"]).toBe("Test Post");
123
- expect(result["userId"]).instanceOf(ReferenceSubquery);
124
- // viewCount has static default (defaultTo), so it's omitted to let DB handle it
125
- expect(result["viewCount"]).toBeUndefined();
126
- expect(result["id"]).toBeDefined();
127
- expect(typeof result["id"]).toBe("string");
128
- });
129
-
130
- it("should not generate default values when generateDefault is false", () => {
131
- const result = encodeValues(
132
- { title: "Test Post", userId: "user1" },
133
- postsTable,
134
- false,
135
- "sqlite",
136
- );
137
-
138
- expect(result).toEqual({
139
- title: "Test Post",
140
- userId: expect.any(ReferenceSubquery),
141
- });
142
- });
143
-
144
- it("should not override explicitly provided values", () => {
145
- const result = encodeValues(
146
- { title: "Test Post", userId: "user1", viewCount: 100 },
147
- postsTable,
148
- true,
149
- "sqlite",
150
- );
151
-
152
- expect(result["viewCount"]).toBe(100);
153
- });
154
- });
155
-
156
- describe("complete record encoding", () => {
157
- it("should encode all fields correctly", () => {
158
- const date = new Date("2024-01-15T10:30:00Z");
159
- const result = encodeValues(
160
- {
161
- id: "user1",
162
- name: "Alice",
163
- email: "alice@example.com",
164
- age: 30,
165
- isActive: false,
166
- createdAt: date,
167
- },
168
- usersTable,
169
- false,
170
- "sqlite",
171
- );
172
-
173
- expect(result).toEqual({
174
- id: "user1",
175
- name: "Alice",
176
- email: "alice@example.com",
177
- age: 30,
178
- isActive: 0,
179
- createdAt: date.getTime(),
180
- });
181
- });
182
- });
183
-
184
- describe("FragnoId encoding", () => {
185
- it("should encode FragnoId with external ID only", () => {
186
- const fragnoId = FragnoId.fromExternal("user123", 1);
187
- const result = encodeValues({ id: fragnoId, name: "John" }, usersTable, false, "postgresql");
188
-
189
- expect(result).toEqual({
190
- id: "user123",
191
- name: "John",
192
- });
193
- });
194
-
195
- it("should encode FragnoId with both IDs", () => {
196
- const fragnoId = new FragnoId({
197
- externalId: "user123",
198
- internalId: BigInt(456),
199
- version: 1,
200
- });
201
- const result = encodeValues({ id: fragnoId, name: "John" }, usersTable, false, "postgresql");
202
-
203
- expect(result).toEqual({
204
- id: "user123",
205
- name: "John",
206
- });
207
- });
208
-
209
- it("should encode FragnoId in reference columns", () => {
210
- const fragnoId = new FragnoId({
211
- externalId: "user123",
212
- internalId: BigInt(456),
213
- version: 1,
214
- });
215
- const result = encodeValues(
216
- { title: "Test Post", userId: fragnoId },
217
- postsTable,
218
- false,
219
- "postgresql",
220
- );
221
-
222
- // Reference columns should use the internal ID (bigint)
223
- expect(result).toEqual({
224
- title: "Test Post",
225
- userId: BigInt(456),
226
- });
227
- });
228
-
229
- it("should convert FragnoId without internalId to ReferenceSubquery for reference columns", () => {
230
- const fragnoId = new FragnoId({
231
- externalId: "user123",
232
- version: 1,
233
- });
234
- const result = encodeValues(
235
- { title: "Test Post", userId: fragnoId },
236
- postsTable,
237
- false,
238
- "postgresql",
239
- );
240
-
241
- // FragnoId without internalId should be converted to ReferenceSubquery for database lookup
242
- expect(result["title"]).toBe("Test Post");
243
- expect(result["userId"]).toBeInstanceOf(ReferenceSubquery);
244
- expect((result["userId"] as ReferenceSubquery).externalIdValue).toBe("user123");
245
- });
246
-
247
- it("should handle FragnoId across different providers", () => {
248
- const fragnoId = new FragnoId({
249
- externalId: "user123",
250
- internalId: BigInt(456),
251
- version: 1,
252
- });
253
- const testData = { id: fragnoId, name: "John" };
254
-
255
- // Test across providers
256
- const sqliteResult = encodeValues(testData, usersTable, false, "sqlite");
257
- const postgresqlResult = encodeValues(testData, usersTable, false, "postgresql");
258
- const mysqlResult = encodeValues(testData, usersTable, false, "mysql");
259
-
260
- expect(sqliteResult).toEqual({ id: "user123", name: "John" });
261
- expect(postgresqlResult).toEqual({ id: "user123", name: "John" });
262
- expect(mysqlResult).toEqual({ id: "user123", name: "John" });
263
- });
264
- });
265
- });
3
+ import { decodeResult } from "./value-decoding";
4
+ import {
5
+ SQLocalDriverConfig,
6
+ NodePostgresDriverConfig,
7
+ MySQL2DriverConfig,
8
+ } from "../adapters/generic-sql/driver-config";
266
9
 
267
10
  describe("decodeResult", () => {
268
11
  const testSchema = schema((s) => {
@@ -295,12 +38,16 @@ describe("decodeResult", () => {
295
38
  const usersTable = testSchema.tables.users;
296
39
  const postsTable = testSchema.tables.posts;
297
40
 
41
+ const sqliteConfig = new SQLocalDriverConfig();
42
+ const postgresqlConfig = new NodePostgresDriverConfig();
43
+ const mysqlConfig = new MySQL2DriverConfig();
44
+
298
45
  describe("basic decoding", () => {
299
46
  it("should decode string values", () => {
300
47
  const result = decodeResult(
301
48
  { id: "user1", name: "John", email: "john@example.com" },
302
49
  usersTable,
303
- "sqlite",
50
+ sqliteConfig,
304
51
  );
305
52
 
306
53
  expect(result).toEqual({
@@ -311,25 +58,25 @@ describe("decodeResult", () => {
311
58
  });
312
59
 
313
60
  it("should decode integer values", () => {
314
- const result = decodeResult({ age: 25 }, usersTable, "sqlite");
61
+ const result = decodeResult({ age: 25 }, usersTable, sqliteConfig);
315
62
 
316
63
  expect(result).toEqual({ age: 25 });
317
64
  });
318
65
 
319
66
  it("should decode boolean values from sqlite", () => {
320
- const result = decodeResult({ isActive: 1 }, usersTable, "sqlite");
67
+ const result = decodeResult({ isActive: 1 }, usersTable, sqliteConfig);
321
68
 
322
69
  expect(result).toEqual({ isActive: true });
323
70
  });
324
71
 
325
72
  it("should decode boolean false from sqlite", () => {
326
- const result = decodeResult({ isActive: 0 }, usersTable, "sqlite");
73
+ const result = decodeResult({ isActive: 0 }, usersTable, sqliteConfig);
327
74
 
328
75
  expect(result).toEqual({ isActive: false });
329
76
  });
330
77
 
331
78
  it("should decode boolean values from postgresql", () => {
332
- const result = decodeResult({ isActive: true }, usersTable, "postgresql");
79
+ const result = decodeResult({ isActive: true }, usersTable, postgresqlConfig);
333
80
 
334
81
  expect(result).toEqual({ isActive: true });
335
82
  });
@@ -338,7 +85,7 @@ describe("decodeResult", () => {
338
85
  describe("date decoding", () => {
339
86
  it("should decode number to Date for sqlite timestamp", () => {
340
87
  const timestamp = 1705317000000;
341
- const result = decodeResult({ createdAt: timestamp }, usersTable, "sqlite");
88
+ const result = decodeResult({ createdAt: timestamp }, usersTable, sqliteConfig);
342
89
 
343
90
  expect(result["createdAt"]).toBeInstanceOf(Date);
344
91
  expect((result["createdAt"] as Date).getTime()).toBe(timestamp);
@@ -346,7 +93,7 @@ describe("decodeResult", () => {
346
93
 
347
94
  it("should decode ISO string to Date for sqlite timestamp", () => {
348
95
  const isoString = "2024-01-15T10:30:00.000Z";
349
- const result = decodeResult({ createdAt: isoString }, usersTable, "sqlite");
96
+ const result = decodeResult({ createdAt: isoString }, usersTable, sqliteConfig);
350
97
 
351
98
  expect(result["createdAt"]).toBeInstanceOf(Date);
352
99
  expect((result["createdAt"] as Date).toISOString()).toBe(isoString);
@@ -354,7 +101,7 @@ describe("decodeResult", () => {
354
101
 
355
102
  it("should keep Date as Date for postgresql", () => {
356
103
  const date = new Date("2024-01-15T10:30:00Z");
357
- const result = decodeResult({ createdAt: date }, usersTable, "postgresql");
104
+ const result = decodeResult({ createdAt: date }, usersTable, postgresqlConfig);
358
105
 
359
106
  expect(result["createdAt"]).toBe(date);
360
107
  });
@@ -362,13 +109,13 @@ describe("decodeResult", () => {
362
109
 
363
110
  describe("nullable columns", () => {
364
111
  it("should handle null values", () => {
365
- const result = decodeResult({ age: null }, usersTable, "sqlite");
112
+ const result = decodeResult({ age: null }, usersTable, sqliteConfig);
366
113
 
367
114
  expect(result).toEqual({ age: null });
368
115
  });
369
116
 
370
117
  it("should handle nullable timestamp", () => {
371
- const result = decodeResult({ publishedAt: null }, postsTable, "sqlite");
118
+ const result = decodeResult({ publishedAt: null }, postsTable, sqliteConfig);
372
119
 
373
120
  expect(result).toEqual({ publishedAt: null });
374
121
  });
@@ -385,7 +132,7 @@ describe("decodeResult", () => {
385
132
  "author:email": "alice@example.com",
386
133
  },
387
134
  postsTable,
388
- "sqlite",
135
+ sqliteConfig,
389
136
  );
390
137
 
391
138
  expect(result).toEqual({
@@ -410,7 +157,7 @@ describe("decodeResult", () => {
410
157
  "author:createdAt": timestamp,
411
158
  },
412
159
  postsTable,
413
- "sqlite",
160
+ sqliteConfig,
414
161
  );
415
162
 
416
163
  expect(result["author"]).toEqual({
@@ -428,7 +175,7 @@ describe("decodeResult", () => {
428
175
  "unknownRelation:field": "value",
429
176
  },
430
177
  postsTable,
431
- "sqlite",
178
+ sqliteConfig,
432
179
  );
433
180
 
434
181
  expect(result).toEqual({
@@ -446,7 +193,7 @@ describe("decodeResult", () => {
446
193
  "author:unknownField": "value",
447
194
  },
448
195
  postsTable,
449
- "sqlite",
196
+ sqliteConfig,
450
197
  );
451
198
 
452
199
  expect(result).toEqual({
@@ -496,7 +243,7 @@ describe("decodeResult", () => {
496
243
  "category:name": "Technology",
497
244
  },
498
245
  schemaWithMultipleRelations.tables.posts,
499
- "sqlite",
246
+ sqliteConfig,
500
247
  );
501
248
 
502
249
  expect(result).toEqual({
@@ -526,7 +273,7 @@ describe("decodeResult", () => {
526
273
  "author:name": "Alice",
527
274
  },
528
275
  postsTable,
529
- "sqlite",
276
+ sqliteConfig,
530
277
  );
531
278
 
532
279
  // Main table id should be FragnoId
@@ -557,7 +304,7 @@ describe("decodeResult", () => {
557
304
  createdAt: timestamp,
558
305
  },
559
306
  usersTable,
560
- "sqlite",
307
+ sqliteConfig,
561
308
  );
562
309
 
563
310
  expect(result).toEqual({
@@ -573,7 +320,7 @@ describe("decodeResult", () => {
573
320
 
574
321
  describe("edge cases", () => {
575
322
  it("should handle empty result", () => {
576
- const result = decodeResult({}, usersTable, "sqlite");
323
+ const result = decodeResult({}, usersTable, sqliteConfig);
577
324
 
578
325
  expect(result).toEqual({});
579
326
  });
@@ -585,7 +332,7 @@ describe("decodeResult", () => {
585
332
  "author:name": "Alice",
586
333
  },
587
334
  postsTable,
588
- "sqlite",
335
+ sqliteConfig,
589
336
  );
590
337
 
591
338
  expect(result).toEqual({
@@ -608,7 +355,7 @@ describe("decodeResult", () => {
608
355
  "author:name": "Alice",
609
356
  },
610
357
  postsTable,
611
- "sqlite",
358
+ sqliteConfig,
612
359
  );
613
360
 
614
361
  expect(result).toEqual({
@@ -633,14 +380,14 @@ describe("decodeResult", () => {
633
380
  name: "John",
634
381
  },
635
382
  usersTable,
636
- "postgresql",
383
+ postgresqlConfig,
637
384
  );
638
385
 
639
386
  const fragnoId = result["id"];
640
387
  assert(fragnoId instanceof FragnoId);
641
388
 
642
389
  expect(fragnoId.externalId).toBe("user123");
643
- expect(fragnoId.internalId).toBe(456);
390
+ expect(fragnoId.internalId).toBe(456n);
644
391
  expect(result["name"]).toBe("John");
645
392
  });
646
393
 
@@ -652,7 +399,7 @@ describe("decodeResult", () => {
652
399
  name: "John",
653
400
  },
654
401
  usersTable,
655
- "postgresql",
402
+ postgresqlConfig,
656
403
  );
657
404
 
658
405
  const fragnoId = result["id"];
@@ -670,7 +417,7 @@ describe("decodeResult", () => {
670
417
  name: "John",
671
418
  },
672
419
  usersTable,
673
- "postgresql",
420
+ postgresqlConfig,
674
421
  );
675
422
 
676
423
  expect(result).toEqual({
@@ -688,9 +435,9 @@ describe("decodeResult", () => {
688
435
  };
689
436
 
690
437
  // Test across providers
691
- const sqliteResult = decodeResult(testData, usersTable, "sqlite");
692
- const postgresqlResult = decodeResult(testData, usersTable, "postgresql");
693
- const mysqlResult = decodeResult(testData, usersTable, "mysql");
438
+ const sqliteResult = decodeResult(testData, usersTable, sqliteConfig);
439
+ const postgresqlResult = decodeResult(testData, usersTable, postgresqlConfig);
440
+ const mysqlResult = decodeResult(testData, usersTable, mysqlConfig);
694
441
 
695
442
  // All should create FragnoId objects
696
443
  expect(sqliteResult["id"]).toBeInstanceOf(FragnoId);
@@ -698,7 +445,7 @@ describe("decodeResult", () => {
698
445
  expect(mysqlResult["id"]).toBeInstanceOf(FragnoId);
699
446
 
700
447
  expect((sqliteResult["id"] as FragnoId).externalId).toBe("user123");
701
- expect((sqliteResult["id"] as FragnoId).internalId).toBe(456);
448
+ expect((sqliteResult["id"] as FragnoId).internalId).toBe(456n);
702
449
  });
703
450
 
704
451
  it("should create FragnoId in relation data when both IDs present", () => {
@@ -712,7 +459,7 @@ describe("decodeResult", () => {
712
459
  "author:name": "Alice",
713
460
  },
714
461
  postsTable,
715
- "postgresql",
462
+ postgresqlConfig,
716
463
  );
717
464
 
718
465
  expect(result["id"]).toBe("post1");
@@ -721,7 +468,7 @@ describe("decodeResult", () => {
721
468
  const author: Record<string, unknown> = result["author"] as Record<string, unknown>;
722
469
  assert(author["id"] instanceof FragnoId);
723
470
  expect(author["id"].externalId).toBe("user123");
724
- expect(author["id"].internalId).toBe(456);
471
+ expect(author["id"].internalId).toBe(456n);
725
472
  expect(author["name"]).toBe("Alice");
726
473
  });
727
474
 
@@ -734,7 +481,7 @@ describe("decodeResult", () => {
734
481
  "author:name": "Alice",
735
482
  },
736
483
  postsTable,
737
- "postgresql",
484
+ postgresqlConfig,
738
485
  );
739
486
 
740
487
  expect(result).toEqual({
@@ -762,12 +509,12 @@ describe("decodeResult", () => {
762
509
  createdAt: timestamp,
763
510
  },
764
511
  usersTable,
765
- "sqlite",
512
+ sqliteConfig,
766
513
  );
767
514
 
768
515
  expect(result["id"]).toBeInstanceOf(FragnoId);
769
516
  expect((result["id"] as FragnoId).externalId).toBe("user123");
770
- expect((result["id"] as FragnoId).internalId).toBe(456);
517
+ expect((result["id"] as FragnoId).internalId).toBe(456n);
771
518
  expect(result["name"]).toBe("Alice");
772
519
  expect(result["email"]).toBe("alice@example.com");
773
520
  expect(result["age"]).toBe(30);
@@ -783,12 +530,12 @@ describe("decodeResult", () => {
783
530
  name: "John",
784
531
  },
785
532
  usersTable,
786
- "postgresql",
533
+ postgresqlConfig,
787
534
  );
788
535
 
789
536
  expect(result["id"]).toBeInstanceOf(FragnoId);
790
537
  expect((result["id"] as FragnoId).externalId).toBe("user123");
791
- expect((result["id"] as FragnoId).internalId).toBe(789);
538
+ expect((result["id"] as FragnoId).internalId).toBe(789n);
792
539
  expect(result["name"]).toBe("John");
793
540
  });
794
541
  });
@@ -0,0 +1,113 @@
1
+ import type { AnyTable } from "../schema/create";
2
+ import { createSQLSerializer } from "./serialize/create-sql-serializer";
3
+ import { FragnoId, FragnoReference } from "../schema/create";
4
+ import type { DriverConfig } from "../adapters/generic-sql/driver-config";
5
+
6
+ /**
7
+ * Decodes a database result record to application format.
8
+ *
9
+ * This function transforms database column names back to application property names
10
+ * and deserializes values according to the database provider's format (e.g., converting
11
+ * SQLite integers back to JavaScript Date objects).
12
+ *
13
+ * Supports relation data encoded with the pattern `relationName:columnName`.
14
+ *
15
+ * @param result - The raw database result record
16
+ * @param table - The table schema definition containing column and relation information
17
+ * @param driverConfig - The driver configuration containing database type information
18
+ * @returns A record in application format with deserialized values
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * const decoded = decodeResult(
23
+ * { user_id: 123, created_at: 1234567890, 'posts:title': 'Hello' },
24
+ * userTable,
25
+ * driverConfig
26
+ * );
27
+ * // Returns: { userId: 123, createdAt: Date, posts: { title: 'Hello' } }
28
+ * ```
29
+ */
30
+ export function decodeResult(
31
+ result: Record<string, unknown>,
32
+ table: AnyTable,
33
+ driverConfig: DriverConfig,
34
+ ): Record<string, unknown> {
35
+ const serializer = createSQLSerializer(driverConfig);
36
+ const output: Record<string, unknown> = {};
37
+ // First pass: collect all column values
38
+ const columnValues: Record<string, unknown> = {};
39
+
40
+ // Collect all relation data (including nested) keyed by relation name
41
+ const relationData: Record<string, Record<string, unknown>> = {};
42
+
43
+ for (const k in result) {
44
+ const colonIndex = k.indexOf(":");
45
+ const value = result[k];
46
+
47
+ // Direct column (no colon)
48
+ if (colonIndex === -1) {
49
+ const col = table.columns[k];
50
+ if (!col) {
51
+ continue;
52
+ }
53
+
54
+ // Store all column values (including hidden ones for FragnoId creation)
55
+ columnValues[k] = serializer.deserialize(value, col);
56
+ continue;
57
+ }
58
+
59
+ // Relation column (has colon)
60
+ const relationName = k.slice(0, colonIndex);
61
+ const remainder = k.slice(colonIndex + 1);
62
+
63
+ const relation = table.relations[relationName];
64
+ if (relation === undefined) {
65
+ continue;
66
+ }
67
+
68
+ // Collect relation data with the remaining key path
69
+ relationData[relationName] ??= {};
70
+ relationData[relationName][remainder] = value;
71
+ }
72
+
73
+ // Process each relation's data recursively
74
+ for (const relationName in relationData) {
75
+ const relation = table.relations[relationName];
76
+ if (!relation) {
77
+ continue;
78
+ }
79
+
80
+ // Recursively decode the relation data
81
+ output[relationName] = decodeResult(relationData[relationName], relation.table, driverConfig);
82
+ }
83
+
84
+ // Second pass: create output with FragnoId objects where appropriate
85
+ for (const k in columnValues) {
86
+ const col = table.columns[k];
87
+ if (!col) {
88
+ continue;
89
+ }
90
+
91
+ // Filter out hidden columns (like _internalId, _version) from results
92
+ if (col.isHidden) {
93
+ continue;
94
+ }
95
+
96
+ // For external ID columns, create FragnoId if we have both external and internal IDs
97
+ if (col.role === "external-id" && columnValues["_internalId"] !== undefined) {
98
+ output[k] = new FragnoId({
99
+ externalId: columnValues[k] as string,
100
+ internalId: columnValues["_internalId"] as bigint,
101
+ // _version is always selected as a hidden column, so it should always be present
102
+ version: columnValues["_version"] as number,
103
+ });
104
+ } else if (col.role === "reference") {
105
+ // For reference columns, create FragnoReference with internal ID
106
+ output[k] = FragnoReference.fromInternal(columnValues[k] as bigint);
107
+ } else {
108
+ output[k] = columnValues[k];
109
+ }
110
+ }
111
+
112
+ return output;
113
+ }