@fragno-dev/db 0.2.2 → 0.3.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 (355) hide show
  1. package/.turbo/turbo-build.log +202 -140
  2. package/CHANGELOG.md +35 -0
  3. package/README.md +30 -9
  4. package/dist/adapters/adapters.d.ts +23 -21
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/generic-sql/driver-config.d.ts +16 -1
  8. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/driver-config.js +23 -1
  10. package/dist/adapters/generic-sql/driver-config.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +27 -9
  12. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  13. package/dist/adapters/generic-sql/generic-sql-adapter.js +55 -16
  14. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  15. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +129 -3
  16. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  17. package/dist/adapters/generic-sql/migration/dialect/mysql.js +24 -5
  18. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  19. package/dist/adapters/generic-sql/migration/dialect/postgres.js +6 -5
  20. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  21. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +21 -10
  22. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  23. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  24. package/dist/adapters/generic-sql/migration/prepared-migrations.js +8 -8
  25. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  26. package/dist/adapters/generic-sql/migration/sql-generator.js +74 -51
  27. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  28. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +6 -5
  29. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  30. package/dist/adapters/generic-sql/query/cursor-utils.js +42 -4
  31. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  32. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +25 -17
  33. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  34. package/dist/adapters/generic-sql/query/select-builder.js +5 -3
  35. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/sql-query-compiler.js +15 -12
  37. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  38. package/dist/adapters/generic-sql/query/where-builder.js +39 -29
  39. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  40. package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
  41. package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  42. package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
  43. package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
  44. package/dist/adapters/generic-sql/uow-decoder.js +7 -3
  45. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  46. package/dist/adapters/generic-sql/uow-encoder.js +28 -8
  47. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  48. package/dist/adapters/in-memory/condition-evaluator.js +131 -0
  49. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
  50. package/dist/adapters/in-memory/errors.d.ts +13 -0
  51. package/dist/adapters/in-memory/errors.d.ts.map +1 -0
  52. package/dist/adapters/in-memory/errors.js +23 -0
  53. package/dist/adapters/in-memory/errors.js.map +1 -0
  54. package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
  55. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
  56. package/dist/adapters/in-memory/in-memory-adapter.js +176 -0
  57. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
  58. package/dist/adapters/in-memory/in-memory-uow.js +648 -0
  59. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
  60. package/dist/adapters/in-memory/index.d.ts +4 -0
  61. package/dist/adapters/in-memory/index.js +4 -0
  62. package/dist/adapters/in-memory/options.d.ts +28 -0
  63. package/dist/adapters/in-memory/options.d.ts.map +1 -0
  64. package/dist/adapters/in-memory/options.js +61 -0
  65. package/dist/adapters/in-memory/options.js.map +1 -0
  66. package/dist/adapters/in-memory/reference-resolution.js +26 -0
  67. package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
  68. package/dist/adapters/in-memory/sorted-array-index.js +129 -0
  69. package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
  70. package/dist/adapters/in-memory/store.js +71 -0
  71. package/dist/adapters/in-memory/store.js.map +1 -0
  72. package/dist/adapters/in-memory/value-comparison.js +28 -0
  73. package/dist/adapters/in-memory/value-comparison.js.map +1 -0
  74. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  75. package/dist/adapters/shared/uow-operation-compiler.js +11 -11
  76. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  77. package/dist/adapters/sql/index.d.ts +5 -0
  78. package/dist/adapters/sql/index.js +4 -0
  79. package/dist/db-fragment-definition-builder.d.ts +18 -7
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  81. package/dist/db-fragment-definition-builder.js +116 -54
  82. package/dist/db-fragment-definition-builder.js.map +1 -1
  83. package/dist/dispatchers/cloudflare-do/index.d.ts +26 -0
  84. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
  85. package/dist/dispatchers/cloudflare-do/index.js +63 -0
  86. package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
  87. package/dist/dispatchers/node/index.d.ts +17 -0
  88. package/dist/dispatchers/node/index.d.ts.map +1 -0
  89. package/dist/dispatchers/node/index.js +59 -0
  90. package/dist/dispatchers/node/index.js.map +1 -0
  91. package/dist/fragments/internal-fragment.d.ts +79 -2
  92. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  93. package/dist/fragments/internal-fragment.js +150 -32
  94. package/dist/fragments/internal-fragment.js.map +1 -1
  95. package/dist/fragments/internal-fragment.routes.js +29 -0
  96. package/dist/fragments/internal-fragment.routes.js.map +1 -0
  97. package/dist/fragments/internal-fragment.schema.d.ts +9 -0
  98. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
  99. package/dist/fragments/internal-fragment.schema.js +22 -0
  100. package/dist/fragments/internal-fragment.schema.js.map +1 -0
  101. package/dist/hooks/durable-hooks-processor.d.ts +14 -0
  102. package/dist/hooks/durable-hooks-processor.d.ts.map +1 -0
  103. package/dist/hooks/durable-hooks-processor.js +32 -0
  104. package/dist/hooks/durable-hooks-processor.js.map +1 -0
  105. package/dist/hooks/hooks.d.ts +42 -1
  106. package/dist/hooks/hooks.d.ts.map +1 -1
  107. package/dist/hooks/hooks.js +72 -6
  108. package/dist/hooks/hooks.js.map +1 -1
  109. package/dist/migration-engine/auto-from-schema.js +14 -11
  110. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  111. package/dist/migration-engine/generation-engine.d.ts +16 -10
  112. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  113. package/dist/migration-engine/generation-engine.js +72 -33
  114. package/dist/migration-engine/generation-engine.js.map +1 -1
  115. package/dist/migration-engine/shared.js.map +1 -1
  116. package/dist/mod.d.ts +15 -8
  117. package/dist/mod.d.ts.map +1 -1
  118. package/dist/mod.js +14 -8
  119. package/dist/mod.js.map +1 -1
  120. package/dist/naming/sql-naming.d.ts +19 -0
  121. package/dist/naming/sql-naming.d.ts.map +1 -0
  122. package/dist/naming/sql-naming.js +116 -0
  123. package/dist/naming/sql-naming.js.map +1 -0
  124. package/dist/node_modules/.pnpm/{rou3@0.7.10 → rou3@0.7.12}/node_modules/rou3/dist/index.js +8 -5
  125. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +1 -0
  126. package/dist/outbox/outbox-builder.js +156 -0
  127. package/dist/outbox/outbox-builder.js.map +1 -0
  128. package/dist/outbox/outbox.d.ts +52 -0
  129. package/dist/outbox/outbox.d.ts.map +1 -0
  130. package/dist/outbox/outbox.js +37 -0
  131. package/dist/outbox/outbox.js.map +1 -0
  132. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +3 -2
  133. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -1
  134. package/dist/packages/fragno/dist/api/fragment-instantiator.js +164 -20
  135. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -1
  136. package/dist/packages/fragno/dist/api/request-input-context.js +67 -0
  137. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -1
  138. package/dist/packages/fragno/dist/api/route.js +14 -1
  139. package/dist/packages/fragno/dist/api/route.js.map +1 -1
  140. package/dist/packages/fragno/dist/internal/trace-context.js +12 -0
  141. package/dist/packages/fragno/dist/internal/trace-context.js.map +1 -0
  142. package/dist/query/column-defaults.js +20 -4
  143. package/dist/query/column-defaults.js.map +1 -1
  144. package/dist/query/cursor.d.ts +3 -1
  145. package/dist/query/cursor.d.ts.map +1 -1
  146. package/dist/query/cursor.js +45 -14
  147. package/dist/query/cursor.js.map +1 -1
  148. package/dist/query/db-now.d.ts +8 -0
  149. package/dist/query/db-now.d.ts.map +1 -0
  150. package/dist/query/db-now.js +7 -0
  151. package/dist/query/db-now.js.map +1 -0
  152. package/dist/query/serialize/create-sql-serializer.js +3 -2
  153. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  154. package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
  155. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  156. package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
  157. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  158. package/dist/query/serialize/dialect/sqlite-serializer.js +55 -11
  159. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  160. package/dist/query/serialize/sql-serializer.js +2 -2
  161. package/dist/query/serialize/sql-serializer.js.map +1 -1
  162. package/dist/query/simple-query-interface.d.ts +6 -1
  163. package/dist/query/simple-query-interface.d.ts.map +1 -1
  164. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  165. package/dist/query/unit-of-work/execute-unit-of-work.js +11 -6
  166. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  167. package/dist/query/unit-of-work/unit-of-work.d.ts +50 -14
  168. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  169. package/dist/query/unit-of-work/unit-of-work.js +86 -5
  170. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  171. package/dist/query/value-decoding.js +9 -6
  172. package/dist/query/value-decoding.js.map +1 -1
  173. package/dist/query/value-encoding.js +29 -9
  174. package/dist/query/value-encoding.js.map +1 -1
  175. package/dist/schema/create.d.ts +38 -14
  176. package/dist/schema/create.d.ts.map +1 -1
  177. package/dist/schema/create.js +81 -42
  178. package/dist/schema/create.js.map +1 -1
  179. package/dist/schema/generate-id.js +2 -2
  180. package/dist/schema/generate-id.js.map +1 -1
  181. package/dist/schema/type-conversion/create-sql-type-mapper.js +3 -2
  182. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  183. package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
  184. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  185. package/dist/schema/validator.d.ts +10 -0
  186. package/dist/schema/validator.d.ts.map +1 -0
  187. package/dist/schema/validator.js +123 -0
  188. package/dist/schema/validator.js.map +1 -0
  189. package/dist/schema-output/drizzle.d.ts +30 -0
  190. package/dist/schema-output/drizzle.d.ts.map +1 -0
  191. package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +82 -56
  192. package/dist/schema-output/drizzle.js.map +1 -0
  193. package/dist/schema-output/prisma.d.ts +17 -0
  194. package/dist/schema-output/prisma.d.ts.map +1 -0
  195. package/dist/schema-output/prisma.js +296 -0
  196. package/dist/schema-output/prisma.js.map +1 -0
  197. package/dist/util/default-database-adapter.js +61 -0
  198. package/dist/util/default-database-adapter.js.map +1 -0
  199. package/dist/with-database.d.ts +1 -1
  200. package/dist/with-database.d.ts.map +1 -1
  201. package/dist/with-database.js +12 -3
  202. package/dist/with-database.js.map +1 -1
  203. package/package.json +43 -28
  204. package/src/adapters/adapters.ts +30 -24
  205. package/src/adapters/drizzle/migrate-drizzle.test.ts +54 -33
  206. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +599 -0
  207. package/src/adapters/drizzle/test-utils.ts +12 -8
  208. package/src/adapters/generic-sql/driver-config.ts +38 -0
  209. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -5
  210. package/src/adapters/generic-sql/generic-sql-adapter.ts +110 -24
  211. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +54 -0
  212. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +231 -3
  213. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +118 -0
  214. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +26 -8
  215. package/src/adapters/generic-sql/migration/dialect/mysql.ts +46 -8
  216. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +25 -7
  217. package/src/adapters/generic-sql/migration/dialect/postgres.ts +8 -4
  218. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +47 -8
  219. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +27 -12
  220. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +128 -39
  221. package/src/adapters/generic-sql/migration/prepared-migrations.ts +15 -8
  222. package/src/adapters/generic-sql/migration/sql-generator.ts +142 -65
  223. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +9 -6
  224. package/src/adapters/generic-sql/query/cursor-utils.test.ts +271 -0
  225. package/src/adapters/generic-sql/query/cursor-utils.ts +41 -6
  226. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +27 -27
  227. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +38 -24
  228. package/src/adapters/generic-sql/query/select-builder.test.ts +15 -11
  229. package/src/adapters/generic-sql/query/select-builder.ts +6 -2
  230. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +52 -2
  231. package/src/adapters/generic-sql/query/sql-query-compiler.ts +50 -15
  232. package/src/adapters/generic-sql/query/where-builder.test.ts +91 -17
  233. package/src/adapters/generic-sql/query/where-builder.ts +90 -38
  234. package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +6 -6
  235. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +806 -0
  236. package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +11 -11
  237. package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +10 -10
  238. package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +7 -7
  239. package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +6 -6
  240. package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
  241. package/src/adapters/generic-sql/uow-decoder.test.ts +1 -1
  242. package/src/adapters/generic-sql/uow-decoder.ts +21 -3
  243. package/src/adapters/generic-sql/uow-encoder.test.ts +33 -2
  244. package/src/adapters/generic-sql/uow-encoder.ts +50 -11
  245. package/src/adapters/in-memory/condition-evaluator.test.ts +193 -0
  246. package/src/adapters/in-memory/condition-evaluator.ts +275 -0
  247. package/src/adapters/in-memory/errors.ts +20 -0
  248. package/src/adapters/in-memory/in-memory-adapter.ts +277 -0
  249. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +296 -0
  250. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +100 -0
  251. package/src/adapters/in-memory/in-memory-uow.ts +1348 -0
  252. package/src/adapters/in-memory/index.ts +3 -0
  253. package/src/adapters/in-memory/options.test.ts +41 -0
  254. package/src/adapters/in-memory/options.ts +87 -0
  255. package/src/adapters/in-memory/reference-resolution.test.ts +50 -0
  256. package/src/adapters/in-memory/reference-resolution.ts +67 -0
  257. package/src/adapters/in-memory/sorted-array-index.test.ts +123 -0
  258. package/src/adapters/in-memory/sorted-array-index.ts +228 -0
  259. package/src/adapters/in-memory/store.test.ts +68 -0
  260. package/src/adapters/in-memory/store.ts +145 -0
  261. package/src/adapters/in-memory/value-comparison.ts +53 -0
  262. package/src/adapters/in-memory/value-normalization.test.ts +57 -0
  263. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1163 -0
  264. package/src/adapters/shared/from-unit-of-work-compiler.ts +3 -1
  265. package/src/adapters/shared/uow-operation-compiler.ts +26 -16
  266. package/src/adapters/sql/index.ts +12 -0
  267. package/src/db-fragment-definition-builder.test.ts +30 -12
  268. package/src/db-fragment-definition-builder.ts +142 -73
  269. package/src/db-fragment-instantiator.test.ts +105 -13
  270. package/src/db-fragment-integration.test.ts +9 -7
  271. package/src/dispatchers/cloudflare-do/index.test.ts +73 -0
  272. package/src/dispatchers/cloudflare-do/index.ts +104 -0
  273. package/src/dispatchers/node/index.test.ts +91 -0
  274. package/src/dispatchers/node/index.ts +87 -0
  275. package/src/fragments/internal-fragment.routes.ts +42 -0
  276. package/src/fragments/internal-fragment.schema.ts +51 -0
  277. package/src/fragments/internal-fragment.test.ts +458 -8
  278. package/src/fragments/internal-fragment.ts +322 -63
  279. package/src/hooks/durable-hooks-processor.test.ts +117 -0
  280. package/src/hooks/durable-hooks-processor.ts +67 -0
  281. package/src/hooks/hooks.test.ts +165 -5
  282. package/src/hooks/hooks.ts +197 -9
  283. package/src/migration-engine/auto-from-schema.test.ts +14 -14
  284. package/src/migration-engine/auto-from-schema.ts +5 -2
  285. package/src/migration-engine/create.test.ts +2 -2
  286. package/src/migration-engine/generation-engine.test.ts +229 -104
  287. package/src/migration-engine/generation-engine.ts +94 -64
  288. package/src/migration-engine/shared.ts +1 -0
  289. package/src/mod.ts +64 -26
  290. package/src/naming/sql-naming.ts +180 -0
  291. package/src/outbox/outbox-builder.ts +241 -0
  292. package/src/outbox/outbox.test.ts +253 -0
  293. package/src/outbox/outbox.ts +137 -0
  294. package/src/query/column-defaults.ts +41 -3
  295. package/src/query/condition-builder.test.ts +3 -3
  296. package/src/query/cursor.test.ts +116 -18
  297. package/src/query/cursor.ts +75 -26
  298. package/src/query/db-now.ts +6 -0
  299. package/src/query/query-type.test.ts +2 -2
  300. package/src/query/serialize/create-sql-serializer.ts +7 -2
  301. package/src/query/serialize/dialect/mysql-serializer.ts +12 -4
  302. package/src/query/serialize/dialect/postgres-serializer.ts +34 -4
  303. package/src/query/serialize/dialect/sqlite-serializer.test.ts +51 -1
  304. package/src/query/serialize/dialect/sqlite-serializer.ts +92 -9
  305. package/src/query/serialize/sql-serializer.ts +4 -4
  306. package/src/query/simple-query-interface.ts +5 -0
  307. package/src/query/unit-of-work/execute-unit-of-work.test.ts +25 -1
  308. package/src/query/unit-of-work/execute-unit-of-work.ts +25 -8
  309. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +12 -12
  310. package/src/query/unit-of-work/unit-of-work-types.test.ts +1 -1
  311. package/src/query/unit-of-work/unit-of-work.test.ts +168 -37
  312. package/src/query/unit-of-work/unit-of-work.ts +203 -18
  313. package/src/query/value-decoding.test.ts +13 -2
  314. package/src/query/value-decoding.ts +17 -4
  315. package/src/query/value-encoding.test.ts +85 -2
  316. package/src/query/value-encoding.ts +56 -6
  317. package/src/schema/create.test.ts +129 -42
  318. package/src/schema/create.ts +185 -47
  319. package/src/schema/generate-id.test.ts +2 -2
  320. package/src/schema/generate-id.ts +2 -2
  321. package/src/schema/serialize.test.ts +14 -2
  322. package/src/schema/type-conversion/create-sql-type-mapper.ts +7 -2
  323. package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
  324. package/src/schema/type-conversion/type-mapping.test.ts +25 -1
  325. package/src/schema/validator.test.ts +197 -0
  326. package/src/schema/validator.ts +231 -0
  327. package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +179 -129
  328. package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +143 -93
  329. package/src/schema-output/prisma.test.ts +536 -0
  330. package/src/schema-output/prisma.ts +573 -0
  331. package/src/util/default-database-adapter.ts +106 -0
  332. package/src/with-database.ts +22 -3
  333. package/tsdown.config.ts +6 -4
  334. package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
  335. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
  336. package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
  337. package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
  338. package/dist/adapters/drizzle/generate.d.ts +0 -30
  339. package/dist/adapters/drizzle/generate.d.ts.map +0 -1
  340. package/dist/adapters/drizzle/generate.js.map +0 -1
  341. package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
  342. package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
  343. package/dist/adapters/kysely/kysely-adapter.js +0 -17
  344. package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
  345. package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
  346. package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
  347. package/dist/adapters/shared/table-name-mapper.js +0 -43
  348. package/dist/adapters/shared/table-name-mapper.js.map +0 -1
  349. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
  350. package/dist/schema-generator/schema-generator.d.ts +0 -15
  351. package/dist/schema-generator/schema-generator.d.ts.map +0 -1
  352. package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
  353. package/src/adapters/kysely/kysely-adapter.ts +0 -27
  354. package/src/adapters/shared/table-name-mapper.ts +0 -50
  355. package/src/schema-generator/schema-generator.ts +0 -12
@@ -1,4 +1,5 @@
1
1
  import { createId } from "../id.js";
2
+ import { FragnoDbValidationError, createTableStandardSchemaProps, createTableValidator } from "./validator.js";
2
3
  import { generateId } from "./generate-id.js";
3
4
 
4
5
  //#region src/schema/create.ts
@@ -14,11 +15,11 @@ var RelationInit = class {
14
15
  }
15
16
  };
16
17
  var ExplicitRelationInit = class extends RelationInit {
17
- init(ormName) {
18
+ init(name) {
18
19
  return {
19
- id: `${this.referencer.ormName}_${this.referencedTable.ormName}`,
20
+ id: `${this.referencer.name}_${this.referencedTable.name}`,
20
21
  on: this.on,
21
- name: ormName,
22
+ name,
22
23
  referencer: this.referencer,
23
24
  table: this.referencedTable,
24
25
  type: this.type
@@ -42,7 +43,6 @@ const runtimeDefaultBuilder = {
42
43
  var Column = class {
43
44
  type;
44
45
  name = "";
45
- ormName = "";
46
46
  isNullable = false;
47
47
  role = "regular";
48
48
  isHidden = false;
@@ -304,12 +304,15 @@ var FragnoReference = class FragnoReference {
304
304
  return this.#internalId;
305
305
  }
306
306
  };
307
+ const validationClasses = {
308
+ FragnoId,
309
+ FragnoReference
310
+ };
307
311
  var TableBuilder = class {
308
312
  #name;
309
313
  #columns;
310
314
  #relations;
311
315
  #indexes;
312
- #ormName = "";
313
316
  #columnOrder = [];
314
317
  constructor(name) {
315
318
  this.#name = name;
@@ -332,12 +335,11 @@ var TableBuilder = class {
332
335
  getColumnOrder() {
333
336
  return this.#columnOrder;
334
337
  }
335
- addColumn(ormName, colOrType) {
338
+ addColumn(name, colOrType) {
336
339
  const col = typeof colOrType === "string" ? column(colOrType) : colOrType;
337
- col.ormName = ormName;
338
- col.name = ormName;
339
- this.#columns[ormName] = col;
340
- this.#columnOrder.push(ormName);
340
+ col.name = name;
341
+ this.#columns[name] = col;
342
+ this.#columnOrder.push(name);
341
343
  return this;
342
344
  }
343
345
  /**
@@ -367,20 +369,16 @@ var TableBuilder = class {
367
369
  let versionCol;
368
370
  if (!this.#columns["_internalId"]) {
369
371
  const col = internalIdColumn();
370
- col.ormName = "_internalId";
371
372
  col.name = "_internalId";
372
373
  this.#columns["_internalId"] = col;
373
374
  }
374
375
  if (!this.#columns["_version"]) {
375
376
  const col = versionColumn();
376
- col.ormName = "_version";
377
377
  col.name = "_version";
378
378
  this.#columns["_version"] = col;
379
379
  }
380
- const ormName = this.#ormName || this.#name;
381
380
  const table = {
382
381
  name: this.#name,
383
- ormName,
384
382
  columns: this.#columns,
385
383
  relations: this.#relations,
386
384
  indexes: this.#indexes,
@@ -397,6 +395,8 @@ var TableBuilder = class {
397
395
  return versionCol;
398
396
  }
399
397
  };
398
+ table["~standard"] = createTableStandardSchemaProps(table, validationClasses);
399
+ table.validate = createTableValidator(table, validationClasses);
400
400
  for (const k in this.#columns) {
401
401
  const column$1 = this.#columns[k];
402
402
  if (!column$1) continue;
@@ -412,15 +412,31 @@ var TableBuilder = class {
412
412
  }
413
413
  };
414
414
  var SchemaBuilder = class SchemaBuilder {
415
+ #name;
415
416
  #tables;
416
417
  #version = 0;
417
418
  #operations = [];
418
- constructor(existingSchema) {
419
+ #tableNames = /* @__PURE__ */ new Set();
420
+ #indexNames = /* @__PURE__ */ new Set();
421
+ constructor(name, existingSchema) {
422
+ this.#name = name;
419
423
  if (existingSchema) {
420
424
  this.#tables = existingSchema.tables;
421
425
  this.#version = existingSchema.version;
422
426
  this.#operations = [...existingSchema.operations];
423
427
  } else this.#tables = {};
428
+ for (const table of Object.values(this.#tables)) {
429
+ this.#registerTableName(table.name);
430
+ for (const index of Object.values(table.indexes)) this.#registerIndexName(index.name, table.name);
431
+ }
432
+ }
433
+ #registerTableName(name) {
434
+ if (this.#tableNames.has(name)) throw new Error(`Duplicate table name "${name}" in schema "${this.#name}".`);
435
+ this.#tableNames.add(name);
436
+ }
437
+ #registerIndexName(name, tableName) {
438
+ if (this.#indexNames.has(name)) throw new Error(`Duplicate index name "${name}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${tableName}").`);
439
+ this.#indexNames.add(name);
424
440
  }
425
441
  /**
426
442
  * Add an existing schema to this builder.
@@ -428,29 +444,39 @@ var SchemaBuilder = class SchemaBuilder {
428
444
  *
429
445
  * @example
430
446
  * ```ts
431
- * const builder = new SchemaBuilder()
447
+ * const builder = new SchemaBuilder("combined")
432
448
  * .add(userSchema)
433
449
  * .add(postSchema)
434
450
  * .addTable("comments", ...);
435
451
  * ```
436
452
  */
437
453
  mergeWithExistingSchema(schema$1) {
454
+ for (const table of Object.values(schema$1.tables)) {
455
+ if (this.#tableNames.has(table.name)) throw new Error(`Duplicate table name "${table.name}" in schema "${this.#name}" when merging.`);
456
+ for (const index of Object.values(table.indexes)) if (this.#indexNames.has(index.name)) throw new Error(`Duplicate index name "${index.name}" in schema "${this.#name}" when merging (conflict on "${table.name}").`);
457
+ }
438
458
  this.#tables = {
439
459
  ...this.#tables,
440
460
  ...schema$1.tables
441
461
  };
442
462
  this.#operations = [...this.#operations, ...schema$1.operations];
443
463
  this.#version += schema$1.version;
464
+ for (const table of Object.values(schema$1.tables)) {
465
+ this.#tableNames.add(table.name);
466
+ for (const index of Object.values(table.indexes)) this.#indexNames.add(index.name);
467
+ }
444
468
  return this;
445
469
  }
446
470
  /**
447
471
  * Add a table to the schema. Increments the version counter.
448
472
  */
449
- addTable(ormName, callback) {
473
+ addTable(name, callback) {
450
474
  this.#version++;
451
- const result = callback(new TableBuilder(ormName));
475
+ if (this.#tableNames.has(name)) throw new Error(`Duplicate table name "${name}" in schema "${this.#name}".`);
476
+ const result = callback(new TableBuilder(name));
452
477
  const builtTable = result.build();
453
- builtTable.ormName = ormName;
478
+ const indexNames = result.getIndexes().map((idx) => idx.name);
479
+ for (const indexName of indexNames) if (this.#indexNames.has(indexName)) throw new Error(`Duplicate index name "${indexName}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${name}").`);
454
480
  const subOperations = [];
455
481
  const columnOrder = result.getColumnOrder();
456
482
  for (const colName of columnOrder) {
@@ -474,18 +500,20 @@ var SchemaBuilder = class SchemaBuilder {
474
500
  for (const idx of result.getIndexes()) subOperations.push({
475
501
  type: "add-index",
476
502
  name: idx.name,
477
- columns: idx.columns.map((c) => c.ormName),
503
+ columns: idx.columns.map((c) => c.name),
478
504
  unique: idx.unique
479
505
  });
480
506
  this.#operations.push({
481
507
  type: "add-table",
482
- tableName: ormName,
508
+ tableName: name,
483
509
  operations: subOperations
484
510
  });
485
511
  this.#tables = {
486
512
  ...this.#tables,
487
- [ormName]: builtTable
513
+ [name]: builtTable
488
514
  };
515
+ this.#tableNames.add(name);
516
+ for (const indexName of indexNames) this.#indexNames.add(indexName);
489
517
  return this;
490
518
  }
491
519
  /**
@@ -497,7 +525,7 @@ var SchemaBuilder = class SchemaBuilder {
497
525
  * @example
498
526
  * ```ts
499
527
  * // One-to-one or many-to-one: post -> user
500
- * schema(s => s
528
+ * schema("blog", s => s
501
529
  * .addTable("users", t => t.addColumn("id", idColumn()))
502
530
  * .addTable("posts", t => t
503
531
  * .addColumn("id", idColumn())
@@ -528,6 +556,7 @@ var SchemaBuilder = class SchemaBuilder {
528
556
  this.#version++;
529
557
  const table = this.#tables[config.from.table];
530
558
  const referencedTable = this.#tables[config.to.table];
559
+ if (!referenceName || referenceName.trim().length === 0) throw new Error(`referenceName is required for addReference on ${config.from.table}`);
531
560
  if (!table) throw new Error(`Table ${config.from.table} not found in schema`);
532
561
  if (!referencedTable) throw new Error(`Referenced table ${config.to.table} not found in schema`);
533
562
  const columnName = config.from.column;
@@ -537,6 +566,7 @@ var SchemaBuilder = class SchemaBuilder {
537
566
  const referencedColumn = referencedTable.columns[actualTargetColumnName];
538
567
  if (!column$1) throw new Error(`Column ${columnName} not found in table ${config.from.table}`);
539
568
  if (!referencedColumn) throw new Error(`Column ${actualTargetColumnName} not found in table ${config.to.table}`);
569
+ if (table.relations[referenceName]) throw new Error(`Reference ${referenceName} already exists on table ${config.from.table}`);
540
570
  if (column$1.role === "reference" && column$1.type !== "bigint") throw new Error(`Reference column ${columnName} must be of type bigint to match internal ID type`);
541
571
  const init = new ExplicitRelationInit(config.type, referencedTable, table);
542
572
  init.on.push([columnName, targetColumnName]);
@@ -570,7 +600,7 @@ var SchemaBuilder = class SchemaBuilder {
570
600
  * @example
571
601
  * ```ts
572
602
  * // Add a new column to an existing table
573
- * schema(s => s
603
+ * schema("blog", s => s
574
604
  * .addTable("users", t => t
575
605
  * .addColumn("id", idColumn())
576
606
  * .addColumn("name", column("string")))
@@ -599,12 +629,15 @@ var SchemaBuilder = class SchemaBuilder {
599
629
  columnName: colName,
600
630
  column: newTable.columns[colName]
601
631
  });
602
- for (const idx of resultBuilder.getIndexes()) if (!existingIndexes.has(idx.name)) subOperations.push({
603
- type: "add-index",
604
- name: idx.name,
605
- columns: idx.columns.map((c) => c.ormName),
606
- unique: idx.unique
607
- });
632
+ for (const idx of resultBuilder.getIndexes()) if (!existingIndexes.has(idx.name)) {
633
+ if (this.#indexNames.has(idx.name)) throw new Error(`Duplicate index name "${idx.name}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${tableName}").`);
634
+ subOperations.push({
635
+ type: "add-index",
636
+ name: idx.name,
637
+ columns: idx.columns.map((c) => c.name),
638
+ unique: idx.unique
639
+ });
640
+ }
608
641
  if (subOperations.length > 0) {
609
642
  this.#version++;
610
643
  this.#operations.push({
@@ -614,6 +647,7 @@ var SchemaBuilder = class SchemaBuilder {
614
647
  });
615
648
  }
616
649
  this.#tables[tableName] = newTable;
650
+ for (const idx of resultBuilder.getIndexes()) if (!existingIndexes.has(idx.name)) this.#indexNames.add(idx.name);
617
651
  for (const col of Object.values(newTable.columns)) col.tableName = newTable.name;
618
652
  return this;
619
653
  }
@@ -625,6 +659,7 @@ var SchemaBuilder = class SchemaBuilder {
625
659
  const version = this.#version;
626
660
  const tables = this.#tables;
627
661
  return {
662
+ name: this.#name,
628
663
  version,
629
664
  tables,
630
665
  operations,
@@ -639,7 +674,6 @@ var SchemaBuilder = class SchemaBuilder {
639
674
  else if (col instanceof IdColumn) clonedCol = new IdColumn(col.type);
640
675
  else clonedCol = new Column(col.type);
641
676
  clonedCol.name = col.name;
642
- clonedCol.ormName = col.ormName;
643
677
  clonedCol.isNullable = col.isNullable;
644
678
  clonedCol.role = col.role;
645
679
  clonedCol.isHidden = col.isHidden;
@@ -647,19 +681,24 @@ var SchemaBuilder = class SchemaBuilder {
647
681
  clonedCol.tableName = col.tableName;
648
682
  clonedColumns[colName] = clonedCol;
649
683
  }
650
- cloneTables[k] = {
684
+ const clonedTable = {
651
685
  ...v,
652
686
  columns: clonedColumns
653
687
  };
688
+ clonedTable["~standard"] = createTableStandardSchemaProps(clonedTable, validationClasses);
689
+ clonedTable.validate = createTableValidator(clonedTable, validationClasses);
690
+ cloneTables[k] = clonedTable;
654
691
  }
655
- return new SchemaBuilder({
692
+ const clonedSchema = {
693
+ name: this.#name,
656
694
  version,
657
695
  tables: cloneTables,
658
696
  operations: [...operations],
659
697
  clone: () => {
660
698
  throw new Error("Cannot clone during clone");
661
699
  }
662
- }).build();
700
+ };
701
+ return new SchemaBuilder(this.#name, clonedSchema).build();
663
702
  }
664
703
  };
665
704
  }
@@ -673,19 +712,19 @@ var SchemaBuilder = class SchemaBuilder {
673
712
  /**
674
713
  * Create a new schema with callback pattern.
675
714
  */
676
- function schema(callback) {
677
- return callback(new SchemaBuilder()).build();
715
+ function schema(name, callback) {
716
+ return callback(new SchemaBuilder(name)).build();
678
717
  }
679
- function compileForeignKey(key, nameType = "orm") {
718
+ function compileForeignKey(key) {
680
719
  return {
681
720
  name: key.name,
682
- table: nameType === "sql" ? key.table.name : key.table.ormName,
683
- referencedTable: nameType === "sql" ? key.referencedTable.name : key.referencedTable.ormName,
684
- referencedColumns: key.referencedColumns.map((col) => nameType === "sql" ? col.name : col.ormName),
685
- columns: key.columns.map((col) => nameType === "sql" ? col.name : col.ormName)
721
+ table: key.table.name,
722
+ referencedTable: key.referencedTable.name,
723
+ referencedColumns: key.referencedColumns.map((col) => col.name),
724
+ columns: key.columns.map((col) => col.name)
686
725
  };
687
726
  }
688
727
 
689
728
  //#endregion
690
- export { Column, ExplicitRelationInit, FragnoId, FragnoReference, IdColumn, InternalIdColumn, SchemaBuilder, TableBuilder, VersionColumn, column, compileForeignKey, generateId, idColumn, internalIdColumn, referenceColumn, schema, versionColumn };
729
+ export { Column, ExplicitRelationInit, FragnoDbValidationError, FragnoId, FragnoReference, IdColumn, InternalIdColumn, SchemaBuilder, TableBuilder, VersionColumn, column, compileForeignKey, generateId, idColumn, internalIdColumn, referenceColumn, schema, versionColumn };
691
730
  //# sourceMappingURL=create.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","names":["defaultBuilder: DefaultBuilder","runtimeDefaultBuilder: RuntimeDefaultBuilder","#externalId","#internalId","#version","#name","#columns","#relations","#indexes","#columnOrder","column","idCol: AnyColumn | undefined","internalIdCol: AnyColumn | undefined","versionCol: AnyColumn | undefined","#ormName","table: Table<TColumns, TRelations, TIndexes>","#tables","#operations","schema","subOperations: TableSubOperation[]","cloneTables: Record<string, AnyTable>","clonedColumns: Record<string, AnyColumn>","clonedCol: AnyColumn"],"sources":["../../src/schema/create.ts"],"sourcesContent":["import { createId } from \"../id\";\n\nexport { generateId } from \"./generate-id\";\n\nexport type AnySchema = Schema<Record<string, AnyTable>>;\n\nexport type AnyRelation = Relation;\n\nexport type AnyTable = Table;\n\nexport type AnyColumn =\n | Column<keyof TypeMap, unknown, unknown>\n | IdColumn<IdColumnType, unknown, unknown>\n | InternalIdColumn<unknown, unknown>\n | VersionColumn<unknown, unknown>;\n/**\n * Sub-operations that can be performed within table operations.\n * These are stored in order within add-table and alter-table operations.\n */\nexport type TableSubOperation =\n | { type: \"add-column\"; columnName: string; column: AnyColumn }\n | { type: \"add-index\"; name: string; columns: string[]; unique: boolean }\n | {\n type: \"add-foreign-key\";\n name: string;\n columns: string[];\n referencedTable: string;\n referencedColumns: string[];\n };\n\n/**\n * Operations that can be performed on a schema during its definition.\n * These are tracked so we can generate migrations for specific version ranges.\n */\nexport type SchemaOperation =\n | {\n type: \"add-table\";\n tableName: string;\n operations: TableSubOperation[]; // Ordered list of sub-operations\n }\n | {\n type: \"alter-table\";\n tableName: string;\n operations: TableSubOperation[]; // Ordered list of sub-operations\n }\n | {\n type: \"add-reference\";\n tableName: string; // The table that has the foreign key\n referenceName: string;\n config: {\n type: \"one\" | \"many\";\n from: { table: string; column: string };\n to: { table: string; column: string };\n };\n };\n\nexport interface ForeignKey {\n name: string;\n table: AnyTable;\n columns: AnyColumn[];\n\n referencedTable: AnyTable;\n referencedColumns: AnyColumn[];\n}\n\nclass RelationInit<\n TRelationType extends RelationType,\n TTables extends Record<string, AnyTable>,\n TTableName extends keyof TTables,\n> {\n type: TRelationType;\n referencedTable: TTables[TTableName];\n referencer: AnyTable;\n on: [string, string][] = [];\n\n constructor(type: TRelationType, referencedTable: TTables[TTableName], referencer: AnyTable) {\n this.type = type;\n this.referencedTable = referencedTable;\n this.referencer = referencer;\n }\n}\n\nexport interface Index<\n TColumns extends AnyColumn[] = AnyColumn[],\n TColumnNames extends readonly string[] = readonly string[],\n> {\n name: string;\n columns: TColumns;\n columnNames: TColumnNames;\n unique: boolean;\n}\n\nexport class ExplicitRelationInit<\n TRelationType extends RelationType,\n TTables extends Record<string, AnyTable>,\n TTableName extends keyof TTables,\n> extends RelationInit<TRelationType, TTables, TTableName> {\n init(ormName: string): Relation<TRelationType, TTables[TTableName]> {\n const id = `${this.referencer.ormName}_${this.referencedTable.ormName}`;\n\n return {\n id,\n on: this.on,\n name: ormName,\n referencer: this.referencer,\n table: this.referencedTable,\n type: this.type,\n };\n }\n}\n\nexport interface Relation<\n TRelationType extends RelationType = RelationType,\n TTable extends AnyTable = AnyTable,\n> {\n id: string;\n name: string;\n type: TRelationType;\n\n table: TTable;\n referencer: AnyTable;\n\n on: [string, string][];\n}\n\nexport interface Table<\n TColumns extends Record<string, AnyColumn> = Record<string, AnyColumn>,\n TRelations extends Record<string, AnyRelation> = Record<string, AnyRelation>,\n TIndexes extends Record<string, Index> = Record<string, Index>,\n> {\n name: string;\n ormName: string;\n\n columns: TColumns;\n relations: TRelations;\n indexes: TIndexes;\n\n /**\n * Get column by name\n */\n getColumnByName: (name: string) => AnyColumn | undefined;\n /**\n * Get the external ID column (user-facing)\n */\n getIdColumn: () => AnyColumn;\n /**\n * Get the internal ID column (database-native, used for joins)\n */\n getInternalIdColumn: () => AnyColumn;\n /**\n * Get the version column (for optimistic concurrency control)\n */\n getVersionColumn: () => AnyColumn;\n}\n\ntype DBSpecial = { tag: \"special\"; value: \"now\" };\ntype RuntimeSpecial = { tag: \"special\"; value: \"cuid\" | \"now\" };\n\n/**\n * Builder for database-level default values.\n */\nexport interface DefaultBuilder {\n /** Database-generated timestamp (DEFAULT NOW()) */\n now(): DBSpecial;\n}\n\n/**\n * Builder for runtime-generated default values.\n */\nexport interface RuntimeDefaultBuilder {\n /** Generate CUID identifier */\n cuid(): RuntimeSpecial;\n /** Generate current timestamp */\n now(): RuntimeSpecial;\n}\n\nconst defaultBuilder: DefaultBuilder = {\n now: () => ({ tag: \"special\", value: \"now\" }),\n};\n\nconst runtimeDefaultBuilder: RuntimeDefaultBuilder = {\n cuid: () => ({ tag: \"special\", value: \"cuid\" }),\n now: () => ({ tag: \"special\", value: \"now\" }),\n};\n\ntype IdColumnType = `varchar(${number})`;\n\nexport type TypeMap = {\n string: string;\n bigint: bigint;\n integer: number;\n decimal: number;\n bool: boolean;\n json: unknown;\n /**\n * this follows the same specs as Prisma `Bytes` for consistency.\n */\n binary: Uint8Array;\n date: Date;\n timestamp: Date;\n} & Record<`varchar(${number})`, string>;\n\nexport class Column<TType extends keyof TypeMap, TIn = unknown, TOut = unknown> {\n type: TType;\n name: string = \"\";\n ormName: string = \"\";\n isNullable: boolean = false;\n role: \"external-id\" | \"internal-id\" | \"version\" | \"reference\" | \"regular\" = \"regular\";\n isHidden: boolean = false;\n\n default?:\n | { value: TypeMap[TType] }\n | { dbSpecial: \"now\" }\n | { runtime: \"cuid\" | \"now\" | (() => TypeMap[TType]) };\n\n tableName: string = \"\";\n\n constructor(type: TType) {\n this.type = type;\n }\n\n nullable<TNullable extends boolean = true>(nullable?: TNullable) {\n this.isNullable = nullable ?? true;\n\n return this as Column<\n TType,\n TNullable extends true ? TIn | null : Exclude<TIn, null>,\n TNullable extends true ? TOut | null : Exclude<TOut, null>\n >;\n }\n\n hidden<THidden extends boolean = true>(hidden?: THidden) {\n this.isHidden = hidden ?? true;\n return this as Column<TType, null, null>;\n }\n\n /**\n * Generate default value at runtime in application code (not in the database).\n *\n * Use this when you need values generated in your application code, either because:\n * - Your database doesn't support the operation (e.g., generating CUIDs)\n * - You want consistent behavior across all databases\n * - You need custom generation logic\n *\n * @param value - Either a literal value or builder callback:\n * - Literal: Any static value of the column type\n * - `(b) => b.cuid()` - Generate a CUID identifier\n * - `(b) => b.now()` - Generate current timestamp\n * - `(b) => ...` - Custom function that returns the default value\n *\n * @example\n * ```ts\n * column(\"string\").defaultTo$((b) => b.cuid()) // Generate CUID at runtime\n * column(\"timestamp\").defaultTo$((b) => b.now()) // Generate timestamp at runtime\n * column(\"integer\").defaultTo$(42) // Static literal\n * column(\"integer\").defaultTo$((b) => Math.floor(Math.random() * 100)) // Custom function\n * ```\n */\n defaultTo$(\n value: TypeMap[TType] | ((builder: RuntimeDefaultBuilder) => RuntimeSpecial | TypeMap[TType]),\n ): Column<TType, TIn | null, TOut> {\n if (typeof value === \"function\") {\n const fn = value as (builder: RuntimeDefaultBuilder) => RuntimeSpecial | TypeMap[TType];\n const result = fn(runtimeDefaultBuilder);\n if (\n typeof result === \"object\" &&\n result !== null &&\n \"tag\" in result &&\n result.tag === \"special\"\n ) {\n this.default = { runtime: result.value };\n } else {\n // Custom function - we need to wrap the callback to call it again later\n this.default = { runtime: () => fn(runtimeDefaultBuilder) as TypeMap[TType] };\n }\n } else {\n // Direct literal value - wrap it in a function for runtime generation\n this.default = { runtime: () => value };\n }\n return this;\n }\n\n /**\n * Set a database-level default value (generated by the database, not application code).\n *\n * The database will generate the default value when inserting rows. If the database\n * doesn't support the operation, Fragno will fall back to generating the value in\n * application code.\n *\n * @param value - Either a literal value or builder callback:\n * - Literal: Any static value of the column type\n * - `(b) => b.now()` - Database-generated timestamp\n *\n * @example\n * ```ts\n * // Static defaults\n * column(\"string\").defaultTo(\"active\")\n * column(\"integer\").defaultTo(0)\n * column(\"boolean\").defaultTo(true)\n *\n * // Database-generated timestamp (with fallback)\n * column(\"timestamp\").defaultTo((b) => b.now())\n * ```\n */\n defaultTo(\n value: TypeMap[TType] | ((builder: DefaultBuilder) => DBSpecial | TypeMap[TType]),\n ): Column<TType, TIn | null, TOut> {\n if (typeof value === \"function\") {\n const fn = value as (builder: DefaultBuilder) => DBSpecial | TypeMap[TType];\n const result = fn(defaultBuilder);\n if (\n typeof result === \"object\" &&\n result !== null &&\n \"tag\" in result &&\n result.tag === \"special\"\n ) {\n this.default = { dbSpecial: result.value };\n } else {\n this.default = { value: result as TypeMap[TType] };\n }\n } else {\n this.default = { value };\n }\n return this;\n }\n\n /**\n * Generate default value for the column at runtime.\n * Used for both runtime defaults (defaultTo$) and fallback generation for\n * database defaults (defaultTo) when the database doesn't support them.\n */\n generateDefaultValue(): TypeMap[TType] | undefined {\n if (!this.default) {\n return;\n }\n\n if (\"value\" in this.default) {\n return this.default.value;\n }\n\n if (\"dbSpecial\" in this.default) {\n // Fallback generation for database-level special functions\n if (this.default.dbSpecial === \"now\") {\n return new Date(Date.now()) as TypeMap[TType];\n }\n return;\n }\n\n // Runtime defaults (defaultTo$)\n if (this.default.runtime === \"cuid\") {\n return createId() as TypeMap[TType];\n }\n if (this.default.runtime === \"now\") {\n return new Date(Date.now()) as TypeMap[TType];\n }\n\n // Custom function\n return this.default.runtime();\n }\n\n /**\n * @description This is used for type inference only. Runtime value will be undefined.\n * @internal\n */\n get $in(): TIn {\n return undefined as unknown as TIn;\n }\n\n /**\n * @description This is used for type inference only. Runtime value will be undefined.\n * @internal\n */\n get $out(): TOut {\n return undefined as unknown as TOut;\n }\n}\n\nexport class IdColumn<\n TType extends IdColumnType = IdColumnType,\n TIn = unknown,\n TOut = unknown,\n> extends Column<TType, TIn, TOut> {\n id = true;\n\n override defaultTo$(\n value: TypeMap[TType] | ((builder: RuntimeDefaultBuilder) => RuntimeSpecial | TypeMap[TType]),\n ) {\n return super.defaultTo$(value) as IdColumn<TType, TIn | null, TOut>;\n }\n\n override defaultTo(\n value: TypeMap[TType] | ((builder: DefaultBuilder) => DBSpecial | TypeMap[TType]),\n ) {\n return super.defaultTo(value) as IdColumn<TType, TIn | null, TOut>;\n }\n}\n\n/**\n * Internal ID column - used for database-native joins and foreign keys.\n * Hidden from user API by default.\n */\nexport class InternalIdColumn<TIn = unknown, TOut = unknown> extends Column<\"bigint\", TIn, TOut> {\n override role = \"internal-id\" as const;\n\n constructor() {\n super(\"bigint\");\n this.hidden();\n }\n}\n\n/**\n * Version column - used for optimistic concurrency control.\n * Automatically incremented on each update.\n */\nexport class VersionColumn<TIn = unknown, TOut = unknown> extends Column<\"integer\", TIn, TOut> {\n override role = \"version\" as const;\n\n constructor() {\n super(\"integer\");\n this.defaultTo(0).hidden();\n }\n}\n\nexport function column<TType extends keyof TypeMap>(\n type: TType,\n): Column<TType, TypeMap[TType], TypeMap[TType]> {\n return new Column(type);\n}\n\n/**\n * Create a reference column that points to another table's internal ID.\n * This is used for foreign key relationships.\n * Always uses bigint to match the internal ID type.\n */\nexport function referenceColumn(): Column<\n \"bigint\",\n string | bigint | FragnoId | FragnoReference,\n FragnoReference\n> {\n const col = new Column<\"bigint\", string | bigint | FragnoId | FragnoReference, FragnoReference>(\n \"bigint\",\n );\n col.role = \"reference\";\n return col;\n}\n\n/**\n * Create an external ID column (user-facing).\n * This is a CUID string that can be auto-generated or user-provided.\n * Input accepts string | FragnoId | null, output returns FragnoId.\n */\nexport function idColumn(): IdColumn<\"varchar(30)\", string | FragnoId | null, FragnoId> {\n const col = new IdColumn<\"varchar(30)\", string | FragnoId | null, FragnoId>(\"varchar(30)\");\n col.role = \"external-id\";\n col.defaultTo$((b) => b.cuid());\n return col;\n}\n\n/**\n * Create an internal ID column (database-native, hidden from user API).\n * Used for joins and foreign keys.\n * @internal\n */\nexport function internalIdColumn(): InternalIdColumn<null, bigint> {\n const col = new InternalIdColumn<null, bigint>();\n col.role = \"internal-id\";\n col.hidden();\n return col;\n}\n\n/**\n * Create a version column for optimistic concurrency control.\n * @internal\n */\nexport function versionColumn(): VersionColumn<null, number> {\n const col = new VersionColumn<null, number>();\n col.role = \"version\";\n col.hidden();\n return col;\n}\n\n/**\n * FragnoId represents a unified ID object that can contain external ID, internal ID, or both.\n * @internal\n *\n * For query inputs: externalId is sufficient (internalId is optional)\n * For query results: both externalId and internalId are provided\n */\nexport class FragnoId {\n readonly #externalId: string;\n readonly #internalId?: bigint;\n readonly #version: number;\n\n constructor({\n externalId,\n internalId,\n version,\n }: {\n externalId: string;\n internalId?: bigint;\n version: number;\n }) {\n this.#externalId = externalId;\n this.#internalId = internalId;\n this.#version = version;\n }\n\n /**\n * Create a FragnoId from just an external ID (for inputs)\n */\n static fromExternal(externalId: string, version: number): FragnoId {\n return new FragnoId({ externalId, version });\n }\n\n get version(): number {\n return this.#version;\n }\n\n get externalId(): string {\n return this.#externalId;\n }\n\n get internalId(): bigint | undefined {\n return this.#internalId;\n }\n\n /**\n * Get the appropriate ID for database operations\n * Prefers internal ID if available, falls back to external ID\n */\n get databaseId(): string | bigint {\n return this.#internalId ?? this.#externalId;\n }\n\n /**\n * Convert to a plain object for serialization\n */\n toJSON(): { externalId: string; internalId?: string } {\n return {\n externalId: this.#externalId,\n internalId: this.#internalId?.toString(),\n };\n }\n\n toString(): string {\n return this.#externalId;\n }\n\n valueOf(): string {\n return this.#externalId;\n }\n}\n\n/**\n * FragnoReference represents a foreign key reference to another table's internal ID.\n * Unlike FragnoId, it only contains the internal ID (bigint) of the referenced record.\n * This is used for reference columns in query results.\n * @internal\n */\nexport class FragnoReference {\n readonly #internalId: bigint;\n\n constructor(internalId: bigint) {\n this.#internalId = internalId;\n }\n\n /**\n * Create a FragnoReference from an internal ID\n */\n static fromInternal(internalId: bigint): FragnoReference {\n return new FragnoReference(internalId);\n }\n\n /**\n * Get the internal ID for database operations\n */\n get internalId(): bigint {\n return this.#internalId;\n }\n}\n\ntype RelationType = \"one\" | \"many\";\n\nexport class TableBuilder<\n TColumns extends Record<string, AnyColumn> = Record<string, AnyColumn>,\n TRelations extends Record<string, AnyRelation> = Record<string, AnyRelation>,\n TIndexes extends Record<string, Index> = Record<string, Index>,\n> {\n #name: string;\n #columns: TColumns;\n #relations: TRelations;\n #indexes: TIndexes;\n #ormName: string = \"\";\n #columnOrder: string[] = [];\n\n constructor(name: string) {\n this.#name = name;\n this.#columns = {} as TColumns;\n this.#relations = {} as TRelations;\n this.#indexes = {} as TIndexes;\n }\n\n // For alterTable to set existing state\n setColumns(columns: TColumns): void {\n this.#columns = { ...columns };\n }\n\n setRelations(relations: TRelations): void {\n this.#relations = { ...relations };\n }\n\n setIndexes(indexes: TIndexes): void {\n this.#indexes = { ...indexes };\n }\n\n // For SchemaBuilder to read collected indexes\n getIndexes(): Index[] {\n return Object.values(this.#indexes) as Index[];\n }\n\n getColumnOrder(): string[] {\n return this.#columnOrder;\n }\n\n /**\n * Add a column to the table.\n */\n addColumn<TColumnName extends string, TColumn extends AnyColumn>(\n ormName: TColumnName,\n col: TColumn,\n ): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes>;\n\n /**\n * Add a column to the table with simplified syntax.\n */\n addColumn<TColumnName extends string, TType extends keyof TypeMap>(\n ormName: TColumnName,\n type: TType,\n ): TableBuilder<\n TColumns & Record<TColumnName, Column<TType, TypeMap[TType], TypeMap[TType]>>,\n TRelations,\n TIndexes\n >;\n\n addColumn<TColumnName extends string, TColumn extends AnyColumn, TType extends keyof TypeMap>(\n ormName: TColumnName,\n colOrType: TColumn | TType,\n ): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes> {\n // Create the column if a type string was provided\n const col = typeof colOrType === \"string\" ? column(colOrType) : colOrType;\n\n // Set column metadata\n col.ormName = ormName;\n col.name = ormName;\n\n // Add column directly to this builder\n this.#columns[ormName] = col as unknown as TColumns[TColumnName];\n this.#columnOrder.push(ormName);\n\n return this as unknown as TableBuilder<\n TColumns & Record<TColumnName, TColumn>,\n TRelations,\n TIndexes\n >;\n }\n\n /**\n * Create an index on the specified columns.\n */\n createIndex<\n TIndexName extends string,\n const TColumnNames extends readonly (string & keyof TColumns)[],\n >(\n name: TIndexName,\n columns: TColumnNames,\n options?: { unique?: boolean },\n ): TableBuilder<\n TColumns,\n TRelations,\n TIndexes & Record<TIndexName, Index<ColumnsToTuple<TColumns, TColumnNames>, TColumnNames>>\n > {\n const cols = columns.map((colName) => {\n const column = this.#columns[colName];\n if (!column) {\n throw new Error(`Unknown column name ${colName}`);\n }\n return column;\n });\n\n const unique = options?.unique ?? false;\n // Safe: we're adding the index to the internal indexes object\n this.#indexes[name] = {\n name,\n columns: cols,\n columnNames: columns,\n unique,\n } as unknown as TIndexes[TIndexName];\n\n return this as unknown as TableBuilder<\n TColumns,\n TRelations,\n TIndexes & Record<TIndexName, Index<ColumnsToTuple<TColumns, TColumnNames>, TColumnNames>>\n >;\n }\n\n /**\n * Build the final table. This should be called after all columns are added.\n */\n build(): Table<TColumns, TRelations, TIndexes> {\n let idCol: AnyColumn | undefined;\n let internalIdCol: AnyColumn | undefined;\n let versionCol: AnyColumn | undefined;\n\n // TODO: Throw if user manually added version/internalId columns\n\n // Auto-add _internalId and _version columns if not already present\n if (!this.#columns[\"_internalId\"]) {\n const col = internalIdColumn();\n col.ormName = \"_internalId\";\n col.name = \"_internalId\";\n // Safe: we're adding system columns to the internal columns object\n (this.#columns as Record<string, AnyColumn>)[\"_internalId\"] = col;\n }\n\n if (!this.#columns[\"_version\"]) {\n const col = versionColumn();\n col.ormName = \"_version\";\n col.name = \"_version\";\n // Safe: we're adding system columns to the internal columns object\n (this.#columns as Record<string, AnyColumn>)[\"_version\"] = col;\n }\n\n // Use name as ormName if ormName is not set\n const ormName = this.#ormName || this.#name;\n\n const table: Table<TColumns, TRelations, TIndexes> = {\n name: this.#name,\n ormName,\n columns: this.#columns,\n relations: this.#relations,\n indexes: this.#indexes,\n getColumnByName: (name) => {\n return Object.values(this.#columns).find((c) => c.name === name);\n },\n getIdColumn: () => {\n return idCol!;\n },\n getInternalIdColumn: () => {\n return internalIdCol!;\n },\n getVersionColumn: () => {\n return versionCol!;\n },\n };\n\n // Set table reference and find special columns\n for (const k in this.#columns) {\n const column = this.#columns[k];\n if (!column) {\n continue;\n }\n\n column.tableName = table.name;\n if (column instanceof IdColumn || column.role === \"external-id\") {\n idCol = column;\n }\n if (column instanceof InternalIdColumn || column.role === \"internal-id\") {\n internalIdCol = column;\n }\n if (column instanceof VersionColumn || column.role === \"version\") {\n versionCol = column;\n }\n }\n\n if (idCol === undefined) {\n throw new Error(`there's no id column in your table ${this.#name}`);\n }\n if (internalIdCol === undefined) {\n throw new Error(`there's no internal id column in your table ${this.#name}`);\n }\n if (versionCol === undefined) {\n throw new Error(`there's no version column in your table ${this.#name}`);\n }\n\n return table;\n }\n}\n\nexport interface Schema<TTables extends Record<string, AnyTable> = Record<string, AnyTable>> {\n /**\n * @description The version of the schema, automatically incremented on each change.\n */\n version: number;\n tables: TTables;\n /**\n * @description Operations performed on this schema, in order.\n * Used to generate migrations for specific version ranges.\n */\n operations: SchemaOperation[];\n\n clone: () => Schema<TTables>;\n}\n\n/**\n * Utility type for updating a single table's relations in a schema.\n * Used to properly type the return value of addReference.\n */\ntype UpdateTableRelations<\n TTables extends Record<string, AnyTable>,\n TTableName extends keyof TTables,\n TReferenceName extends string,\n TReferencedTableName extends keyof TTables,\n TRelationType extends RelationType = RelationType,\n> = {\n [K in keyof TTables]: K extends TTableName\n ? Table<\n TTables[TTableName][\"columns\"],\n TTables[TTableName][\"relations\"] &\n Record<TReferenceName, Relation<TRelationType, TTables[TReferencedTableName]>>,\n TTables[TTableName][\"indexes\"]\n >\n : TTables[K];\n};\n\n/**\n * Utility type for updating a single table in a schema.\n * Used to properly type the return value of alterTable.\n */\ntype UpdateTable<\n TTables extends Record<string, AnyTable>,\n TTableName extends keyof TTables,\n TNewColumns extends Record<string, AnyColumn>,\n TNewRelations extends Record<string, AnyRelation>,\n TNewIndexes extends Record<string, Index>,\n> = {\n [K in keyof TTables]: K extends TTableName\n ? Table<TNewColumns, TNewRelations, TNewIndexes>\n : TTables[K];\n};\n\n/**\n * Map an array of column names to a tuple of their actual column types\n */\ntype ColumnsToTuple<\n TColumns extends Record<string, AnyColumn>,\n TColumnNames extends readonly (keyof TColumns)[],\n> = {\n [K in keyof TColumnNames]: TColumnNames[K] extends keyof TColumns\n ? TColumns[TColumnNames[K]]\n : never;\n} & AnyColumn[];\n\nexport class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {\n #tables: TTables;\n #version: number = 0;\n #operations: SchemaOperation[] = [];\n\n constructor(existingSchema?: Schema<TTables>) {\n if (existingSchema) {\n this.#tables = existingSchema.tables;\n this.#version = existingSchema.version;\n this.#operations = [...existingSchema.operations];\n } else {\n this.#tables = {} as TTables;\n }\n }\n\n /**\n * Add an existing schema to this builder.\n * Merges tables and operations from the provided schema.\n *\n * @example\n * ```ts\n * const builder = new SchemaBuilder()\n * .add(userSchema)\n * .add(postSchema)\n * .addTable(\"comments\", ...);\n * ```\n */\n mergeWithExistingSchema<TNewTables extends Record<string, AnyTable>>(\n schema: Schema<TNewTables>,\n ): SchemaBuilder<TTables & TNewTables> {\n this.#tables = { ...this.#tables, ...schema.tables } as TTables & TNewTables;\n this.#operations = [...this.#operations, ...schema.operations];\n this.#version += schema.version;\n\n return this as unknown as SchemaBuilder<TTables & TNewTables>;\n }\n\n /**\n * Add a table to the schema. Increments the version counter.\n */\n addTable<\n TTableName extends string,\n TColumns extends Record<string, AnyColumn>,\n TRelations extends Record<string, AnyRelation>,\n TIndexes extends Record<string, Index> = Record<string, Index>,\n >(\n ormName: TTableName,\n callback: (\n builder: TableBuilder<\n Record<string, AnyColumn>,\n Record<string, AnyRelation>,\n Record<string, Index>\n >,\n ) => TableBuilder<TColumns, TRelations, TIndexes>,\n ): SchemaBuilder<TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>> {\n this.#version++;\n\n const tableBuilder = new TableBuilder(ormName);\n const result = callback(tableBuilder);\n const builtTable = result.build();\n builtTable.ormName = ormName;\n\n // Collect sub-operations in order\n const subOperations: TableSubOperation[] = [];\n\n // Add user-defined columns first\n const columnOrder = result.getColumnOrder();\n for (const colName of columnOrder) {\n const col = builtTable.columns[colName];\n subOperations.push({\n type: \"add-column\",\n columnName: colName,\n column: col,\n });\n }\n\n // Add system columns (_internalId and _version) that were auto-added\n if (builtTable.columns[\"_internalId\"]) {\n subOperations.push({\n type: \"add-column\",\n columnName: \"_internalId\",\n column: builtTable.columns[\"_internalId\"],\n });\n }\n if (builtTable.columns[\"_version\"]) {\n subOperations.push({\n type: \"add-column\",\n columnName: \"_version\",\n column: builtTable.columns[\"_version\"],\n });\n }\n\n // Add indexes from builder\n for (const idx of result.getIndexes()) {\n subOperations.push({\n type: \"add-index\",\n name: idx.name,\n columns: idx.columns.map((c) => c.ormName),\n unique: idx.unique,\n });\n }\n\n // Add the add-table operation\n this.#operations.push({\n type: \"add-table\",\n tableName: ormName,\n operations: subOperations,\n });\n\n // Update tables map\n this.#tables = { ...this.#tables, [ormName]: builtTable } as TTables &\n Record<TTableName, Table<TColumns, TRelations, TIndexes>>;\n\n return this as unknown as SchemaBuilder<\n TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>\n >;\n }\n\n /**\n * Add a relation between two tables.\n *\n * @param referenceName - A name for this relation (e.g., \"author\", \"posts\")\n * @param config - Configuration specifying the relation type and foreign key mapping\n *\n * @example\n * ```ts\n * // One-to-one or many-to-one: post -> user\n * schema(s => s\n * .addTable(\"users\", t => t.addColumn(\"id\", idColumn()))\n * .addTable(\"posts\", t => t\n * .addColumn(\"id\", idColumn())\n * .addColumn(\"userId\", referenceColumn()))\n * .addReference(\"author\", {\n * type: \"one\",\n * from: { table: \"posts\", column: \"userId\" },\n * to: { table: \"users\", column: \"id\" },\n * })\n * )\n *\n * // One-to-many (inverse relation): user -> posts\n * .addReference(\"posts\", {\n * type: \"many\",\n * from: { table: \"users\", column: \"id\" },\n * to: { table: \"posts\", column: \"userId\" },\n * })\n *\n * // Self-referencing foreign key\n * .addReference(\"inviter\", {\n * type: \"one\",\n * from: { table: \"users\", column: \"invitedBy\" },\n * to: { table: \"users\", column: \"id\" },\n * })\n * ```\n */\n addReference<\n TFromTableName extends string & keyof TTables,\n TToTableName extends string & keyof TTables,\n TReferenceName extends string,\n TRelationType extends RelationType,\n >(\n referenceName: TReferenceName,\n config: {\n type: TRelationType;\n from: {\n table: TFromTableName;\n column: keyof TTables[TFromTableName][\"columns\"];\n };\n to: {\n table: TToTableName;\n column: keyof TTables[TToTableName][\"columns\"];\n };\n },\n ): SchemaBuilder<\n UpdateTableRelations<TTables, TFromTableName, TReferenceName, TToTableName, TRelationType>\n > {\n this.#version++;\n\n const table = this.#tables[config.from.table];\n const referencedTable = this.#tables[config.to.table];\n\n if (!table) {\n throw new Error(`Table ${config.from.table} not found in schema`);\n }\n if (!referencedTable) {\n throw new Error(`Referenced table ${config.to.table} not found in schema`);\n }\n\n const columnName = config.from.column as string;\n const targetColumnName = config.to.column as string;\n\n // Foreign keys always reference internal IDs, not external IDs\n // If user specifies \"id\", translate to \"_internalId\" for the actual FK\n const actualTargetColumnName = targetColumnName === \"id\" ? \"_internalId\" : targetColumnName;\n\n const column = table.columns[columnName];\n const referencedColumn = referencedTable.columns[actualTargetColumnName];\n\n if (!column) {\n throw new Error(`Column ${columnName} not found in table ${config.from.table}`);\n }\n if (!referencedColumn) {\n throw new Error(`Column ${actualTargetColumnName} not found in table ${config.to.table}`);\n }\n\n // Verify that reference columns are bigint (matching internal ID type)\n if (column.role === \"reference\" && column.type !== \"bigint\") {\n throw new Error(\n `Reference column ${columnName} must be of type bigint to match internal ID type`,\n );\n }\n\n // Create the relation (use the user-facing column name for the relation)\n const init = new ExplicitRelationInit(config.type, referencedTable, table);\n init.on.push([columnName, targetColumnName]);\n const relation = init.init(referenceName);\n\n // Add relation to the table\n table.relations[referenceName] = relation;\n\n // Record the operation\n this.#operations.push({\n type: \"add-reference\",\n tableName: config.from.table,\n referenceName,\n config: {\n type: config.type,\n from: { table: config.from.table, column: columnName },\n to: { table: config.to.table, column: actualTargetColumnName },\n },\n });\n\n // Return this with updated type\n // Safe: The relation was added to the table in place and now has the updated relations\n return this as unknown as SchemaBuilder<\n UpdateTableRelations<TTables, TFromTableName, TReferenceName, TToTableName, TRelationType>\n >;\n }\n\n /**\n * Alter an existing table by adding columns or indexes.\n * This is used for append-only schema modifications.\n *\n * @param tableName - The name of the table to modify\n * @param callback - A callback that receives a table builder for adding columns/indexes\n *\n * @example\n * ```ts\n * // Add a new column to an existing table\n * schema(s => s\n * .addTable(\"users\", t => t\n * .addColumn(\"id\", idColumn())\n * .addColumn(\"name\", column(\"string\")))\n * .alterTable(\"users\", t => t\n * .addColumn(\"email\", column(\"string\"))\n * .addColumn(\"age\", column(\"integer\").nullable())\n * .createIndex(\"idx_email\", [\"email\"]))\n * )\n * ```\n */\n alterTable<\n TTableName extends string & keyof TTables,\n TNewColumns extends Record<string, AnyColumn>,\n TNewRelations extends Record<string, AnyRelation>,\n TNewIndexes extends Record<string, Index> = Record<string, Index>,\n >(\n tableName: TTableName,\n callback: (\n builder: TableBuilder<\n TTables[TTableName][\"columns\"],\n TTables[TTableName][\"relations\"],\n Record<string, Index>\n >,\n ) => TableBuilder<TNewColumns, TNewRelations, TNewIndexes>,\n ): SchemaBuilder<UpdateTable<TTables, TTableName, TNewColumns, TNewRelations, TNewIndexes>> {\n const table = this.#tables[tableName];\n\n if (!table) {\n throw new Error(`Table ${tableName} not found in schema`);\n }\n\n // Create builder with existing table state\n const tableBuilder = new TableBuilder(tableName);\n tableBuilder.setColumns(table.columns);\n tableBuilder.setRelations(table.relations);\n tableBuilder.setIndexes(table.indexes);\n\n // Track existing columns and indexes\n const existingColumns = new Set(Object.keys(table.columns));\n const existingIndexes = new Set(Object.keys(table.indexes));\n\n // Apply modifications\n const resultBuilder = callback(\n tableBuilder as TableBuilder<\n TTables[TTableName][\"columns\"],\n TTables[TTableName][\"relations\"],\n Record<string, Index>\n >,\n );\n const newTable = resultBuilder.build();\n\n // Collect sub-operations\n const subOperations: TableSubOperation[] = [];\n\n // Find new columns (preserve order from builder)\n const columnOrder = resultBuilder.getColumnOrder();\n for (const colName of columnOrder) {\n if (!existingColumns.has(colName)) {\n subOperations.push({\n type: \"add-column\",\n columnName: colName,\n column: newTable.columns[colName],\n });\n }\n }\n\n // Add only new indexes\n for (const idx of resultBuilder.getIndexes()) {\n if (!existingIndexes.has(idx.name)) {\n subOperations.push({\n type: \"add-index\",\n name: idx.name,\n columns: idx.columns.map((c) => c.ormName),\n unique: idx.unique,\n });\n }\n }\n\n if (subOperations.length > 0) {\n this.#version++;\n this.#operations.push({\n type: \"alter-table\",\n tableName,\n operations: subOperations,\n });\n }\n\n // Update table reference in schema\n this.#tables[tableName] = newTable as unknown as TTables[TTableName];\n\n // Set table name for all columns\n for (const col of Object.values(newTable.columns)) {\n col.tableName = newTable.name;\n }\n\n return this as unknown as SchemaBuilder<\n UpdateTable<TTables, TTableName, TNewColumns, TNewRelations, TNewIndexes>\n >;\n }\n\n /**\n * Build the final schema. This should be called after all tables are added.\n */\n build(): Schema<TTables> {\n const operations = this.#operations;\n const version = this.#version;\n const tables = this.#tables;\n\n const schema: Schema<TTables> = {\n version,\n tables,\n operations,\n clone: () => {\n const cloneTables: Record<string, AnyTable> = {};\n\n for (const [k, v] of Object.entries(tables)) {\n // Create a new table with cloned columns\n const clonedColumns: Record<string, AnyColumn> = {};\n for (const [colName, col] of Object.entries(v.columns)) {\n // Create a new column with the same properties, preserving the column type\n let clonedCol: AnyColumn;\n if (col instanceof InternalIdColumn) {\n clonedCol = new InternalIdColumn();\n } else if (col instanceof VersionColumn) {\n clonedCol = new VersionColumn();\n } else if (col instanceof IdColumn) {\n clonedCol = new IdColumn(col.type);\n } else {\n clonedCol = new Column(col.type);\n }\n\n clonedCol.name = col.name;\n clonedCol.ormName = col.ormName;\n clonedCol.isNullable = col.isNullable;\n clonedCol.role = col.role;\n clonedCol.isHidden = col.isHidden;\n clonedCol.default = col.default;\n clonedCol.tableName = col.tableName;\n clonedColumns[colName] = clonedCol;\n }\n\n cloneTables[k] = {\n ...v,\n columns: clonedColumns,\n };\n }\n\n return new SchemaBuilder<TTables>({\n version,\n tables: cloneTables as TTables,\n operations: [...operations],\n clone: () => {\n throw new Error(\"Cannot clone during clone\");\n },\n }).build();\n },\n };\n\n return schema;\n }\n\n /**\n * Get the current version of the schema builder.\n */\n getVersion(): number {\n return this.#version;\n }\n}\n\n/**\n * Create a new schema with callback pattern.\n */\nexport function schema<const TTables extends Record<string, AnyTable> = {}>(\n callback: (builder: SchemaBuilder<{}>) => SchemaBuilder<TTables>,\n): Schema<TTables> {\n return callback(new SchemaBuilder()).build();\n}\n\nexport function compileForeignKey(key: ForeignKey, nameType: \"sql\" | \"orm\" = \"orm\") {\n return {\n name: key.name,\n table: nameType === \"sql\" ? key.table.name : key.table.ormName,\n referencedTable: nameType === \"sql\" ? key.referencedTable.name : key.referencedTable.ormName,\n referencedColumns: key.referencedColumns.map((col) =>\n nameType === \"sql\" ? col.name : col.ormName,\n ),\n columns: key.columns.map((col) => (nameType === \"sql\" ? col.name : col.ormName)),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"create.js","names":["defaultBuilder: DefaultBuilder","runtimeDefaultBuilder: RuntimeDefaultBuilder","#externalId","#internalId","#version","#name","#columns","#relations","#indexes","#columnOrder","column","idCol: AnyColumn | undefined","internalIdCol: AnyColumn | undefined","versionCol: AnyColumn | undefined","#tables","#operations","#registerTableName","#registerIndexName","#tableNames","#indexNames","schema","subOperations: TableSubOperation[]","cloneTables: Record<string, AnyTable>","clonedColumns: Record<string, AnyColumn>","clonedCol: AnyColumn","clonedSchema: Schema<TTables>"],"sources":["../../src/schema/create.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { createId } from \"../id\";\nimport type { DbNow } from \"../query/db-now\";\nimport type { Prettify } from \"../util/types\";\nimport { createTableStandardSchemaProps, createTableValidator } from \"./validator\";\n\nexport { generateId } from \"./generate-id\";\nexport { FragnoDbValidationError } from \"./validator\";\n\nexport type AnySchema = Schema<Record<string, AnyTable>>;\n\nexport type AnyRelation = Relation;\n\nexport type AnyTable = Table;\n\nexport type AnyColumn =\n | Column<keyof TypeMap, unknown, unknown>\n | IdColumn<IdColumnType, unknown, unknown>\n | InternalIdColumn<unknown, unknown>\n | VersionColumn<unknown, unknown>;\n/**\n * Sub-operations that can be performed within table operations.\n * These are stored in order within add-table and alter-table operations.\n */\nexport type TableSubOperation =\n | { type: \"add-column\"; columnName: string; column: AnyColumn }\n | { type: \"add-index\"; name: string; columns: string[]; unique: boolean }\n | {\n type: \"add-foreign-key\";\n name: string;\n columns: string[];\n referencedTable: string;\n referencedColumns: string[];\n };\n\n/**\n * Operations that can be performed on a schema during its definition.\n * These are tracked so we can generate migrations for specific version ranges.\n */\nexport type SchemaOperation =\n | {\n type: \"add-table\";\n tableName: string;\n operations: TableSubOperation[]; // Ordered list of sub-operations\n }\n | {\n type: \"alter-table\";\n tableName: string;\n operations: TableSubOperation[]; // Ordered list of sub-operations\n }\n | {\n type: \"add-reference\";\n tableName: string; // The table that has the foreign key\n referenceName: string;\n config: {\n type: \"one\" | \"many\";\n from: { table: string; column: string };\n to: { table: string; column: string };\n };\n };\n\nexport interface ForeignKey {\n name: string;\n table: AnyTable;\n columns: AnyColumn[];\n\n referencedTable: AnyTable;\n referencedColumns: AnyColumn[];\n}\n\nclass RelationInit<\n TRelationType extends RelationType,\n TTables extends Record<string, AnyTable>,\n TTableName extends keyof TTables,\n> {\n type: TRelationType;\n referencedTable: TTables[TTableName];\n referencer: AnyTable;\n on: [string, string][] = [];\n\n constructor(type: TRelationType, referencedTable: TTables[TTableName], referencer: AnyTable) {\n this.type = type;\n this.referencedTable = referencedTable;\n this.referencer = referencer;\n }\n}\n\nexport interface Index<\n TColumns extends AnyColumn[] = AnyColumn[],\n TColumnNames extends readonly string[] = readonly string[],\n> {\n name: string;\n columns: TColumns;\n columnNames: TColumnNames;\n unique: boolean;\n}\n\nexport class ExplicitRelationInit<\n TRelationType extends RelationType,\n TTables extends Record<string, AnyTable>,\n TTableName extends keyof TTables,\n> extends RelationInit<TRelationType, TTables, TTableName> {\n init(name: string): Relation<TRelationType, TTables[TTableName]> {\n const id = `${this.referencer.name}_${this.referencedTable.name}`;\n\n return {\n id,\n on: this.on,\n name,\n referencer: this.referencer,\n table: this.referencedTable,\n type: this.type,\n };\n }\n}\n\nexport interface Relation<\n TRelationType extends RelationType = RelationType,\n TTable extends AnyTable = AnyTable,\n> {\n id: string;\n name: string;\n type: TRelationType;\n\n table: TTable;\n referencer: AnyTable;\n\n on: [string, string][];\n}\n\ntype PickNullable<T> = {\n [P in keyof T as null extends T[P] ? P : never]: T[P];\n};\n\ntype PickNotNullable<T> = {\n [P in keyof T as null extends T[P] ? never : P]: T[P];\n};\n\ntype RawInsertValuesFromColumns<TColumns extends Record<string, AnyColumn>> = {\n [K in keyof TColumns as string extends K ? never : K]: TColumns[K][\"$in\"];\n};\n\ntype TableInsertValuesFromColumns<TColumns extends Record<string, AnyColumn>> = Prettify<\n Partial<PickNullable<RawInsertValuesFromColumns<TColumns>>> &\n PickNotNullable<RawInsertValuesFromColumns<TColumns>>\n>;\n\nexport type TableInsertValues<T extends AnyTable> = TableInsertValuesFromColumns<T[\"columns\"]>;\n\nexport type TableUnknownKeysMode = \"strip\" | \"strict\";\n\nexport type TableValidationOptions = {\n unknownKeys?: TableUnknownKeysMode;\n};\n\nexport interface Table<\n TColumns extends Record<string, AnyColumn> = Record<string, AnyColumn>,\n TRelations extends Record<string, AnyRelation> = Record<string, AnyRelation>,\n TIndexes extends Record<string, Index> = Record<string, Index>,\n> {\n /**\n * Standard Schema-compatible validator for insert values.\n */\n \"~standard\": StandardSchemaV1.Props<\n TableInsertValuesFromColumns<TColumns>,\n TableInsertValuesFromColumns<TColumns>\n >;\n name: string;\n\n columns: TColumns;\n relations: TRelations;\n indexes: TIndexes;\n\n /**\n * Validate insert values at runtime.\n */\n validate: (\n value: unknown,\n options?: TableValidationOptions,\n ) => TableInsertValuesFromColumns<TColumns>;\n\n /**\n * Get column by name\n */\n getColumnByName: (name: string) => AnyColumn | undefined;\n /**\n * Get the external ID column (user-facing)\n */\n getIdColumn: () => AnyColumn;\n /**\n * Get the internal ID column (database-native, used for joins)\n */\n getInternalIdColumn: () => AnyColumn;\n /**\n * Get the version column (for optimistic concurrency control)\n */\n getVersionColumn: () => AnyColumn;\n}\n\ntype DBSpecial = { tag: \"special\"; value: \"now\" };\ntype RuntimeSpecial = { tag: \"special\"; value: \"cuid\" | \"now\" };\n\n/**\n * Builder for database-level default values.\n */\nexport interface DefaultBuilder {\n /** Database-generated timestamp (DEFAULT NOW()) */\n now(): DBSpecial;\n}\n\n/**\n * Builder for runtime-generated default values.\n */\nexport interface RuntimeDefaultBuilder {\n /** Generate CUID identifier */\n cuid(): RuntimeSpecial;\n /** Generate current timestamp */\n now(): RuntimeSpecial;\n}\n\nconst defaultBuilder: DefaultBuilder = {\n now: () => ({ tag: \"special\", value: \"now\" }),\n};\n\nconst runtimeDefaultBuilder: RuntimeDefaultBuilder = {\n cuid: () => ({ tag: \"special\", value: \"cuid\" }),\n now: () => ({ tag: \"special\", value: \"now\" }),\n};\n\ntype IdColumnType = `varchar(${number})`;\n\nexport type TypeMap = {\n string: string;\n bigint: bigint;\n integer: number;\n decimal: number;\n bool: boolean;\n json: unknown;\n /**\n * this follows the same specs as Prisma `Bytes` for consistency.\n */\n binary: Uint8Array;\n date: Date;\n timestamp: Date;\n} & Record<`varchar(${number})`, string>;\n\nexport class Column<TType extends keyof TypeMap, TIn = unknown, TOut = unknown> {\n type: TType;\n name: string = \"\";\n isNullable: boolean = false;\n role: \"external-id\" | \"internal-id\" | \"version\" | \"reference\" | \"regular\" = \"regular\";\n isHidden: boolean = false;\n\n default?:\n | { value: TypeMap[TType] }\n | { dbSpecial: \"now\" }\n | { runtime: \"cuid\" | \"now\" | (() => TypeMap[TType]) };\n\n tableName: string = \"\";\n\n constructor(type: TType) {\n this.type = type;\n }\n\n nullable<TNullable extends boolean = true>(nullable?: TNullable) {\n this.isNullable = nullable ?? true;\n\n return this as Column<\n TType,\n TNullable extends true ? TIn | null : Exclude<TIn, null>,\n TNullable extends true ? TOut | null : Exclude<TOut, null>\n >;\n }\n\n hidden<THidden extends boolean = true>(hidden?: THidden) {\n this.isHidden = hidden ?? true;\n return this as Column<TType, null, null>;\n }\n\n /**\n * Generate default value at runtime in application code (not in the database).\n *\n * Use this when you need values generated in your application code, either because:\n * - Your database doesn't support the operation (e.g., generating CUIDs)\n * - You want consistent behavior across all databases\n * - You need custom generation logic\n *\n * @param value - Either a literal value or builder callback:\n * - Literal: Any static value of the column type\n * - `(b) => b.cuid()` - Generate a CUID identifier\n * - `(b) => b.now()` - Generate current timestamp\n * - `(b) => ...` - Custom function that returns the default value\n *\n * @example\n * ```ts\n * column(\"string\").defaultTo$((b) => b.cuid()) // Generate CUID at runtime\n * column(\"timestamp\").defaultTo$((b) => b.now()) // Generate timestamp at runtime\n * column(\"integer\").defaultTo$(42) // Static literal\n * column(\"integer\").defaultTo$((b) => Math.floor(Math.random() * 100)) // Custom function\n * ```\n */\n defaultTo$(\n value: TypeMap[TType] | ((builder: RuntimeDefaultBuilder) => RuntimeSpecial | TypeMap[TType]),\n ): Column<TType, TIn | null, TOut> {\n if (typeof value === \"function\") {\n const fn = value as (builder: RuntimeDefaultBuilder) => RuntimeSpecial | TypeMap[TType];\n const result = fn(runtimeDefaultBuilder);\n if (\n typeof result === \"object\" &&\n result !== null &&\n \"tag\" in result &&\n result.tag === \"special\"\n ) {\n this.default = { runtime: result.value };\n } else {\n // Custom function - we need to wrap the callback to call it again later\n this.default = { runtime: () => fn(runtimeDefaultBuilder) as TypeMap[TType] };\n }\n } else {\n // Direct literal value - wrap it in a function for runtime generation\n this.default = { runtime: () => value };\n }\n return this;\n }\n\n /**\n * Set a database-level default value (generated by the database, not application code).\n *\n * The database will generate the default value when inserting rows. If the database\n * doesn't support the operation, Fragno will fall back to generating the value in\n * application code.\n *\n * @param value - Either a literal value or builder callback:\n * - Literal: Any static value of the column type\n * - `(b) => b.now()` - Database-generated timestamp\n *\n * @example\n * ```ts\n * // Static defaults\n * column(\"string\").defaultTo(\"active\")\n * column(\"integer\").defaultTo(0)\n * column(\"boolean\").defaultTo(true)\n *\n * // Database-generated timestamp (with fallback)\n * column(\"timestamp\").defaultTo((b) => b.now())\n * ```\n */\n defaultTo(\n value: TypeMap[TType] | ((builder: DefaultBuilder) => DBSpecial | TypeMap[TType]),\n ): Column<TType, TIn | null, TOut> {\n if (typeof value === \"function\") {\n const fn = value as (builder: DefaultBuilder) => DBSpecial | TypeMap[TType];\n const result = fn(defaultBuilder);\n if (\n typeof result === \"object\" &&\n result !== null &&\n \"tag\" in result &&\n result.tag === \"special\"\n ) {\n this.default = { dbSpecial: result.value };\n } else {\n this.default = { value: result as TypeMap[TType] };\n }\n } else {\n this.default = { value };\n }\n return this;\n }\n\n /**\n * Generate default value for the column at runtime.\n * Used for both runtime defaults (defaultTo$) and fallback generation for\n * database defaults (defaultTo) when the database doesn't support them.\n */\n generateDefaultValue(): TypeMap[TType] | undefined {\n if (!this.default) {\n return;\n }\n\n if (\"value\" in this.default) {\n return this.default.value;\n }\n\n if (\"dbSpecial\" in this.default) {\n // Fallback generation for database-level special functions\n if (this.default.dbSpecial === \"now\") {\n return new Date(Date.now()) as TypeMap[TType];\n }\n return;\n }\n\n // Runtime defaults (defaultTo$)\n if (this.default.runtime === \"cuid\") {\n return createId() as TypeMap[TType];\n }\n if (this.default.runtime === \"now\") {\n return new Date(Date.now()) as TypeMap[TType];\n }\n\n // Custom function\n return this.default.runtime();\n }\n\n /**\n * @description This is used for type inference only. Runtime value will be undefined.\n * @internal\n */\n get $in(): TIn {\n return undefined as unknown as TIn;\n }\n\n /**\n * @description This is used for type inference only. Runtime value will be undefined.\n * @internal\n */\n get $out(): TOut {\n return undefined as unknown as TOut;\n }\n}\n\nexport class IdColumn<\n TType extends IdColumnType = IdColumnType,\n TIn = unknown,\n TOut = unknown,\n> extends Column<TType, TIn, TOut> {\n id = true;\n\n override defaultTo$(\n value: TypeMap[TType] | ((builder: RuntimeDefaultBuilder) => RuntimeSpecial | TypeMap[TType]),\n ) {\n return super.defaultTo$(value) as IdColumn<TType, TIn | null, TOut>;\n }\n\n override defaultTo(\n value: TypeMap[TType] | ((builder: DefaultBuilder) => DBSpecial | TypeMap[TType]),\n ) {\n return super.defaultTo(value) as IdColumn<TType, TIn | null, TOut>;\n }\n}\n\n/**\n * Internal ID column - used for database-native joins and foreign keys.\n * Hidden from user API by default.\n */\nexport class InternalIdColumn<TIn = unknown, TOut = unknown> extends Column<\"bigint\", TIn, TOut> {\n override role = \"internal-id\" as const;\n\n constructor() {\n super(\"bigint\");\n this.hidden();\n }\n}\n\n/**\n * Version column - used for optimistic concurrency control.\n * Automatically incremented on each update.\n */\nexport class VersionColumn<TIn = unknown, TOut = unknown> extends Column<\"integer\", TIn, TOut> {\n override role = \"version\" as const;\n\n constructor() {\n super(\"integer\");\n this.defaultTo(0).hidden();\n }\n}\n\ntype ColumnInput<TType extends keyof TypeMap> =\n | TypeMap[TType]\n | (TType extends \"timestamp\" | \"date\" ? DbNow : never);\n\nexport function column<TType extends keyof TypeMap>(\n type: TType,\n): Column<TType, ColumnInput<TType>, TypeMap[TType]> {\n return new Column(type);\n}\n\n/**\n * Create a reference column that points to another table's internal ID.\n * This is used for foreign key relationships.\n * Always uses bigint to match the internal ID type.\n */\nexport function referenceColumn(): Column<\n \"bigint\",\n string | bigint | FragnoId | FragnoReference,\n FragnoReference\n> {\n const col = new Column<\"bigint\", string | bigint | FragnoId | FragnoReference, FragnoReference>(\n \"bigint\",\n );\n col.role = \"reference\";\n return col;\n}\n\n/**\n * Create an external ID column (user-facing).\n * This is a CUID string that can be auto-generated or user-provided.\n * Input accepts string | FragnoId | null, output returns FragnoId.\n */\nexport function idColumn(): IdColumn<\"varchar(30)\", string | FragnoId | null, FragnoId> {\n const col = new IdColumn<\"varchar(30)\", string | FragnoId | null, FragnoId>(\"varchar(30)\");\n col.role = \"external-id\";\n col.defaultTo$((b) => b.cuid());\n return col;\n}\n\n/**\n * Create an internal ID column (database-native, hidden from user API).\n * Used for joins and foreign keys.\n * @internal\n */\nexport function internalIdColumn(): InternalIdColumn<null, bigint> {\n const col = new InternalIdColumn<null, bigint>();\n col.role = \"internal-id\";\n col.hidden();\n return col;\n}\n\n/**\n * Create a version column for optimistic concurrency control.\n * @internal\n */\nexport function versionColumn(): VersionColumn<null, number> {\n const col = new VersionColumn<null, number>();\n col.role = \"version\";\n col.hidden();\n return col;\n}\n\n/**\n * FragnoId represents a unified ID object that can contain external ID, internal ID, or both.\n * @internal\n *\n * For query inputs: externalId is sufficient (internalId is optional)\n * For query results: both externalId and internalId are provided\n */\nexport class FragnoId {\n readonly #externalId: string;\n readonly #internalId?: bigint;\n readonly #version: number;\n\n constructor({\n externalId,\n internalId,\n version,\n }: {\n externalId: string;\n internalId?: bigint;\n version: number;\n }) {\n this.#externalId = externalId;\n this.#internalId = internalId;\n this.#version = version;\n }\n\n /**\n * Create a FragnoId from just an external ID (for inputs)\n */\n static fromExternal(externalId: string, version: number): FragnoId {\n return new FragnoId({ externalId, version });\n }\n\n get version(): number {\n return this.#version;\n }\n\n get externalId(): string {\n return this.#externalId;\n }\n\n get internalId(): bigint | undefined {\n return this.#internalId;\n }\n\n /**\n * Get the appropriate ID for database operations\n * Prefers internal ID if available, falls back to external ID\n */\n get databaseId(): string | bigint {\n return this.#internalId ?? this.#externalId;\n }\n\n /**\n * Convert to a plain object for serialization\n */\n toJSON(): { externalId: string; internalId?: string } {\n return {\n externalId: this.#externalId,\n internalId: this.#internalId?.toString(),\n };\n }\n\n toString(): string {\n return this.#externalId;\n }\n\n valueOf(): string {\n return this.#externalId;\n }\n}\n\n/**\n * FragnoReference represents a foreign key reference to another table's internal ID.\n * Unlike FragnoId, it only contains the internal ID (bigint) of the referenced record.\n * This is used for reference columns in query results.\n * @internal\n */\nexport class FragnoReference {\n readonly #internalId: bigint;\n\n constructor(internalId: bigint) {\n this.#internalId = internalId;\n }\n\n /**\n * Create a FragnoReference from an internal ID\n */\n static fromInternal(internalId: bigint): FragnoReference {\n return new FragnoReference(internalId);\n }\n\n /**\n * Get the internal ID for database operations\n */\n get internalId(): bigint {\n return this.#internalId;\n }\n}\n\nconst validationClasses = { FragnoId, FragnoReference };\n\ntype RelationType = \"one\" | \"many\";\n\nexport class TableBuilder<\n TColumns extends Record<string, AnyColumn> = Record<string, AnyColumn>,\n TRelations extends Record<string, AnyRelation> = Record<string, AnyRelation>,\n TIndexes extends Record<string, Index> = Record<string, Index>,\n> {\n #name: string;\n #columns: TColumns;\n #relations: TRelations;\n #indexes: TIndexes;\n #columnOrder: string[] = [];\n\n constructor(name: string) {\n this.#name = name;\n this.#columns = {} as TColumns;\n this.#relations = {} as TRelations;\n this.#indexes = {} as TIndexes;\n }\n\n // For alterTable to set existing state\n setColumns(columns: TColumns): void {\n this.#columns = { ...columns };\n }\n\n setRelations(relations: TRelations): void {\n this.#relations = { ...relations };\n }\n\n setIndexes(indexes: TIndexes): void {\n this.#indexes = { ...indexes };\n }\n\n // For SchemaBuilder to read collected indexes\n getIndexes(): Index[] {\n return Object.values(this.#indexes) as Index[];\n }\n\n getColumnOrder(): string[] {\n return this.#columnOrder;\n }\n\n /**\n * Add a column to the table.\n */\n addColumn<TColumnName extends string, TColumn extends AnyColumn>(\n name: TColumnName,\n col: TColumn,\n ): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes>;\n\n /**\n * Add a column to the table with simplified syntax.\n */\n addColumn<TColumnName extends string, TType extends keyof TypeMap>(\n name: TColumnName,\n type: TType,\n ): TableBuilder<\n TColumns & Record<TColumnName, Column<TType, ColumnInput<TType>, TypeMap[TType]>>,\n TRelations,\n TIndexes\n >;\n\n addColumn<TColumnName extends string, TColumn extends AnyColumn, TType extends keyof TypeMap>(\n name: TColumnName,\n colOrType: TColumn | TType,\n ): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes> {\n // Create the column if a type string was provided\n const col = typeof colOrType === \"string\" ? column(colOrType) : colOrType;\n\n // Set column metadata\n col.name = name;\n\n // Add column directly to this builder\n this.#columns[name] = col as unknown as TColumns[TColumnName];\n this.#columnOrder.push(name);\n\n return this as unknown as TableBuilder<\n TColumns & Record<TColumnName, TColumn>,\n TRelations,\n TIndexes\n >;\n }\n\n /**\n * Create an index on the specified columns.\n */\n createIndex<\n TIndexName extends string,\n const TColumnNames extends readonly (string & keyof TColumns)[],\n >(\n name: TIndexName,\n columns: TColumnNames,\n options?: { unique?: boolean },\n ): TableBuilder<\n TColumns,\n TRelations,\n TIndexes & Record<TIndexName, Index<ColumnsToTuple<TColumns, TColumnNames>, TColumnNames>>\n > {\n const cols = columns.map((colName) => {\n const column = this.#columns[colName];\n if (!column) {\n throw new Error(`Unknown column name ${colName}`);\n }\n return column;\n });\n\n const unique = options?.unique ?? false;\n // Safe: we're adding the index to the internal indexes object\n this.#indexes[name] = {\n name,\n columns: cols,\n columnNames: columns,\n unique,\n } as unknown as TIndexes[TIndexName];\n\n return this as unknown as TableBuilder<\n TColumns,\n TRelations,\n TIndexes & Record<TIndexName, Index<ColumnsToTuple<TColumns, TColumnNames>, TColumnNames>>\n >;\n }\n\n /**\n * Build the final table. This should be called after all columns are added.\n */\n build(): Table<TColumns, TRelations, TIndexes> {\n let idCol: AnyColumn | undefined;\n let internalIdCol: AnyColumn | undefined;\n let versionCol: AnyColumn | undefined;\n\n // TODO: Throw if user manually added version/internalId columns\n\n // Auto-add _internalId and _version columns if not already present\n if (!this.#columns[\"_internalId\"]) {\n const col = internalIdColumn();\n col.name = \"_internalId\";\n // Safe: we're adding system columns to the internal columns object\n (this.#columns as Record<string, AnyColumn>)[\"_internalId\"] = col;\n }\n\n if (!this.#columns[\"_version\"]) {\n const col = versionColumn();\n col.name = \"_version\";\n // Safe: we're adding system columns to the internal columns object\n (this.#columns as Record<string, AnyColumn>)[\"_version\"] = col;\n }\n\n const table = {\n name: this.#name,\n columns: this.#columns,\n relations: this.#relations,\n indexes: this.#indexes,\n getColumnByName: (name) => {\n return Object.values(this.#columns).find((c) => c.name === name);\n },\n getIdColumn: () => {\n return idCol!;\n },\n getInternalIdColumn: () => {\n return internalIdCol!;\n },\n getVersionColumn: () => {\n return versionCol!;\n },\n } as Table<TColumns, TRelations, TIndexes>;\n\n table[\"~standard\"] = createTableStandardSchemaProps(table, validationClasses);\n table.validate = createTableValidator(table, validationClasses);\n\n // Set table reference and find special columns\n for (const k in this.#columns) {\n const column = this.#columns[k];\n if (!column) {\n continue;\n }\n\n column.tableName = table.name;\n if (column instanceof IdColumn || column.role === \"external-id\") {\n idCol = column;\n }\n if (column instanceof InternalIdColumn || column.role === \"internal-id\") {\n internalIdCol = column;\n }\n if (column instanceof VersionColumn || column.role === \"version\") {\n versionCol = column;\n }\n }\n\n if (idCol === undefined) {\n throw new Error(`there's no id column in your table ${this.#name}`);\n }\n if (internalIdCol === undefined) {\n throw new Error(`there's no internal id column in your table ${this.#name}`);\n }\n if (versionCol === undefined) {\n throw new Error(`there's no version column in your table ${this.#name}`);\n }\n\n return table;\n }\n}\n\nexport interface Schema<TTables extends Record<string, AnyTable> = Record<string, AnyTable>> {\n /**\n * @description The name of the schema (required).\n */\n name: string;\n /**\n * @description The version of the schema, automatically incremented on each change.\n */\n version: number;\n tables: TTables;\n /**\n * @description Operations performed on this schema, in order.\n * Used to generate migrations for specific version ranges.\n */\n operations: SchemaOperation[];\n\n clone: () => Schema<TTables>;\n}\n\n/**\n * Utility type for updating a single table's relations in a schema.\n * Used to properly type the return value of addReference.\n */\ntype UpdateTableRelations<\n TTables extends Record<string, AnyTable>,\n TTableName extends keyof TTables,\n TReferenceName extends string,\n TReferencedTableName extends keyof TTables,\n TRelationType extends RelationType = RelationType,\n> = {\n [K in keyof TTables]: K extends TTableName\n ? Table<\n TTables[TTableName][\"columns\"],\n TTables[TTableName][\"relations\"] &\n Record<TReferenceName, Relation<TRelationType, TTables[TReferencedTableName]>>,\n TTables[TTableName][\"indexes\"]\n >\n : TTables[K];\n};\n\n/**\n * Utility type for updating a single table in a schema.\n * Used to properly type the return value of alterTable.\n */\ntype UpdateTable<\n TTables extends Record<string, AnyTable>,\n TTableName extends keyof TTables,\n TNewColumns extends Record<string, AnyColumn>,\n TNewRelations extends Record<string, AnyRelation>,\n TNewIndexes extends Record<string, Index>,\n> = {\n [K in keyof TTables]: K extends TTableName\n ? Table<TNewColumns, TNewRelations, TNewIndexes>\n : TTables[K];\n};\n\n/**\n * Map an array of column names to a tuple of their actual column types\n */\ntype ColumnsToTuple<\n TColumns extends Record<string, AnyColumn>,\n TColumnNames extends readonly (keyof TColumns)[],\n> = {\n [K in keyof TColumnNames]: TColumnNames[K] extends keyof TColumns\n ? TColumns[TColumnNames[K]]\n : never;\n} & AnyColumn[];\n\nexport class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {\n #name: string;\n #tables: TTables;\n #version: number = 0;\n #operations: SchemaOperation[] = [];\n #tableNames: Set<string> = new Set();\n #indexNames: Set<string> = new Set();\n\n constructor(name: string, existingSchema?: Schema<TTables>) {\n this.#name = name;\n if (existingSchema) {\n this.#tables = existingSchema.tables;\n this.#version = existingSchema.version;\n this.#operations = [...existingSchema.operations];\n } else {\n this.#tables = {} as TTables;\n }\n\n for (const table of Object.values(this.#tables)) {\n this.#registerTableName(table.name);\n for (const index of Object.values(table.indexes)) {\n this.#registerIndexName(index.name, table.name);\n }\n }\n }\n\n #registerTableName(name: string): void {\n if (this.#tableNames.has(name)) {\n throw new Error(`Duplicate table name \"${name}\" in schema \"${this.#name}\".`);\n }\n this.#tableNames.add(name);\n }\n\n #registerIndexName(name: string, tableName: string): void {\n if (this.#indexNames.has(name)) {\n throw new Error(\n `Duplicate index name \"${name}\" in schema \"${this.#name}\". Index names must be unique across tables (conflict on \"${tableName}\").`,\n );\n }\n this.#indexNames.add(name);\n }\n\n /**\n * Add an existing schema to this builder.\n * Merges tables and operations from the provided schema.\n *\n * @example\n * ```ts\n * const builder = new SchemaBuilder(\"combined\")\n * .add(userSchema)\n * .add(postSchema)\n * .addTable(\"comments\", ...);\n * ```\n */\n mergeWithExistingSchema<TNewTables extends Record<string, AnyTable>>(\n schema: Schema<TNewTables>,\n ): SchemaBuilder<TTables & TNewTables> {\n for (const table of Object.values(schema.tables)) {\n if (this.#tableNames.has(table.name)) {\n throw new Error(\n `Duplicate table name \"${table.name}\" in schema \"${this.#name}\" when merging.`,\n );\n }\n for (const index of Object.values(table.indexes)) {\n if (this.#indexNames.has(index.name)) {\n throw new Error(\n `Duplicate index name \"${index.name}\" in schema \"${this.#name}\" when merging (conflict on \"${table.name}\").`,\n );\n }\n }\n }\n\n this.#tables = { ...this.#tables, ...schema.tables } as TTables & TNewTables;\n this.#operations = [...this.#operations, ...schema.operations];\n this.#version += schema.version;\n\n for (const table of Object.values(schema.tables)) {\n this.#tableNames.add(table.name);\n for (const index of Object.values(table.indexes)) {\n this.#indexNames.add(index.name);\n }\n }\n\n return this as unknown as SchemaBuilder<TTables & TNewTables>;\n }\n\n /**\n * Add a table to the schema. Increments the version counter.\n */\n addTable<\n TTableName extends string,\n TColumns extends Record<string, AnyColumn>,\n TRelations extends Record<string, AnyRelation>,\n TIndexes extends Record<string, Index> = Record<string, Index>,\n >(\n name: TTableName,\n callback: (\n builder: TableBuilder<\n Record<string, AnyColumn>,\n Record<string, AnyRelation>,\n Record<string, Index>\n >,\n ) => TableBuilder<TColumns, TRelations, TIndexes>,\n ): SchemaBuilder<TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>> {\n this.#version++;\n\n if (this.#tableNames.has(name)) {\n throw new Error(`Duplicate table name \"${name}\" in schema \"${this.#name}\".`);\n }\n\n const tableBuilder = new TableBuilder(name);\n const result = callback(tableBuilder);\n const builtTable = result.build();\n const indexNames = result.getIndexes().map((idx) => idx.name);\n\n for (const indexName of indexNames) {\n if (this.#indexNames.has(indexName)) {\n throw new Error(\n `Duplicate index name \"${indexName}\" in schema \"${this.#name}\". Index names must be unique across tables (conflict on \"${name}\").`,\n );\n }\n }\n\n // Collect sub-operations in order\n const subOperations: TableSubOperation[] = [];\n\n // Add user-defined columns first\n const columnOrder = result.getColumnOrder();\n for (const colName of columnOrder) {\n const col = builtTable.columns[colName];\n subOperations.push({\n type: \"add-column\",\n columnName: colName,\n column: col,\n });\n }\n\n // Add system columns (_internalId and _version) that were auto-added\n if (builtTable.columns[\"_internalId\"]) {\n subOperations.push({\n type: \"add-column\",\n columnName: \"_internalId\",\n column: builtTable.columns[\"_internalId\"],\n });\n }\n if (builtTable.columns[\"_version\"]) {\n subOperations.push({\n type: \"add-column\",\n columnName: \"_version\",\n column: builtTable.columns[\"_version\"],\n });\n }\n\n // Add indexes from builder\n for (const idx of result.getIndexes()) {\n subOperations.push({\n type: \"add-index\",\n name: idx.name,\n columns: idx.columns.map((c) => c.name),\n unique: idx.unique,\n });\n }\n\n // Add the add-table operation\n this.#operations.push({\n type: \"add-table\",\n tableName: name,\n operations: subOperations,\n });\n\n // Update tables map\n this.#tables = { ...this.#tables, [name]: builtTable } as TTables &\n Record<TTableName, Table<TColumns, TRelations, TIndexes>>;\n this.#tableNames.add(name);\n for (const indexName of indexNames) {\n this.#indexNames.add(indexName);\n }\n\n return this as unknown as SchemaBuilder<\n TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>\n >;\n }\n\n /**\n * Add a relation between two tables.\n *\n * @param referenceName - A name for this relation (e.g., \"author\", \"posts\")\n * @param config - Configuration specifying the relation type and foreign key mapping\n *\n * @example\n * ```ts\n * // One-to-one or many-to-one: post -> user\n * schema(\"blog\", s => s\n * .addTable(\"users\", t => t.addColumn(\"id\", idColumn()))\n * .addTable(\"posts\", t => t\n * .addColumn(\"id\", idColumn())\n * .addColumn(\"userId\", referenceColumn()))\n * .addReference(\"author\", {\n * type: \"one\",\n * from: { table: \"posts\", column: \"userId\" },\n * to: { table: \"users\", column: \"id\" },\n * })\n * )\n *\n * // One-to-many (inverse relation): user -> posts\n * .addReference(\"posts\", {\n * type: \"many\",\n * from: { table: \"users\", column: \"id\" },\n * to: { table: \"posts\", column: \"userId\" },\n * })\n *\n * // Self-referencing foreign key\n * .addReference(\"inviter\", {\n * type: \"one\",\n * from: { table: \"users\", column: \"invitedBy\" },\n * to: { table: \"users\", column: \"id\" },\n * })\n * ```\n */\n addReference<\n TFromTableName extends string & keyof TTables,\n TToTableName extends string & keyof TTables,\n TReferenceName extends string,\n TRelationType extends RelationType,\n >(\n referenceName: TReferenceName,\n config: {\n type: TRelationType;\n from: {\n table: TFromTableName;\n column: keyof TTables[TFromTableName][\"columns\"];\n };\n to: {\n table: TToTableName;\n column: keyof TTables[TToTableName][\"columns\"];\n };\n },\n ): SchemaBuilder<\n UpdateTableRelations<TTables, TFromTableName, TReferenceName, TToTableName, TRelationType>\n > {\n this.#version++;\n\n const table = this.#tables[config.from.table];\n const referencedTable = this.#tables[config.to.table];\n\n if (!referenceName || referenceName.trim().length === 0) {\n throw new Error(`referenceName is required for addReference on ${config.from.table}`);\n }\n\n if (!table) {\n throw new Error(`Table ${config.from.table} not found in schema`);\n }\n if (!referencedTable) {\n throw new Error(`Referenced table ${config.to.table} not found in schema`);\n }\n\n const columnName = config.from.column as string;\n const targetColumnName = config.to.column as string;\n\n // Foreign keys always reference internal IDs, not external IDs\n // If user specifies \"id\", translate to \"_internalId\" for the actual FK\n const actualTargetColumnName = targetColumnName === \"id\" ? \"_internalId\" : targetColumnName;\n\n const column = table.columns[columnName];\n const referencedColumn = referencedTable.columns[actualTargetColumnName];\n\n if (!column) {\n throw new Error(`Column ${columnName} not found in table ${config.from.table}`);\n }\n if (!referencedColumn) {\n throw new Error(`Column ${actualTargetColumnName} not found in table ${config.to.table}`);\n }\n\n if (table.relations[referenceName]) {\n throw new Error(`Reference ${referenceName} already exists on table ${config.from.table}`);\n }\n\n // Verify that reference columns are bigint (matching internal ID type)\n if (column.role === \"reference\" && column.type !== \"bigint\") {\n throw new Error(\n `Reference column ${columnName} must be of type bigint to match internal ID type`,\n );\n }\n\n // Create the relation (use the user-facing column name for the relation)\n const init = new ExplicitRelationInit(config.type, referencedTable, table);\n init.on.push([columnName, targetColumnName]);\n const relation = init.init(referenceName);\n\n // Add relation to the table\n table.relations[referenceName] = relation;\n\n // Record the operation\n this.#operations.push({\n type: \"add-reference\",\n tableName: config.from.table,\n referenceName,\n config: {\n type: config.type,\n from: { table: config.from.table, column: columnName },\n to: { table: config.to.table, column: actualTargetColumnName },\n },\n });\n\n // Return this with updated type\n // Safe: The relation was added to the table in place and now has the updated relations\n return this as unknown as SchemaBuilder<\n UpdateTableRelations<TTables, TFromTableName, TReferenceName, TToTableName, TRelationType>\n >;\n }\n\n /**\n * Alter an existing table by adding columns or indexes.\n * This is used for append-only schema modifications.\n *\n * @param tableName - The name of the table to modify\n * @param callback - A callback that receives a table builder for adding columns/indexes\n *\n * @example\n * ```ts\n * // Add a new column to an existing table\n * schema(\"blog\", s => s\n * .addTable(\"users\", t => t\n * .addColumn(\"id\", idColumn())\n * .addColumn(\"name\", column(\"string\")))\n * .alterTable(\"users\", t => t\n * .addColumn(\"email\", column(\"string\"))\n * .addColumn(\"age\", column(\"integer\").nullable())\n * .createIndex(\"idx_email\", [\"email\"]))\n * )\n * ```\n */\n alterTable<\n TTableName extends string & keyof TTables,\n TNewColumns extends Record<string, AnyColumn>,\n TNewRelations extends Record<string, AnyRelation>,\n TNewIndexes extends Record<string, Index> = Record<string, Index>,\n >(\n tableName: TTableName,\n callback: (\n builder: TableBuilder<\n TTables[TTableName][\"columns\"],\n TTables[TTableName][\"relations\"],\n Record<string, Index>\n >,\n ) => TableBuilder<TNewColumns, TNewRelations, TNewIndexes>,\n ): SchemaBuilder<UpdateTable<TTables, TTableName, TNewColumns, TNewRelations, TNewIndexes>> {\n const table = this.#tables[tableName];\n\n if (!table) {\n throw new Error(`Table ${tableName} not found in schema`);\n }\n\n // Create builder with existing table state\n const tableBuilder = new TableBuilder(tableName);\n tableBuilder.setColumns(table.columns);\n tableBuilder.setRelations(table.relations);\n tableBuilder.setIndexes(table.indexes);\n\n // Track existing columns and indexes\n const existingColumns = new Set(Object.keys(table.columns));\n const existingIndexes = new Set(Object.keys(table.indexes));\n\n // Apply modifications\n const resultBuilder = callback(\n tableBuilder as TableBuilder<\n TTables[TTableName][\"columns\"],\n TTables[TTableName][\"relations\"],\n Record<string, Index>\n >,\n );\n const newTable = resultBuilder.build();\n\n // Collect sub-operations\n const subOperations: TableSubOperation[] = [];\n\n // Find new columns (preserve order from builder)\n const columnOrder = resultBuilder.getColumnOrder();\n for (const colName of columnOrder) {\n if (!existingColumns.has(colName)) {\n subOperations.push({\n type: \"add-column\",\n columnName: colName,\n column: newTable.columns[colName],\n });\n }\n }\n\n // Add only new indexes\n for (const idx of resultBuilder.getIndexes()) {\n if (!existingIndexes.has(idx.name)) {\n if (this.#indexNames.has(idx.name)) {\n throw new Error(\n `Duplicate index name \"${idx.name}\" in schema \"${this.#name}\". Index names must be unique across tables (conflict on \"${tableName}\").`,\n );\n }\n subOperations.push({\n type: \"add-index\",\n name: idx.name,\n columns: idx.columns.map((c) => c.name),\n unique: idx.unique,\n });\n }\n }\n\n if (subOperations.length > 0) {\n this.#version++;\n this.#operations.push({\n type: \"alter-table\",\n tableName,\n operations: subOperations,\n });\n }\n\n // Update table reference in schema\n this.#tables[tableName] = newTable as unknown as TTables[TTableName];\n for (const idx of resultBuilder.getIndexes()) {\n if (!existingIndexes.has(idx.name)) {\n this.#indexNames.add(idx.name);\n }\n }\n\n // Set table name for all columns\n for (const col of Object.values(newTable.columns)) {\n col.tableName = newTable.name;\n }\n\n return this as unknown as SchemaBuilder<\n UpdateTable<TTables, TTableName, TNewColumns, TNewRelations, TNewIndexes>\n >;\n }\n\n /**\n * Build the final schema. This should be called after all tables are added.\n */\n build(): Schema<TTables> {\n const operations = this.#operations;\n const version = this.#version;\n const tables = this.#tables;\n\n const schema: Schema<TTables> = {\n name: this.#name,\n version,\n tables,\n operations,\n clone: () => {\n const cloneTables: Record<string, AnyTable> = {};\n\n for (const [k, v] of Object.entries(tables)) {\n // Create a new table with cloned columns\n const clonedColumns: Record<string, AnyColumn> = {};\n for (const [colName, col] of Object.entries(v.columns)) {\n // Create a new column with the same properties, preserving the column type\n let clonedCol: AnyColumn;\n if (col instanceof InternalIdColumn) {\n clonedCol = new InternalIdColumn();\n } else if (col instanceof VersionColumn) {\n clonedCol = new VersionColumn();\n } else if (col instanceof IdColumn) {\n clonedCol = new IdColumn(col.type);\n } else {\n clonedCol = new Column(col.type);\n }\n\n clonedCol.name = col.name;\n clonedCol.isNullable = col.isNullable;\n clonedCol.role = col.role;\n clonedCol.isHidden = col.isHidden;\n clonedCol.default = col.default;\n clonedCol.tableName = col.tableName;\n clonedColumns[colName] = clonedCol;\n }\n\n const clonedTable = {\n ...v,\n columns: clonedColumns,\n } as AnyTable;\n\n clonedTable[\"~standard\"] = createTableStandardSchemaProps(clonedTable, validationClasses);\n clonedTable.validate = createTableValidator(clonedTable, validationClasses);\n\n cloneTables[k] = clonedTable;\n }\n\n const clonedSchema: Schema<TTables> = {\n name: this.#name,\n version,\n tables: cloneTables as TTables,\n operations: [...operations],\n clone: () => {\n throw new Error(\"Cannot clone during clone\");\n },\n };\n\n return new SchemaBuilder<TTables>(this.#name, clonedSchema).build();\n },\n };\n\n return schema;\n }\n\n /**\n * Get the current version of the schema builder.\n */\n getVersion(): number {\n return this.#version;\n }\n}\n\n/**\n * Create a new schema with callback pattern.\n */\nexport function schema<const TTables extends Record<string, AnyTable> = {}>(\n name: string,\n callback: (builder: SchemaBuilder<{}>) => SchemaBuilder<TTables>,\n): Schema<TTables> {\n return callback(new SchemaBuilder(name)).build();\n}\n\nexport function compileForeignKey(key: ForeignKey) {\n return {\n name: key.name,\n table: key.table.name,\n referencedTable: key.referencedTable.name,\n referencedColumns: key.referencedColumns.map((col) => col.name),\n columns: key.columns.map((col) => col.name),\n };\n}\n"],"mappings":"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"}
@@ -18,8 +18,8 @@ function generateId(schema, tableName) {
18
18
  if (!tableSchema) throw new Error(`Table ${tableName} not found in schema`);
19
19
  const idColumn = tableSchema.getIdColumn();
20
20
  const generated = idColumn.generateDefaultValue();
21
- if (generated === void 0) throw new Error(`ID column ${idColumn.ormName} on table ${tableName} has no default generator`);
22
- if (typeof generated !== "string") throw new Error(`ID column ${idColumn.ormName} on table ${tableName} has no default generator that generates a string.`);
21
+ if (generated === void 0) throw new Error(`ID column ${idColumn.name} on table ${tableName} has no default generator`);
22
+ if (typeof generated !== "string") throw new Error(`ID column ${idColumn.name} on table ${tableName} has no default generator that generates a string.`);
23
23
  return FragnoId.fromExternal(generated, 0);
24
24
  }
25
25
 
@@ -1 +1 @@
1
- {"version":3,"file":"generate-id.js","names":[],"sources":["../../src/schema/generate-id.ts"],"sourcesContent":["import type { AnySchema } from \"./create\";\nimport { FragnoId } from \"./create\";\n\n/**\n * Generate a new ID for a table without creating a record.\n * This is useful when you need to reference an ID before actually creating the record,\n * or when you need to pass the ID to external services.\n *\n * @example\n * ```ts\n * const userId = generateId(mySchema, \"users\");\n * // Use userId in related records or pass to external services\n * uow.create(\"users\", { id: userId, name: \"John\" });\n * ```\n */\nexport function generateId<\n TSchema extends AnySchema,\n TableName extends keyof TSchema[\"tables\"] & string,\n>(schema: TSchema, tableName: TableName): FragnoId {\n const tableSchema = schema.tables[tableName];\n if (!tableSchema) {\n throw new Error(`Table ${tableName} not found in schema`);\n }\n\n const idColumn = tableSchema.getIdColumn();\n const generated = idColumn.generateDefaultValue();\n if (generated === undefined) {\n throw new Error(`ID column ${idColumn.ormName} on table ${tableName} has no default generator`);\n }\n\n if (typeof generated !== \"string\") {\n throw new Error(\n `ID column ${idColumn.ormName} on table ${tableName} has no default generator that generates a string.`,\n );\n }\n\n return FragnoId.fromExternal(generated, 0);\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,SAAgB,WAGd,QAAiB,WAAgC;CACjD,MAAM,cAAc,OAAO,OAAO;AAClC,KAAI,CAAC,YACH,OAAM,IAAI,MAAM,SAAS,UAAU,sBAAsB;CAG3D,MAAM,WAAW,YAAY,aAAa;CAC1C,MAAM,YAAY,SAAS,sBAAsB;AACjD,KAAI,cAAc,OAChB,OAAM,IAAI,MAAM,aAAa,SAAS,QAAQ,YAAY,UAAU,2BAA2B;AAGjG,KAAI,OAAO,cAAc,SACvB,OAAM,IAAI,MACR,aAAa,SAAS,QAAQ,YAAY,UAAU,oDACrD;AAGH,QAAO,SAAS,aAAa,WAAW,EAAE"}
1
+ {"version":3,"file":"generate-id.js","names":[],"sources":["../../src/schema/generate-id.ts"],"sourcesContent":["import type { AnySchema } from \"./create\";\nimport { FragnoId } from \"./create\";\n\n/**\n * Generate a new ID for a table without creating a record.\n * This is useful when you need to reference an ID before actually creating the record,\n * or when you need to pass the ID to external services.\n *\n * @example\n * ```ts\n * const userId = generateId(mySchema, \"users\");\n * // Use userId in related records or pass to external services\n * uow.create(\"users\", { id: userId, name: \"John\" });\n * ```\n */\nexport function generateId<\n TSchema extends AnySchema,\n TableName extends keyof TSchema[\"tables\"] & string,\n>(schema: TSchema, tableName: TableName): FragnoId {\n const tableSchema = schema.tables[tableName];\n if (!tableSchema) {\n throw new Error(`Table ${tableName} not found in schema`);\n }\n\n const idColumn = tableSchema.getIdColumn();\n const generated = idColumn.generateDefaultValue();\n if (generated === undefined) {\n throw new Error(`ID column ${idColumn.name} on table ${tableName} has no default generator`);\n }\n\n if (typeof generated !== \"string\") {\n throw new Error(\n `ID column ${idColumn.name} on table ${tableName} has no default generator that generates a string.`,\n );\n }\n\n return FragnoId.fromExternal(generated, 0);\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,SAAgB,WAGd,QAAiB,WAAgC;CACjD,MAAM,cAAc,OAAO,OAAO;AAClC,KAAI,CAAC,YACH,OAAM,IAAI,MAAM,SAAS,UAAU,sBAAsB;CAG3D,MAAM,WAAW,YAAY,aAAa;CAC1C,MAAM,YAAY,SAAS,sBAAsB;AACjD,KAAI,cAAc,OAChB,OAAM,IAAI,MAAM,aAAa,SAAS,KAAK,YAAY,UAAU,2BAA2B;AAG9F,KAAI,OAAO,cAAc,SACvB,OAAM,IAAI,MACR,aAAa,SAAS,KAAK,YAAY,UAAU,oDAClD;AAGH,QAAO,SAAS,aAAa,WAAW,EAAE"}
@@ -10,13 +10,14 @@ import { SQLiteTypeMapper } from "./dialect/sqlite.js";
10
10
  * (PostgreSQL, MySQL, or SQLite).
11
11
  *
12
12
  * @param database - The database type (sqlite, postgresql, or mysql)
13
+ * @param sqliteStorageMode - Optional SQLite storage mode override
13
14
  * @returns Dialect-specific SQLTypeMapper instance
14
15
  */
15
- function createSQLTypeMapper(database) {
16
+ function createSQLTypeMapper(database, sqliteStorageMode) {
16
17
  switch (database) {
17
18
  case "postgresql": return new PostgreSQLTypeMapper(database);
18
19
  case "mysql": return new MySQLTypeMapper(database);
19
- case "sqlite": return new SQLiteTypeMapper(database);
20
+ case "sqlite": return new SQLiteTypeMapper(database, sqliteStorageMode);
20
21
  default: {
21
22
  const exhaustiveCheck = database;
22
23
  throw new Error(`Unsupported database type: ${exhaustiveCheck}`);