@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
@@ -0,0 +1,390 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ column,
4
+ FragnoId,
5
+ FragnoReference,
6
+ idColumn,
7
+ schema,
8
+ referenceColumn,
9
+ } from "../schema/create";
10
+ import { resolveFragnoIdValue, encodeValues, ReferenceSubquery } from "./value-encoding";
11
+
12
+ describe("encodeValues", () => {
13
+ const testSchema = schema((s) => {
14
+ return s
15
+ .addTable("users", (t) => {
16
+ return t
17
+ .addColumn("id", idColumn())
18
+ .addColumn("name", column("string"))
19
+ .addColumn("email", column("string"))
20
+ .addColumn("age", column("integer").nullable())
21
+ .addColumn("isActive", column("bool"))
22
+ .addColumn("createdAt", column("timestamp"));
23
+ })
24
+ .addTable("posts", (t) => {
25
+ return t
26
+ .addColumn("id", idColumn())
27
+ .addColumn("title", column("string"))
28
+ .addColumn("userId", referenceColumn())
29
+ .addColumn("viewCount", column("integer").defaultTo(0))
30
+ .addColumn("publishedAt", column("timestamp").nullable());
31
+ })
32
+ .addReference("author", {
33
+ type: "one",
34
+ from: { table: "posts", column: "userId" },
35
+ to: { table: "users", column: "id" },
36
+ });
37
+ });
38
+
39
+ const usersTable = testSchema.tables.users;
40
+ const postsTable = testSchema.tables.posts;
41
+
42
+ describe("basic encoding", () => {
43
+ it("should resolve string values", () => {
44
+ const result = encodeValues(
45
+ { id: "user1", name: "John", email: "john@example.com" },
46
+ usersTable,
47
+ false,
48
+ );
49
+
50
+ expect(result).toEqual({
51
+ id: "user1",
52
+ name: "John",
53
+ email: "john@example.com",
54
+ });
55
+ });
56
+
57
+ it("should resolve integer values", () => {
58
+ const result = encodeValues({ age: 25 }, usersTable, false);
59
+
60
+ expect(result).toEqual({ age: 25 });
61
+ });
62
+
63
+ it("should resolve boolean values (not serialized)", () => {
64
+ const result = encodeValues({ isActive: true }, usersTable, false);
65
+
66
+ // Boolean stays as boolean (not converted to 0/1)
67
+ expect(result).toEqual({ isActive: true });
68
+ });
69
+ });
70
+
71
+ describe("date encoding", () => {
72
+ it("should keep Date as Date (not serialized)", () => {
73
+ const date = new Date("2024-01-15T10:30:00Z");
74
+ const result = encodeValues({ createdAt: date }, usersTable, false);
75
+
76
+ // Date stays as Date (serialization happens later in encoder)
77
+ expect(result).toEqual({ createdAt: date });
78
+ });
79
+ });
80
+
81
+ describe("nullable columns", () => {
82
+ it("should handle null values", () => {
83
+ const result = encodeValues({ age: null }, usersTable, false);
84
+
85
+ expect(result).toEqual({ age: null });
86
+ });
87
+
88
+ it("should omit undefined values", () => {
89
+ const result = encodeValues({ age: undefined }, usersTable, false);
90
+
91
+ expect(result).toEqual({});
92
+ });
93
+
94
+ it("should handle nullable timestamp", () => {
95
+ const result = encodeValues({ publishedAt: null }, postsTable, false);
96
+
97
+ expect(result).toEqual({ publishedAt: null });
98
+ });
99
+ });
100
+
101
+ describe("default value generation", () => {
102
+ it("should generate runtime defaults when generateDefault is true", () => {
103
+ const result = encodeValues({ title: "Test Post", userId: "user1" }, postsTable, true);
104
+
105
+ expect(result["title"]).toBe("Test Post");
106
+ expect(result["userId"]).toBeInstanceOf(ReferenceSubquery);
107
+ // viewCount has static default (defaultTo), so it's omitted to let DB handle it
108
+ expect(result["viewCount"]).toBeUndefined();
109
+ expect(result["id"]).toBeDefined();
110
+ expect(typeof result["id"]).toBe("string");
111
+ });
112
+
113
+ it("should not generate default values when generateDefault is false", () => {
114
+ const result = encodeValues({ title: "Test Post", userId: "user1" }, postsTable, false);
115
+
116
+ expect(result).toEqual({
117
+ title: "Test Post",
118
+ userId: expect.any(ReferenceSubquery),
119
+ });
120
+ });
121
+
122
+ it("should not override explicitly provided values", () => {
123
+ const result = encodeValues(
124
+ { title: "Test Post", userId: "user1", viewCount: 100 },
125
+ postsTable,
126
+ true,
127
+ );
128
+
129
+ expect(result["viewCount"]).toBe(100);
130
+ });
131
+ });
132
+
133
+ describe("complete record encoding", () => {
134
+ it("should resolve all fields correctly (without serialization)", () => {
135
+ const date = new Date("2024-01-15T10:30:00Z");
136
+ const result = encodeValues(
137
+ {
138
+ id: "user1",
139
+ name: "Alice",
140
+ email: "alice@example.com",
141
+ age: 30,
142
+ isActive: false,
143
+ createdAt: date,
144
+ },
145
+ usersTable,
146
+ false,
147
+ );
148
+
149
+ // Values are resolved but NOT serialized (Date stays as Date, boolean stays as boolean)
150
+ expect(result).toEqual({
151
+ id: "user1",
152
+ name: "Alice",
153
+ email: "alice@example.com",
154
+ age: 30,
155
+ isActive: false, // Not serialized to 0
156
+ createdAt: date, // Not serialized to timestamp
157
+ });
158
+ });
159
+ });
160
+
161
+ describe("FragnoId encoding", () => {
162
+ it("should resolve FragnoId with external ID only", () => {
163
+ const fragnoId = FragnoId.fromExternal("user123", 1);
164
+ const result = encodeValues({ id: fragnoId, name: "John" }, usersTable, false);
165
+
166
+ expect(result).toEqual({
167
+ id: "user123",
168
+ name: "John",
169
+ });
170
+ });
171
+
172
+ it("should resolve FragnoId with both IDs", () => {
173
+ const fragnoId = new FragnoId({
174
+ externalId: "user123",
175
+ internalId: BigInt(456),
176
+ version: 1,
177
+ });
178
+ const result = encodeValues({ id: fragnoId, name: "John" }, usersTable, false);
179
+
180
+ expect(result).toEqual({
181
+ id: "user123",
182
+ name: "John",
183
+ });
184
+ });
185
+
186
+ it("should resolve FragnoId in reference columns", () => {
187
+ const fragnoId = new FragnoId({
188
+ externalId: "user123",
189
+ internalId: BigInt(456),
190
+ version: 1,
191
+ });
192
+ const result = encodeValues({ title: "Test Post", userId: fragnoId }, postsTable, false);
193
+
194
+ // Reference columns should use the internal ID (bigint, not serialized)
195
+ expect(result).toEqual({
196
+ title: "Test Post",
197
+ userId: BigInt(456),
198
+ });
199
+ });
200
+
201
+ it("should convert FragnoId without internalId to ReferenceSubquery for reference columns", () => {
202
+ const fragnoId = new FragnoId({
203
+ externalId: "user123",
204
+ version: 1,
205
+ });
206
+ const result = encodeValues({ title: "Test Post", userId: fragnoId }, postsTable, false);
207
+
208
+ // FragnoId without internalId should be converted to ReferenceSubquery for database lookup
209
+ expect(result["title"]).toBe("Test Post");
210
+ expect(result["userId"]).toBeInstanceOf(ReferenceSubquery);
211
+ expect((result["userId"] as ReferenceSubquery).externalIdValue).toBe("user123");
212
+ });
213
+
214
+ it("should handle FragnoId across different providers", () => {
215
+ const fragnoId = new FragnoId({
216
+ externalId: "user123",
217
+ internalId: BigInt(456),
218
+ version: 1,
219
+ });
220
+ const testData = { id: fragnoId, name: "John" };
221
+
222
+ // Test that provider-agnostic resolution works
223
+ const result = encodeValues(testData, usersTable, false);
224
+
225
+ expect(result).toEqual({ id: "user123", name: "John" });
226
+ });
227
+
228
+ it("should handle ReferenceSubquery correctly", () => {
229
+ const fragnoId = FragnoId.fromExternal("user123", 1);
230
+ const result = encodeValues({ id: fragnoId, name: "John" }, usersTable, false);
231
+
232
+ // FragnoId handling should still work
233
+ expect(result).toEqual({
234
+ id: "user123",
235
+ name: "John",
236
+ });
237
+
238
+ // Test ReferenceSubquery
239
+ const refResult = encodeValues(
240
+ { title: "Test Post", userId: "user_external_id" },
241
+ postsTable,
242
+ false,
243
+ );
244
+
245
+ expect(refResult["title"]).toBe("Test Post");
246
+ expect(refResult["userId"]).toBeInstanceOf(ReferenceSubquery);
247
+ });
248
+ });
249
+ });
250
+
251
+ describe("resolveFragnoIdValue", () => {
252
+ describe("FragnoReference handling", () => {
253
+ it("should extract internal ID from FragnoReference", () => {
254
+ const ref = FragnoReference.fromInternal(BigInt(123));
255
+ const col = column("bigint");
256
+ col.role = "reference";
257
+
258
+ const result = resolveFragnoIdValue(ref, col);
259
+
260
+ expect(result).toBe(BigInt(123));
261
+ });
262
+ });
263
+
264
+ describe("FragnoId handling for external-id columns", () => {
265
+ it("should extract external ID from FragnoId", () => {
266
+ const externalIdCol = column("string");
267
+ externalIdCol.role = "external-id";
268
+ const fragnoId = new FragnoId({
269
+ externalId: "user123",
270
+ internalId: BigInt(456),
271
+ version: 1,
272
+ });
273
+
274
+ const result = resolveFragnoIdValue(fragnoId, externalIdCol);
275
+
276
+ expect(result).toBe("user123");
277
+ });
278
+
279
+ it("should work with FragnoId created from fromExternal", () => {
280
+ const externalIdCol = column("string");
281
+ externalIdCol.role = "external-id";
282
+ const fragnoId = FragnoId.fromExternal("user789", 2);
283
+
284
+ const result = resolveFragnoIdValue(fragnoId, externalIdCol);
285
+
286
+ expect(result).toBe("user789");
287
+ });
288
+ });
289
+
290
+ describe("FragnoId handling for internal-id columns", () => {
291
+ it("should extract internal ID from FragnoId", () => {
292
+ const internalIdCol = column("bigint");
293
+ internalIdCol.role = "internal-id";
294
+ const fragnoId = new FragnoId({
295
+ externalId: "user123",
296
+ internalId: BigInt(456),
297
+ version: 1,
298
+ });
299
+
300
+ const result = resolveFragnoIdValue(fragnoId, internalIdCol);
301
+
302
+ expect(result).toBe(BigInt(456));
303
+ });
304
+
305
+ it("should throw error when FragnoId lacks internal ID", () => {
306
+ const internalIdCol = column("bigint");
307
+ internalIdCol.role = "internal-id";
308
+ const fragnoId = FragnoId.fromExternal("user123", 1);
309
+
310
+ expect(() => resolveFragnoIdValue(fragnoId, internalIdCol)).toThrow(
311
+ "FragnoId must have internalId for internal-id column",
312
+ );
313
+ });
314
+ });
315
+
316
+ describe("FragnoId handling for reference columns", () => {
317
+ it("should prefer internal ID when available", () => {
318
+ const referenceCol = column("bigint");
319
+ referenceCol.role = "reference";
320
+ const fragnoId = new FragnoId({
321
+ externalId: "user123",
322
+ internalId: BigInt(456),
323
+ version: 1,
324
+ });
325
+
326
+ const result = resolveFragnoIdValue(fragnoId, referenceCol);
327
+
328
+ expect(result).toBe(BigInt(456));
329
+ });
330
+
331
+ it("should fallback to external ID when internal ID unavailable", () => {
332
+ const referenceCol = column("bigint");
333
+ referenceCol.role = "reference";
334
+ const fragnoId = FragnoId.fromExternal("user123", 1);
335
+
336
+ const result = resolveFragnoIdValue(fragnoId, referenceCol);
337
+
338
+ expect(result).toBe("user123");
339
+ });
340
+ });
341
+
342
+ describe("FragnoId handling for regular columns", () => {
343
+ it("should use external ID for regular columns", () => {
344
+ const regularCol = column("string");
345
+ regularCol.role = "regular";
346
+ const fragnoId = new FragnoId({
347
+ externalId: "user123",
348
+ internalId: BigInt(456),
349
+ version: 1,
350
+ });
351
+
352
+ const result = resolveFragnoIdValue(fragnoId, regularCol);
353
+
354
+ expect(result).toBe("user123");
355
+ });
356
+ });
357
+
358
+ describe("non-FragnoId values", () => {
359
+ it("should pass through strings", () => {
360
+ const col = column("string");
361
+ const result = resolveFragnoIdValue("hello", col);
362
+ expect(result).toBe("hello");
363
+ });
364
+
365
+ it("should pass through numbers", () => {
366
+ const col = column("integer");
367
+ const result = resolveFragnoIdValue(42, col);
368
+ expect(result).toBe(42);
369
+ });
370
+
371
+ it("should pass through dates", () => {
372
+ const col = column("timestamp");
373
+ const date = new Date();
374
+ const result = resolveFragnoIdValue(date, col);
375
+ expect(result).toBe(date);
376
+ });
377
+
378
+ it("should pass through null", () => {
379
+ const col = column("string").nullable();
380
+ const result = resolveFragnoIdValue(null, col);
381
+ expect(result).toBe(null);
382
+ });
383
+
384
+ it("should pass through bigint", () => {
385
+ const col = column("bigint");
386
+ const result = resolveFragnoIdValue(BigInt(999), col);
387
+ expect(result).toBe(BigInt(999));
388
+ });
389
+ });
390
+ });
@@ -0,0 +1,168 @@
1
+ import type { AnyTable, AnyColumn } from "../schema/create";
2
+ import { FragnoId, FragnoReference } from "../schema/create";
3
+ import { generateRuntimeDefault } from "./column-defaults";
4
+
5
+ /**
6
+ * Marker class for reference column values that need subquery resolution.
7
+ * When a reference column receives a string (external ID), this marker tells
8
+ * the query builder to generate a subquery to look up the internal ID.
9
+ * @internal
10
+ */
11
+ export class ReferenceSubquery {
12
+ #referencedTable: AnyTable;
13
+ #externalIdValue: string;
14
+
15
+ constructor(referencedTable: AnyTable, externalIdValue: string) {
16
+ this.#referencedTable = referencedTable;
17
+ this.#externalIdValue = externalIdValue;
18
+ }
19
+
20
+ get referencedTable() {
21
+ return this.#referencedTable;
22
+ }
23
+
24
+ get externalIdValue() {
25
+ return this.#externalIdValue;
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Resolves FragnoId or FragnoReference objects to their appropriate primitive values.
31
+ *
32
+ * This function handles the Fragno ID system's conversion to database values:
33
+ * - FragnoReference objects are resolved to their internal IDs
34
+ * - FragnoId objects are resolved based on the column role:
35
+ * - external-id: uses the external ID
36
+ * - internal-id: uses the internal ID (must be present)
37
+ * - reference: uses databaseId (internal ID if available, else external ID)
38
+ * - other: uses the external ID by default
39
+ *
40
+ * @param value - The value to resolve (may be FragnoId, FragnoReference, or any other value)
41
+ * @param col - The column schema definition
42
+ * @returns The resolved primitive value, or the original value if not a FragnoId/FragnoReference
43
+ * @throws Error if internal ID is required but not available
44
+ * @internal
45
+ */
46
+ export function resolveFragnoIdValue(value: unknown, col: AnyColumn): unknown {
47
+ // Handle FragnoReference objects (for reference columns)
48
+ if (value instanceof FragnoReference) {
49
+ return value.internalId;
50
+ }
51
+
52
+ // Handle FragnoId objects
53
+ if (value instanceof FragnoId) {
54
+ // For external ID columns, use the external ID
55
+ if (col.role === "external-id") {
56
+ return value.externalId;
57
+ }
58
+ // For internal ID columns, use the internal ID (must be present)
59
+ if (col.role === "internal-id") {
60
+ if (value.internalId === undefined) {
61
+ throw new Error(`FragnoId must have internalId for internal-id column ${col.name}`);
62
+ }
63
+ return value.internalId;
64
+ }
65
+ // For reference columns, prefer internal ID if available, else external ID
66
+ if (col.role === "reference") {
67
+ return value.databaseId;
68
+ }
69
+ // Default to external ID for other columns
70
+ return value.externalId;
71
+ }
72
+
73
+ return value;
74
+ }
75
+
76
+ /**
77
+ * Encodes a record of values from the application format to resolved format.
78
+ *
79
+ * This function:
80
+ * - Transforms object keys from ORM names to database column names
81
+ * - Resolves FragnoId/FragnoReference objects to primitive values
82
+ * - Generates default values for undefined columns
83
+ * - Creates ReferenceSubquery markers for external ID lookups
84
+ *
85
+ * Note: This function does NOT serialize values (Date → number, bigint → Buffer, etc.).
86
+ * Use UnitOfWorkEncoder.encode() to apply driver-specific serialization after this step.
87
+ *
88
+ * @param values - The record of values to encode in application format
89
+ * @param table - The table schema definition containing column information
90
+ * @param generateDefault - Whether to generate default values for undefined columns
91
+ * @returns A record with database column names and resolved (but not serialized) values
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * const encoded = encodeValues(
96
+ * { userId: 123, createdAt: new Date() },
97
+ * userTable,
98
+ * true
99
+ * );
100
+ * // Returns: { user_id: 123, created_at: Date } (not yet serialized)
101
+ * ```
102
+ */
103
+ export function encodeValues(
104
+ values: Record<string, unknown>,
105
+ table: AnyTable,
106
+ generateDefault: boolean,
107
+ ): Record<string, unknown> {
108
+ const result: Record<string, unknown> = {};
109
+
110
+ for (const k in table.columns) {
111
+ const col = table.columns[k];
112
+
113
+ // Skip internal ID - never provided by user, auto-generated by database
114
+ if (col.role === "internal-id") {
115
+ continue;
116
+ }
117
+ let value = values[k];
118
+
119
+ if (generateDefault && value === undefined) {
120
+ // Only generate runtime defaults (defaultTo$), not static defaults (defaultTo).
121
+ // Static defaults should be handled by the database via DEFAULT constraints.
122
+ value = generateRuntimeDefault(col);
123
+ }
124
+
125
+ if (value !== undefined) {
126
+ // Handle reference columns: strings or FragnoIds without internal IDs need subqueries
127
+ if (col.role === "reference") {
128
+ let needsSubquery = false;
129
+ let externalIdForSubquery: string | undefined;
130
+
131
+ if (typeof value === "string") {
132
+ // String external ID - needs subquery
133
+ needsSubquery = true;
134
+ externalIdForSubquery = value;
135
+ } else if (value instanceof FragnoId && value.internalId === undefined) {
136
+ // FragnoId without internal ID - needs subquery
137
+ needsSubquery = true;
138
+ externalIdForSubquery = value.externalId;
139
+ } else if (value instanceof FragnoId && value.internalId !== undefined) {
140
+ // FragnoId with internal ID - use it directly (will be serialized later)
141
+ result[col.name] = value.internalId;
142
+ continue;
143
+ } else if (value instanceof FragnoReference) {
144
+ // FragnoReference - use internal ID directly (will be serialized later)
145
+ result[col.name] = value.internalId;
146
+ continue;
147
+ }
148
+
149
+ if (needsSubquery) {
150
+ const relation = Object.values(table.relations).find((rel) =>
151
+ rel.on.some(([localCol]) => localCol === k),
152
+ );
153
+ if (relation) {
154
+ result[col.name] = new ReferenceSubquery(relation.table, externalIdForSubquery!);
155
+ continue;
156
+ }
157
+ throw new Error(`Reference column ${k} not found in table ${table.name}`);
158
+ }
159
+ }
160
+
161
+ // Resolve FragnoId/FragnoReference to primitive values (serialization happens later)
162
+ const resolvedValue = resolveFragnoIdValue(value, col);
163
+ result[col.name] = resolvedValue;
164
+ }
165
+ }
166
+
167
+ return result;
168
+ }
@@ -8,7 +8,11 @@ import {
8
8
  schema,
9
9
  SchemaBuilder,
10
10
  } from "./create";
11
- import type { RawColumnValues, TableToColumnValues, TableToInsertValues } from "../query/query";
11
+ import type {
12
+ RawColumnValues,
13
+ TableToColumnValues,
14
+ TableToInsertValues,
15
+ } from "../query/simple-query-interface";
12
16
 
13
17
  describe("create", () => {
14
18
  it("should create a table with columns using callback pattern", () => {
@@ -1,4 +1,5 @@
1
1
  import { createId } from "../id";
2
+ import { inspect } from "node:util";
2
3
 
3
4
  export type AnySchema = Schema<Record<string, AnyTable>>;
4
5
 
@@ -547,6 +548,10 @@ export class FragnoId {
547
548
  valueOf(): string {
548
549
  return this.#externalId;
549
550
  }
551
+
552
+ [inspect.custom](): string {
553
+ return `FragnoId { externalId: ${this.#externalId}, internalId: ${this.#internalId?.toString()} }`;
554
+ }
550
555
  }
551
556
 
552
557
  /**