@fragno-dev/db 0.2.2 → 0.4.1

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 (587) hide show
  1. package/.turbo/turbo-build.log +404 -175
  2. package/CHANGELOG.md +109 -0
  3. package/README.md +54 -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 +24 -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 +60 -22
  14. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  15. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +169 -3
  16. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  17. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -1
  18. package/dist/adapters/generic-sql/migration/dialect/mysql.js +25 -6
  19. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  20. package/dist/adapters/generic-sql/migration/dialect/postgres.js +7 -6
  21. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  22. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +193 -16
  23. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  24. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -1
  25. package/dist/adapters/generic-sql/migration/executor.js +30 -3
  26. package/dist/adapters/generic-sql/migration/executor.js.map +1 -1
  27. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  28. package/dist/adapters/generic-sql/migration/prepared-migrations.js +9 -9
  29. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  30. package/dist/adapters/generic-sql/migration/sql-generator.js +75 -52
  31. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  32. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +7 -6
  33. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  34. package/dist/adapters/generic-sql/query/cursor-utils.js +42 -4
  35. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/db-now-sql.js +27 -0
  37. package/dist/adapters/generic-sql/query/db-now-sql.js.map +1 -0
  38. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +32 -21
  39. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  40. package/dist/adapters/generic-sql/query/select-builder.js +5 -3
  41. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  42. package/dist/adapters/generic-sql/query/sql-query-compiler.js +49 -18
  43. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  44. package/dist/adapters/generic-sql/query/where-builder.js +43 -29
  45. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  46. package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
  47. package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  48. package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
  49. package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
  50. package/dist/adapters/generic-sql/uow-decoder.js +6 -2
  51. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  52. package/dist/adapters/generic-sql/uow-encoder.js +27 -8
  53. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  54. package/dist/adapters/in-memory/condition-evaluator.js +135 -0
  55. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
  56. package/dist/adapters/in-memory/errors.d.ts +13 -0
  57. package/dist/adapters/in-memory/errors.d.ts.map +1 -0
  58. package/dist/adapters/in-memory/errors.js +23 -0
  59. package/dist/adapters/in-memory/errors.js.map +1 -0
  60. package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
  61. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
  62. package/dist/adapters/in-memory/in-memory-adapter.js +196 -0
  63. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
  64. package/dist/adapters/in-memory/in-memory-uow.js +871 -0
  65. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
  66. package/dist/adapters/in-memory/index.d.ts +4 -0
  67. package/dist/adapters/in-memory/index.js +4 -0
  68. package/dist/adapters/in-memory/options.d.ts +30 -0
  69. package/dist/adapters/in-memory/options.d.ts.map +1 -0
  70. package/dist/adapters/in-memory/options.js +62 -0
  71. package/dist/adapters/in-memory/options.js.map +1 -0
  72. package/dist/adapters/in-memory/reference-resolution.js +26 -0
  73. package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
  74. package/dist/adapters/in-memory/sorted-array-index.js +129 -0
  75. package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
  76. package/dist/adapters/in-memory/store.js +71 -0
  77. package/dist/adapters/in-memory/store.js.map +1 -0
  78. package/dist/adapters/in-memory/value-comparison.js +28 -0
  79. package/dist/adapters/in-memory/value-comparison.js.map +1 -0
  80. package/dist/adapters/shared/from-unit-of-work-compiler.js +51 -24
  81. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  82. package/dist/adapters/shared/uow-operation-compiler.js +11 -11
  83. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  84. package/dist/adapters/sql/index.d.ts +5 -0
  85. package/dist/adapters/sql/index.js +4 -0
  86. package/dist/browser/adapters/adapters.d.ts +61 -0
  87. package/dist/browser/adapters/adapters.d.ts.map +1 -0
  88. package/dist/browser/adapters/generic-sql/migration/executor.d.ts +15 -0
  89. package/dist/browser/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  90. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  91. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  92. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts +11 -0
  93. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  94. package/dist/browser/adapters/in-memory/in-memory-adapter.d.ts +5 -0
  95. package/dist/browser/adapters/in-memory/index.d.ts +2 -0
  96. package/dist/browser/adapters/in-memory/options.d.ts +1 -0
  97. package/dist/browser/db-fragment-definition-builder.d.ts +237 -0
  98. package/dist/browser/db-fragment-definition-builder.d.ts.map +1 -0
  99. package/dist/browser/durable-hooks.d.ts +3 -0
  100. package/dist/browser/fragments/internal-fragment.d.ts +317 -0
  101. package/dist/browser/fragments/internal-fragment.d.ts.map +1 -0
  102. package/dist/browser/fragments/internal-fragment.schema.d.ts +1 -0
  103. package/dist/browser/hooks/durable-hooks-logger.d.ts +10 -0
  104. package/dist/browser/hooks/durable-hooks-logger.d.ts.map +1 -0
  105. package/dist/browser/hooks/hooks.d.ts +146 -0
  106. package/dist/browser/hooks/hooks.d.ts.map +1 -0
  107. package/dist/browser/id.js +1 -0
  108. package/dist/browser/internal/adapter-registry.d.ts +4 -0
  109. package/dist/browser/internal/outbox-state.d.ts +2 -0
  110. package/dist/browser/mod.d.ts +15 -0
  111. package/dist/browser/mod.d.ts.map +1 -0
  112. package/dist/browser/mod.js +17 -0
  113. package/dist/browser/mod.js.map +1 -0
  114. package/dist/browser/mod2.d.ts +48 -0
  115. package/dist/browser/mod2.d.ts.map +1 -0
  116. package/dist/browser/naming/sql-naming.d.ts +19 -0
  117. package/dist/browser/naming/sql-naming.d.ts.map +1 -0
  118. package/dist/browser/outbox/outbox.d.ts +21 -0
  119. package/dist/browser/outbox/outbox.d.ts.map +1 -0
  120. package/dist/browser/query/column-defaults.js +1 -0
  121. package/dist/browser/query/condition-builder.d.ts +44 -0
  122. package/dist/browser/query/condition-builder.d.ts.map +1 -0
  123. package/dist/browser/query/condition-builder.js +97 -0
  124. package/dist/browser/query/condition-builder.js.map +1 -0
  125. package/dist/browser/query/cursor.d.ts +105 -0
  126. package/dist/browser/query/cursor.d.ts.map +1 -0
  127. package/dist/browser/query/cursor.js +150 -0
  128. package/dist/browser/query/cursor.js.map +1 -0
  129. package/dist/browser/query/db-now.d.ts +22 -0
  130. package/dist/browser/query/db-now.d.ts.map +1 -0
  131. package/dist/browser/query/db-now.js +33 -0
  132. package/dist/browser/query/db-now.js.map +1 -0
  133. package/dist/browser/query/orm/orm.d.ts +18 -0
  134. package/dist/browser/query/orm/orm.d.ts.map +1 -0
  135. package/dist/browser/query/simple-query-interface.d.ts +108 -0
  136. package/dist/browser/query/simple-query-interface.d.ts.map +1 -0
  137. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts +423 -0
  138. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  139. package/dist/browser/query/unit-of-work/execute-unit-of-work.js +507 -0
  140. package/dist/browser/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  141. package/dist/browser/query/unit-of-work/retry-policy.d.ts +23 -0
  142. package/dist/browser/query/unit-of-work/retry-policy.d.ts.map +1 -0
  143. package/dist/browser/query/unit-of-work/retry-policy.js +40 -0
  144. package/dist/browser/query/unit-of-work/retry-policy.js.map +1 -0
  145. package/dist/browser/query/unit-of-work/unit-of-work.d.ts +703 -0
  146. package/dist/browser/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  147. package/dist/browser/query/unit-of-work/unit-of-work.js +1206 -0
  148. package/dist/browser/query/unit-of-work/unit-of-work.js.map +1 -0
  149. package/dist/browser/query/value-encoding.js +38 -0
  150. package/dist/browser/query/value-encoding.js.map +1 -0
  151. package/dist/browser/schema/create.d.ts +326 -0
  152. package/dist/browser/schema/create.d.ts.map +1 -0
  153. package/dist/browser/schema/create.js +89 -0
  154. package/dist/browser/schema/create.js.map +1 -0
  155. package/dist/browser/schema/generate-id.js +28 -0
  156. package/dist/browser/schema/generate-id.js.map +1 -0
  157. package/dist/browser/shared/providers.d.ts +6 -0
  158. package/dist/browser/shared/providers.d.ts.map +1 -0
  159. package/dist/browser/sql-driver/connection/connection-provider.d.ts +13 -0
  160. package/dist/browser/sql-driver/connection/connection-provider.d.ts.map +1 -0
  161. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  162. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  163. package/dist/browser/sql-driver/driver/runtime-driver.d.ts +23 -0
  164. package/dist/browser/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  165. package/dist/browser/sql-driver/query-executor/plugin.d.ts +17 -0
  166. package/dist/browser/sql-driver/query-executor/plugin.d.ts.map +1 -0
  167. package/dist/browser/sql-driver/query-executor/query-executor.d.ts +36 -0
  168. package/dist/browser/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  169. package/dist/browser/sql-driver/sql-driver-adapter.d.ts +29 -0
  170. package/dist/browser/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  171. package/dist/browser/sql-driver/sql-driver.d.ts +38 -0
  172. package/dist/browser/sql-driver/sql-driver.d.ts.map +1 -0
  173. package/dist/browser/sync/commands.d.ts +15 -0
  174. package/dist/browser/sync/commands.d.ts.map +1 -0
  175. package/dist/browser/sync/commands.js +27 -0
  176. package/dist/browser/sync/commands.js.map +1 -0
  177. package/dist/browser/sync/types.d.ts +63 -0
  178. package/dist/browser/sync/types.d.ts.map +1 -0
  179. package/dist/browser/util/types.d.ts +8 -0
  180. package/dist/browser/util/types.d.ts.map +1 -0
  181. package/dist/browser/with-database.d.ts +29 -0
  182. package/dist/browser/with-database.d.ts.map +1 -0
  183. package/dist/client.d.ts +4 -0
  184. package/dist/client.js +5 -0
  185. package/dist/db-fragment-definition-builder.d.ts +101 -33
  186. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  187. package/dist/db-fragment-definition-builder.js +450 -60
  188. package/dist/db-fragment-definition-builder.js.map +1 -1
  189. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts +20 -0
  190. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts.map +1 -0
  191. package/dist/dispatchers/cloudflare-do/dispatcher.js +147 -0
  192. package/dist/dispatchers/cloudflare-do/dispatcher.js.map +1 -0
  193. package/dist/dispatchers/cloudflare-do/index.d.ts +11 -0
  194. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
  195. package/dist/dispatchers/cloudflare-do/index.js +31 -0
  196. package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
  197. package/dist/dispatchers/node/dispatcher.d.ts +14 -0
  198. package/dist/dispatchers/node/dispatcher.d.ts.map +1 -0
  199. package/dist/dispatchers/node/dispatcher.js +80 -0
  200. package/dist/dispatchers/node/dispatcher.js.map +1 -0
  201. package/dist/dispatchers/node/index.d.ts +12 -0
  202. package/dist/dispatchers/node/index.d.ts.map +1 -0
  203. package/dist/dispatchers/node/index.js +27 -0
  204. package/dist/dispatchers/node/index.js.map +1 -0
  205. package/dist/durable-hooks.d.ts +31 -0
  206. package/dist/durable-hooks.d.ts.map +1 -0
  207. package/dist/durable-hooks.js +23 -0
  208. package/dist/durable-hooks.js.map +1 -0
  209. package/dist/fragments/internal-fragment.d.ts +186 -8
  210. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  211. package/dist/fragments/internal-fragment.js +203 -38
  212. package/dist/fragments/internal-fragment.js.map +1 -1
  213. package/dist/fragments/internal-fragment.routes.js +164 -0
  214. package/dist/fragments/internal-fragment.routes.js.map +1 -0
  215. package/dist/fragments/internal-fragment.schema.d.ts +15 -0
  216. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
  217. package/dist/fragments/internal-fragment.schema.js +39 -0
  218. package/dist/fragments/internal-fragment.schema.js.map +1 -0
  219. package/dist/hooks/durable-hooks-logger.d.ts +10 -0
  220. package/dist/hooks/durable-hooks-logger.d.ts.map +1 -0
  221. package/dist/hooks/durable-hooks-logger.js +75 -0
  222. package/dist/hooks/durable-hooks-logger.js.map +1 -0
  223. package/dist/hooks/durable-hooks-processor.d.ts +1 -0
  224. package/dist/hooks/durable-hooks-processor.js +80 -0
  225. package/dist/hooks/durable-hooks-processor.js.map +1 -0
  226. package/dist/hooks/durable-hooks-runtime.js +44 -0
  227. package/dist/hooks/durable-hooks-runtime.js.map +1 -0
  228. package/dist/hooks/hooks.d.ts +100 -1
  229. package/dist/hooks/hooks.d.ts.map +1 -1
  230. package/dist/hooks/hooks.js +254 -27
  231. package/dist/hooks/hooks.js.map +1 -1
  232. package/dist/id.d.ts +2 -2
  233. package/dist/id.js +2 -2
  234. package/dist/internal/adapter-registry.d.ts +11 -0
  235. package/dist/internal/adapter-registry.d.ts.map +1 -0
  236. package/dist/internal/adapter-registry.js +135 -0
  237. package/dist/internal/adapter-registry.js.map +1 -0
  238. package/dist/internal/outbox-state.d.ts +2 -0
  239. package/dist/internal/outbox-state.js +26 -0
  240. package/dist/internal/outbox-state.js.map +1 -0
  241. package/dist/migration-engine/auto-from-schema.d.ts +33 -0
  242. package/dist/migration-engine/auto-from-schema.d.ts.map +1 -0
  243. package/dist/migration-engine/auto-from-schema.js +223 -37
  244. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  245. package/dist/migration-engine/generation-engine.d.ts +16 -10
  246. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  247. package/dist/migration-engine/generation-engine.js +86 -35
  248. package/dist/migration-engine/generation-engine.js.map +1 -1
  249. package/dist/migration-engine/shared.d.ts +113 -0
  250. package/dist/migration-engine/shared.d.ts.map +1 -0
  251. package/dist/migration-engine/shared.js.map +1 -1
  252. package/dist/mod.d.ts +20 -12
  253. package/dist/mod.d.ts.map +1 -1
  254. package/dist/mod.js +18 -12
  255. package/dist/mod.js.map +1 -1
  256. package/dist/naming/sql-naming.d.ts +19 -0
  257. package/dist/naming/sql-naming.d.ts.map +1 -0
  258. package/dist/naming/sql-naming.js +116 -0
  259. package/dist/naming/sql-naming.js.map +1 -0
  260. package/dist/outbox/outbox-builder.js +156 -0
  261. package/dist/outbox/outbox-builder.js.map +1 -0
  262. package/dist/outbox/outbox.d.ts +54 -0
  263. package/dist/outbox/outbox.d.ts.map +1 -0
  264. package/dist/outbox/outbox.js +37 -0
  265. package/dist/outbox/outbox.js.map +1 -0
  266. package/dist/query/column-defaults.js +20 -4
  267. package/dist/query/column-defaults.js.map +1 -1
  268. package/dist/query/condition-builder.d.ts +7 -1
  269. package/dist/query/condition-builder.d.ts.map +1 -1
  270. package/dist/query/condition-builder.js +5 -1
  271. package/dist/query/condition-builder.js.map +1 -1
  272. package/dist/query/cursor-client.d.ts +105 -0
  273. package/dist/query/cursor-client.d.ts.map +1 -0
  274. package/dist/query/cursor-client.js +165 -0
  275. package/dist/query/cursor-client.js.map +1 -0
  276. package/dist/query/cursor.d.ts +3 -1
  277. package/dist/query/cursor.d.ts.map +1 -1
  278. package/dist/query/cursor.js +51 -14
  279. package/dist/query/cursor.js.map +1 -1
  280. package/dist/query/db-now.d.ts +22 -0
  281. package/dist/query/db-now.d.ts.map +1 -0
  282. package/dist/query/db-now.js +35 -0
  283. package/dist/query/db-now.js.map +1 -0
  284. package/dist/query/orm/orm.js.map +1 -1
  285. package/dist/query/serialize/create-sql-serializer.js +5 -4
  286. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  287. package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
  288. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  289. package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
  290. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  291. package/dist/query/serialize/dialect/sqlite-serializer.js +60 -12
  292. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  293. package/dist/query/serialize/sql-serializer.js +2 -2
  294. package/dist/query/serialize/sql-serializer.js.map +1 -1
  295. package/dist/query/simple-query-interface.d.ts +13 -4
  296. package/dist/query/simple-query-interface.d.ts.map +1 -1
  297. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +37 -2
  298. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  299. package/dist/query/unit-of-work/execute-unit-of-work.js +50 -24
  300. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  301. package/dist/query/unit-of-work/unit-of-work.d.ts +92 -30
  302. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  303. package/dist/query/unit-of-work/unit-of-work.js +136 -11
  304. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  305. package/dist/query/value-decoding.js +16 -6
  306. package/dist/query/value-decoding.js.map +1 -1
  307. package/dist/query/value-encoding.js +29 -9
  308. package/dist/query/value-encoding.js.map +1 -1
  309. package/dist/schema/create.d.ts +103 -35
  310. package/dist/schema/create.d.ts.map +1 -1
  311. package/dist/schema/create.js +172 -58
  312. package/dist/schema/create.js.map +1 -1
  313. package/dist/schema/generate-id.js +2 -2
  314. package/dist/schema/generate-id.js.map +1 -1
  315. package/dist/schema/type-conversion/create-sql-type-mapper.js +4 -3
  316. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  317. package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
  318. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  319. package/dist/schema/validator.d.ts +10 -0
  320. package/dist/schema/validator.d.ts.map +1 -0
  321. package/dist/schema/validator.js +123 -0
  322. package/dist/schema/validator.js.map +1 -0
  323. package/dist/schema-output/drizzle.d.ts +30 -0
  324. package/dist/schema-output/drizzle.d.ts.map +1 -0
  325. package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +88 -60
  326. package/dist/schema-output/drizzle.js.map +1 -0
  327. package/dist/schema-output/prisma.d.ts +17 -0
  328. package/dist/schema-output/prisma.d.ts.map +1 -0
  329. package/dist/schema-output/prisma.js +307 -0
  330. package/dist/schema-output/prisma.js.map +1 -0
  331. package/dist/sql-driver/dialects/durable-object-dialect.js +3 -9
  332. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -1
  333. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -1
  334. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -1
  335. package/dist/sql-driver/sql-driver-adapter.js.map +1 -1
  336. package/dist/sql-driver/sql.js.map +1 -1
  337. package/dist/sync/commands.d.ts +15 -0
  338. package/dist/sync/commands.d.ts.map +1 -0
  339. package/dist/sync/commands.js +27 -0
  340. package/dist/sync/commands.js.map +1 -0
  341. package/dist/sync/index.d.ts +4 -0
  342. package/dist/sync/index.js +4 -0
  343. package/dist/sync/read-tracking.d.ts +25 -0
  344. package/dist/sync/read-tracking.d.ts.map +1 -0
  345. package/dist/sync/read-tracking.js +148 -0
  346. package/dist/sync/read-tracking.js.map +1 -0
  347. package/dist/sync/submit.js +213 -0
  348. package/dist/sync/submit.js.map +1 -0
  349. package/dist/sync/types.d.ts +63 -0
  350. package/dist/sync/types.d.ts.map +1 -0
  351. package/dist/util/default-database-adapter.js +66 -0
  352. package/dist/util/default-database-adapter.js.map +1 -0
  353. package/dist/with-database.d.ts +3 -6
  354. package/dist/with-database.d.ts.map +1 -1
  355. package/dist/with-database.js +8 -7
  356. package/dist/with-database.js.map +1 -1
  357. package/package.json +62 -55
  358. package/src/adapters/adapters.ts +33 -26
  359. package/src/adapters/drizzle/migrate-drizzle.test.ts +99 -41
  360. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +601 -0
  361. package/src/adapters/drizzle/test-utils.ts +13 -8
  362. package/src/adapters/generic-sql/driver-config.ts +38 -0
  363. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +10 -8
  364. package/src/adapters/generic-sql/generic-sql-adapter.ts +117 -34
  365. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +55 -0
  366. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +297 -3
  367. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +120 -0
  368. package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
  369. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +27 -8
  370. package/src/adapters/generic-sql/migration/dialect/mysql.ts +47 -8
  371. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +28 -9
  372. package/src/adapters/generic-sql/migration/dialect/postgres.ts +9 -4
  373. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +839 -8
  374. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +396 -53
  375. package/src/adapters/generic-sql/migration/executor.test.ts +52 -0
  376. package/src/adapters/generic-sql/migration/executor.ts +47 -4
  377. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +238 -46
  378. package/src/adapters/generic-sql/migration/prepared-migrations.ts +21 -13
  379. package/src/adapters/generic-sql/migration/sql-generator.ts +145 -66
  380. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +11 -8
  381. package/src/adapters/generic-sql/query/cursor-utils.test.ts +272 -0
  382. package/src/adapters/generic-sql/query/cursor-utils.ts +42 -7
  383. package/src/adapters/generic-sql/query/db-now-sql.ts +49 -0
  384. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +171 -35
  385. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +53 -40
  386. package/src/adapters/generic-sql/query/select-builder.test.ts +16 -11
  387. package/src/adapters/generic-sql/query/select-builder.ts +7 -3
  388. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +75 -6
  389. package/src/adapters/generic-sql/query/sql-query-compiler.ts +129 -24
  390. package/src/adapters/generic-sql/query/where-builder.test.ts +96 -20
  391. package/src/adapters/generic-sql/query/where-builder.ts +112 -41
  392. package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +11 -20
  393. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +851 -0
  394. package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +18 -15
  395. package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +282 -14
  396. package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +129 -12
  397. package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +9 -7
  398. package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
  399. package/src/adapters/generic-sql/uow-decoder.test.ts +5 -4
  400. package/src/adapters/generic-sql/uow-decoder.ts +23 -5
  401. package/src/adapters/generic-sql/uow-encoder.test.ts +36 -3
  402. package/src/adapters/generic-sql/uow-encoder.ts +48 -13
  403. package/src/adapters/in-memory/condition-evaluator.test.ts +194 -0
  404. package/src/adapters/in-memory/condition-evaluator.ts +280 -0
  405. package/src/adapters/in-memory/errors.ts +20 -0
  406. package/src/adapters/in-memory/in-memory-adapter.ts +388 -0
  407. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +344 -0
  408. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +255 -0
  409. package/src/adapters/in-memory/in-memory-uow.ts +1724 -0
  410. package/src/adapters/in-memory/index.ts +3 -0
  411. package/src/adapters/in-memory/options.test.ts +42 -0
  412. package/src/adapters/in-memory/options.ts +91 -0
  413. package/src/adapters/in-memory/outbox.test.ts +361 -0
  414. package/src/adapters/in-memory/reference-resolution.test.ts +51 -0
  415. package/src/adapters/in-memory/reference-resolution.ts +67 -0
  416. package/src/adapters/in-memory/sorted-array-index.test.ts +124 -0
  417. package/src/adapters/in-memory/sorted-array-index.ts +228 -0
  418. package/src/adapters/in-memory/store.test.ts +69 -0
  419. package/src/adapters/in-memory/store.ts +145 -0
  420. package/src/adapters/in-memory/value-comparison.ts +53 -0
  421. package/src/adapters/in-memory/value-normalization.test.ts +58 -0
  422. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1207 -0
  423. package/src/adapters/shared/from-unit-of-work-compiler.ts +159 -47
  424. package/src/adapters/shared/uow-operation-compiler.ts +28 -18
  425. package/src/adapters/sql/index.ts +12 -0
  426. package/src/browser/mod.ts +64 -0
  427. package/src/client.ts +19 -0
  428. package/src/db-fragment-definition-builder.test.ts +845 -53
  429. package/src/db-fragment-definition-builder.ts +911 -95
  430. package/src/db-fragment-instantiator.test.ts +210 -94
  431. package/src/db-fragment-integration.test.ts +17 -12
  432. package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
  433. package/src/dispatchers/cloudflare-do/index.test.ts +206 -0
  434. package/src/dispatchers/cloudflare-do/index.ts +63 -0
  435. package/src/dispatchers/node/dispatcher.ts +112 -0
  436. package/src/dispatchers/node/index.test.ts +120 -0
  437. package/src/dispatchers/node/index.ts +50 -0
  438. package/src/durable-hooks.test.ts +80 -0
  439. package/src/durable-hooks.ts +67 -0
  440. package/src/fragments/internal-fragment.routes.test.ts +570 -0
  441. package/src/fragments/internal-fragment.routes.ts +334 -0
  442. package/src/fragments/internal-fragment.schema.ts +95 -0
  443. package/src/fragments/internal-fragment.test.ts +505 -83
  444. package/src/fragments/internal-fragment.ts +453 -70
  445. package/src/hooks/durable-hooks-logger.ts +126 -0
  446. package/src/hooks/durable-hooks-processor.pglite.test.ts +87 -0
  447. package/src/hooks/durable-hooks-processor.test.ts +282 -0
  448. package/src/hooks/durable-hooks-processor.ts +173 -0
  449. package/src/hooks/durable-hooks-runtime.test.ts +65 -0
  450. package/src/hooks/durable-hooks-runtime.ts +81 -0
  451. package/src/hooks/hooks.test.ts +455 -34
  452. package/src/hooks/hooks.ts +501 -34
  453. package/src/id.test.ts +34 -0
  454. package/src/id.ts +1 -3
  455. package/src/internal/adapter-registry.test.ts +93 -0
  456. package/src/internal/adapter-registry.ts +239 -0
  457. package/src/internal/outbox-state.ts +43 -0
  458. package/src/migration-engine/auto-from-schema.test.ts +107 -14
  459. package/src/migration-engine/auto-from-schema.ts +365 -44
  460. package/src/migration-engine/create.test.ts +4 -3
  461. package/src/migration-engine/create.ts +1 -1
  462. package/src/migration-engine/generation-engine.test.ts +292 -110
  463. package/src/migration-engine/generation-engine.ts +117 -66
  464. package/src/migration-engine/shared.ts +14 -0
  465. package/src/mod.ts +95 -39
  466. package/src/naming/sql-naming.ts +181 -0
  467. package/src/outbox/outbox-builder.ts +241 -0
  468. package/src/outbox/outbox.test.ts +424 -0
  469. package/src/outbox/outbox.ts +139 -0
  470. package/src/query/column-defaults.ts +42 -4
  471. package/src/query/condition-builder.test.ts +18 -3
  472. package/src/query/condition-builder.ts +7 -0
  473. package/src/query/cursor-client.test.ts +70 -0
  474. package/src/query/cursor-client.ts +263 -0
  475. package/src/query/cursor.test.ts +119 -20
  476. package/src/query/cursor.ts +88 -27
  477. package/src/query/db-now.ts +73 -0
  478. package/src/query/orm/orm.ts +2 -2
  479. package/src/query/query-type.test.ts +4 -3
  480. package/src/query/serialize/create-sql-serializer.ts +10 -5
  481. package/src/query/serialize/dialect/mysql-serializer.ts +13 -5
  482. package/src/query/serialize/dialect/postgres-serializer.ts +35 -5
  483. package/src/query/serialize/dialect/sqlite-serializer.test.ts +90 -3
  484. package/src/query/serialize/dialect/sqlite-serializer.ts +108 -12
  485. package/src/query/serialize/sql-serializer.ts +4 -4
  486. package/src/query/simple-query-interface.ts +15 -4
  487. package/src/query/unit-of-work/execute-unit-of-work.test.ts +372 -10
  488. package/src/query/unit-of-work/execute-unit-of-work.ts +87 -27
  489. package/src/query/unit-of-work/retry-policy.test.ts +1 -0
  490. package/src/query/unit-of-work/tx-builder.test.ts +73 -1
  491. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +17 -16
  492. package/src/query/unit-of-work/unit-of-work-types.test.ts +42 -12
  493. package/src/query/unit-of-work/unit-of-work.test.ts +196 -39
  494. package/src/query/unit-of-work/unit-of-work.ts +309 -38
  495. package/src/query/value-decoding.test.ts +63 -4
  496. package/src/query/value-decoding.ts +32 -6
  497. package/src/query/value-encoding.test.ts +86 -2
  498. package/src/query/value-encoding.ts +56 -6
  499. package/src/schema/create.test.ts +293 -47
  500. package/src/schema/create.ts +406 -70
  501. package/src/schema/generate-id.test.ts +3 -2
  502. package/src/schema/generate-id.ts +2 -2
  503. package/src/schema/serialize.test.ts +18 -5
  504. package/src/schema/type-conversion/create-sql-type-mapper.ts +8 -3
  505. package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
  506. package/src/schema/type-conversion/type-mapping.test.ts +26 -1
  507. package/src/schema/validator.test.ts +199 -0
  508. package/src/schema/validator.ts +232 -0
  509. package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +232 -129
  510. package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +155 -99
  511. package/src/schema-output/prisma.test.ts +694 -0
  512. package/src/schema-output/prisma.ts +593 -0
  513. package/src/sql-driver/better-sqlite3.test.ts +5 -3
  514. package/src/sql-driver/dialects/durable-object-dialect.ts +3 -8
  515. package/src/sql-driver/query-executor/default-query-executor.ts +1 -1
  516. package/src/sql-driver/query-executor/query-executor-base.ts +1 -1
  517. package/src/sql-driver/query-executor/query-executor.ts +1 -1
  518. package/src/sql-driver/sql-driver-adapter.ts +2 -2
  519. package/src/sql-driver/sql.ts +2 -1
  520. package/src/sql-driver/sqlocal.test.ts +4 -2
  521. package/src/sync/commands.test.ts +39 -0
  522. package/src/sync/commands.ts +51 -0
  523. package/src/sync/conflict-checker.test.ts +450 -0
  524. package/src/sync/conflict-checker.ts +248 -0
  525. package/src/sync/index.ts +14 -0
  526. package/src/sync/plan.ts +9 -0
  527. package/src/sync/read-tracking.test.ts +177 -0
  528. package/src/sync/read-tracking.ts +287 -0
  529. package/src/sync/submit.test.ts +205 -0
  530. package/src/sync/submit.ts +328 -0
  531. package/src/sync/types.ts +80 -0
  532. package/src/util/default-database-adapter.ts +119 -0
  533. package/src/with-database.ts +20 -31
  534. package/tsconfig.json +1 -1
  535. package/tsdown.config.ts +38 -24
  536. package/vitest.config.ts +1 -0
  537. package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
  538. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
  539. package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
  540. package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
  541. package/dist/adapters/drizzle/generate.d.ts +0 -30
  542. package/dist/adapters/drizzle/generate.d.ts.map +0 -1
  543. package/dist/adapters/drizzle/generate.js.map +0 -1
  544. package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
  545. package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
  546. package/dist/adapters/kysely/kysely-adapter.js +0 -17
  547. package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
  548. package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
  549. package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
  550. package/dist/adapters/shared/table-name-mapper.js +0 -43
  551. package/dist/adapters/shared/table-name-mapper.js.map +0 -1
  552. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +0 -165
  553. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
  554. package/dist/packages/fragno/dist/api/bind-services.js +0 -20
  555. package/dist/packages/fragno/dist/api/bind-services.js.map +0 -1
  556. package/dist/packages/fragno/dist/api/error.js +0 -48
  557. package/dist/packages/fragno/dist/api/error.js.map +0 -1
  558. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +0 -320
  559. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
  560. package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -525
  561. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +0 -1
  562. package/dist/packages/fragno/dist/api/fragno-response.js +0 -73
  563. package/dist/packages/fragno/dist/api/fragno-response.js.map +0 -1
  564. package/dist/packages/fragno/dist/api/internal/response-stream.js +0 -81
  565. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +0 -1
  566. package/dist/packages/fragno/dist/api/internal/route.js +0 -10
  567. package/dist/packages/fragno/dist/api/internal/route.js.map +0 -1
  568. package/dist/packages/fragno/dist/api/mutable-request-state.js +0 -97
  569. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +0 -1
  570. package/dist/packages/fragno/dist/api/request-context-storage.js +0 -43
  571. package/dist/packages/fragno/dist/api/request-context-storage.js.map +0 -1
  572. package/dist/packages/fragno/dist/api/request-input-context.js +0 -118
  573. package/dist/packages/fragno/dist/api/request-input-context.js.map +0 -1
  574. package/dist/packages/fragno/dist/api/request-middleware.js +0 -83
  575. package/dist/packages/fragno/dist/api/request-middleware.js.map +0 -1
  576. package/dist/packages/fragno/dist/api/request-output-context.js +0 -119
  577. package/dist/packages/fragno/dist/api/request-output-context.js.map +0 -1
  578. package/dist/packages/fragno/dist/api/route.js +0 -17
  579. package/dist/packages/fragno/dist/api/route.js.map +0 -1
  580. package/dist/packages/fragno/dist/internal/symbols.js +0 -10
  581. package/dist/packages/fragno/dist/internal/symbols.js.map +0 -1
  582. package/dist/schema-generator/schema-generator.d.ts +0 -15
  583. package/dist/schema-generator/schema-generator.d.ts.map +0 -1
  584. package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
  585. package/src/adapters/kysely/kysely-adapter.ts +0 -27
  586. package/src/adapters/shared/table-name-mapper.ts +0 -50
  587. package/src/schema-generator/schema-generator.ts +0 -12
@@ -1,6 +1,12 @@
1
+ import type { StandardSchemaV1 } from "@standard-schema/spec";
2
+
1
3
  import { createId } from "../id";
4
+ import type { DbNow } from "../query/db-now";
5
+ import type { Prettify } from "../util/types";
6
+ import { createTableStandardSchemaProps, createTableValidator } from "./validator";
2
7
 
3
8
  export { generateId } from "./generate-id";
9
+ export { FragnoDbValidationError } from "./validator";
4
10
 
5
11
  export type AnySchema = Schema<Record<string, AnyTable>>;
6
12
 
@@ -20,6 +26,16 @@ export type AnyColumn =
20
26
  export type TableSubOperation =
21
27
  | { type: "add-column"; columnName: string; column: AnyColumn }
22
28
  | { type: "add-index"; name: string; columns: string[]; unique: boolean }
29
+ | { type: "rename-column"; from: string; to: string }
30
+ | { type: "drop-column"; name: string }
31
+ | {
32
+ type: "update-column";
33
+ columnName: string;
34
+ column: AnyColumn;
35
+ updateNullable: boolean;
36
+ updateDefault: boolean;
37
+ updateDataType: boolean;
38
+ }
23
39
  | {
24
40
  type: "add-foreign-key";
25
41
  name: string;
@@ -51,6 +67,7 @@ export type SchemaOperation =
51
67
  type: "one" | "many";
52
68
  from: { table: string; column: string };
53
69
  to: { table: string; column: string };
70
+ foreignKey?: boolean;
54
71
  };
55
72
  };
56
73
 
@@ -72,11 +89,18 @@ class RelationInit<
72
89
  referencedTable: TTables[TTableName];
73
90
  referencer: AnyTable;
74
91
  on: [string, string][] = [];
92
+ foreignKey: boolean;
75
93
 
76
- constructor(type: TRelationType, referencedTable: TTables[TTableName], referencer: AnyTable) {
94
+ constructor(
95
+ type: TRelationType,
96
+ referencedTable: TTables[TTableName],
97
+ referencer: AnyTable,
98
+ options?: { foreignKey?: boolean },
99
+ ) {
77
100
  this.type = type;
78
101
  this.referencedTable = referencedTable;
79
102
  this.referencer = referencer;
103
+ this.foreignKey = options?.foreignKey ?? true;
80
104
  }
81
105
  }
82
106
 
@@ -95,16 +119,17 @@ export class ExplicitRelationInit<
95
119
  TTables extends Record<string, AnyTable>,
96
120
  TTableName extends keyof TTables,
97
121
  > extends RelationInit<TRelationType, TTables, TTableName> {
98
- init(ormName: string): Relation<TRelationType, TTables[TTableName]> {
99
- const id = `${this.referencer.ormName}_${this.referencedTable.ormName}`;
122
+ init(name: string): Relation<TRelationType, TTables[TTableName]> {
123
+ const id = `${this.referencer.name}_${this.referencedTable.name}`;
100
124
 
101
125
  return {
102
126
  id,
103
127
  on: this.on,
104
- name: ormName,
128
+ name,
105
129
  referencer: this.referencer,
106
130
  table: this.referencedTable,
107
131
  type: this.type,
132
+ foreignKey: this.foreignKey,
108
133
  };
109
134
  }
110
135
  }
@@ -116,6 +141,7 @@ export interface Relation<
116
141
  id: string;
117
142
  name: string;
118
143
  type: TRelationType;
144
+ foreignKey?: boolean;
119
145
 
120
146
  table: TTable;
121
147
  referencer: AnyTable;
@@ -123,18 +149,57 @@ export interface Relation<
123
149
  on: [string, string][];
124
150
  }
125
151
 
152
+ type PickNullable<T> = {
153
+ [P in keyof T as null extends T[P] ? P : never]: T[P];
154
+ };
155
+
156
+ type PickNotNullable<T> = {
157
+ [P in keyof T as null extends T[P] ? never : P]: T[P];
158
+ };
159
+
160
+ type RawInsertValuesFromColumns<TColumns extends Record<string, AnyColumn>> = {
161
+ [K in keyof TColumns as string extends K ? never : K]: TColumns[K]["$in"];
162
+ };
163
+
164
+ type TableInsertValuesFromColumns<TColumns extends Record<string, AnyColumn>> = Prettify<
165
+ Partial<PickNullable<RawInsertValuesFromColumns<TColumns>>> &
166
+ PickNotNullable<RawInsertValuesFromColumns<TColumns>>
167
+ >;
168
+
169
+ export type TableInsertValues<T extends AnyTable> = TableInsertValuesFromColumns<T["columns"]>;
170
+
171
+ export type TableUnknownKeysMode = "strip" | "strict";
172
+
173
+ export type TableValidationOptions = {
174
+ unknownKeys?: TableUnknownKeysMode;
175
+ };
176
+
126
177
  export interface Table<
127
178
  TColumns extends Record<string, AnyColumn> = Record<string, AnyColumn>,
128
179
  TRelations extends Record<string, AnyRelation> = Record<string, AnyRelation>,
129
180
  TIndexes extends Record<string, Index> = Record<string, Index>,
130
181
  > {
182
+ /**
183
+ * Standard Schema-compatible validator for insert values.
184
+ */
185
+ "~standard": StandardSchemaV1.Props<
186
+ TableInsertValuesFromColumns<TColumns>,
187
+ TableInsertValuesFromColumns<TColumns>
188
+ >;
131
189
  name: string;
132
- ormName: string;
133
190
 
134
191
  columns: TColumns;
135
192
  relations: TRelations;
136
193
  indexes: TIndexes;
137
194
 
195
+ /**
196
+ * Validate insert values at runtime.
197
+ */
198
+ validate: (
199
+ value: unknown,
200
+ options?: TableValidationOptions,
201
+ ) => TableInsertValuesFromColumns<TColumns>;
202
+
138
203
  /**
139
204
  * Get column by name
140
205
  */
@@ -203,7 +268,6 @@ export type TypeMap = {
203
268
  export class Column<TType extends keyof TypeMap, TIn = unknown, TOut = unknown> {
204
269
  type: TType;
205
270
  name: string = "";
206
- ormName: string = "";
207
271
  isNullable: boolean = false;
208
272
  role: "external-id" | "internal-id" | "version" | "reference" | "regular" = "regular";
209
273
  isHidden: boolean = false;
@@ -421,9 +485,36 @@ export class VersionColumn<TIn = unknown, TOut = unknown> extends Column<"intege
421
485
  }
422
486
  }
423
487
 
488
+ function cloneColumn<TColumn extends AnyColumn>(col: TColumn): TColumn {
489
+ let clonedCol: AnyColumn;
490
+
491
+ if (col instanceof InternalIdColumn) {
492
+ clonedCol = new InternalIdColumn();
493
+ } else if (col instanceof VersionColumn) {
494
+ clonedCol = new VersionColumn();
495
+ } else if (col instanceof IdColumn) {
496
+ clonedCol = new IdColumn(col.type);
497
+ } else {
498
+ clonedCol = new Column(col.type);
499
+ }
500
+
501
+ clonedCol.name = col.name;
502
+ clonedCol.isNullable = col.isNullable;
503
+ clonedCol.role = col.role;
504
+ clonedCol.isHidden = col.isHidden;
505
+ clonedCol.default = col.default;
506
+ clonedCol.tableName = col.tableName;
507
+
508
+ return clonedCol as TColumn;
509
+ }
510
+
511
+ type ColumnInput<TType extends keyof TypeMap> =
512
+ | TypeMap[TType]
513
+ | (TType extends "timestamp" | "date" ? DbNow : never);
514
+
424
515
  export function column<TType extends keyof TypeMap>(
425
516
  type: TType,
426
- ): Column<TType, TypeMap[TType], TypeMap[TType]> {
517
+ ): Column<TType, ColumnInput<TType>, TypeMap[TType]> {
427
518
  return new Column(type);
428
519
  }
429
520
 
@@ -449,8 +540,8 @@ export function referenceColumn(): Column<
449
540
  * This is a CUID string that can be auto-generated or user-provided.
450
541
  * Input accepts string | FragnoId | null, output returns FragnoId.
451
542
  */
452
- export function idColumn(): IdColumn<"varchar(30)", string | FragnoId | null, FragnoId> {
453
- const col = new IdColumn<"varchar(30)", string | FragnoId | null, FragnoId>("varchar(30)");
543
+ export function idColumn(): IdColumn<"varchar(128)", string | FragnoId | null, FragnoId> {
544
+ const col = new IdColumn<"varchar(128)", string | FragnoId | null, FragnoId>("varchar(128)");
454
545
  col.role = "external-id";
455
546
  col.defaultTo$((b) => b.cuid());
456
547
  return col;
@@ -579,6 +670,8 @@ export class FragnoReference {
579
670
  }
580
671
  }
581
672
 
673
+ const validationClasses = { FragnoId, FragnoReference };
674
+
582
675
  type RelationType = "one" | "many";
583
676
 
584
677
  export class TableBuilder<
@@ -590,7 +683,6 @@ export class TableBuilder<
590
683
  #columns: TColumns;
591
684
  #relations: TRelations;
592
685
  #indexes: TIndexes;
593
- #ormName: string = "";
594
686
  #columnOrder: string[] = [];
595
687
 
596
688
  constructor(name: string) {
@@ -626,7 +718,7 @@ export class TableBuilder<
626
718
  * Add a column to the table.
627
719
  */
628
720
  addColumn<TColumnName extends string, TColumn extends AnyColumn>(
629
- ormName: TColumnName,
721
+ name: TColumnName,
630
722
  col: TColumn,
631
723
  ): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes>;
632
724
 
@@ -634,28 +726,27 @@ export class TableBuilder<
634
726
  * Add a column to the table with simplified syntax.
635
727
  */
636
728
  addColumn<TColumnName extends string, TType extends keyof TypeMap>(
637
- ormName: TColumnName,
729
+ name: TColumnName,
638
730
  type: TType,
639
731
  ): TableBuilder<
640
- TColumns & Record<TColumnName, Column<TType, TypeMap[TType], TypeMap[TType]>>,
732
+ TColumns & Record<TColumnName, Column<TType, ColumnInput<TType>, TypeMap[TType]>>,
641
733
  TRelations,
642
734
  TIndexes
643
735
  >;
644
736
 
645
737
  addColumn<TColumnName extends string, TColumn extends AnyColumn, TType extends keyof TypeMap>(
646
- ormName: TColumnName,
738
+ name: TColumnName,
647
739
  colOrType: TColumn | TType,
648
740
  ): TableBuilder<TColumns & Record<TColumnName, TColumn>, TRelations, TIndexes> {
649
741
  // Create the column if a type string was provided
650
742
  const col = typeof colOrType === "string" ? column(colOrType) : colOrType;
651
743
 
652
744
  // Set column metadata
653
- col.ormName = ormName;
654
- col.name = ormName;
745
+ col.name = name;
655
746
 
656
747
  // Add column directly to this builder
657
- this.#columns[ormName] = col as unknown as TColumns[TColumnName];
658
- this.#columnOrder.push(ormName);
748
+ this.#columns[name] = col as unknown as TColumns[TColumnName];
749
+ this.#columnOrder.push(name);
659
750
 
660
751
  return this as unknown as TableBuilder<
661
752
  TColumns & Record<TColumnName, TColumn>,
@@ -664,6 +755,32 @@ export class TableBuilder<
664
755
  >;
665
756
  }
666
757
 
758
+ /**
759
+ * Alter an existing column.
760
+ */
761
+ alterColumn<TColumnName extends NonIdColumnName<TColumns>>(
762
+ name: TColumnName,
763
+ ): ColumnAlterer<TColumns, TRelations, TIndexes, TColumnName> {
764
+ return {
765
+ nullable: <TNullable extends boolean = true>(nullable?: TNullable) => {
766
+ const column = this.#columns[name];
767
+ if (!column) {
768
+ throw new Error(`Unknown column name ${String(name)}`);
769
+ }
770
+
771
+ const cloned = cloneColumn(column) as Column<keyof TypeMap>;
772
+ const updated = cloned.nullable(nullable ?? true);
773
+ this.#columns[name] = updated as unknown as TColumns[TColumnName];
774
+
775
+ return this as unknown as TableBuilder<
776
+ UpdateColumn<TColumns, TColumnName, NullableColumn<TColumns[TColumnName], TNullable>>,
777
+ TRelations,
778
+ TIndexes
779
+ >;
780
+ },
781
+ };
782
+ }
783
+
667
784
  /**
668
785
  * Create an index on the specified columns.
669
786
  */
@@ -716,7 +833,6 @@ export class TableBuilder<
716
833
  // Auto-add _internalId and _version columns if not already present
717
834
  if (!this.#columns["_internalId"]) {
718
835
  const col = internalIdColumn();
719
- col.ormName = "_internalId";
720
836
  col.name = "_internalId";
721
837
  // Safe: we're adding system columns to the internal columns object
722
838
  (this.#columns as Record<string, AnyColumn>)["_internalId"] = col;
@@ -724,18 +840,13 @@ export class TableBuilder<
724
840
 
725
841
  if (!this.#columns["_version"]) {
726
842
  const col = versionColumn();
727
- col.ormName = "_version";
728
843
  col.name = "_version";
729
844
  // Safe: we're adding system columns to the internal columns object
730
845
  (this.#columns as Record<string, AnyColumn>)["_version"] = col;
731
846
  }
732
847
 
733
- // Use name as ormName if ormName is not set
734
- const ormName = this.#ormName || this.#name;
735
-
736
- const table: Table<TColumns, TRelations, TIndexes> = {
848
+ const table = {
737
849
  name: this.#name,
738
- ormName,
739
850
  columns: this.#columns,
740
851
  relations: this.#relations,
741
852
  indexes: this.#indexes,
@@ -751,7 +862,10 @@ export class TableBuilder<
751
862
  getVersionColumn: () => {
752
863
  return versionCol!;
753
864
  },
754
- };
865
+ } as Table<TColumns, TRelations, TIndexes>;
866
+
867
+ table["~standard"] = createTableStandardSchemaProps(table, validationClasses);
868
+ table.validate = createTableValidator(table, validationClasses);
755
869
 
756
870
  // Set table reference and find special columns
757
871
  for (const k in this.#columns) {
@@ -787,6 +901,10 @@ export class TableBuilder<
787
901
  }
788
902
 
789
903
  export interface Schema<TTables extends Record<string, AnyTable> = Record<string, AnyTable>> {
904
+ /**
905
+ * @description The name of the schema (required).
906
+ */
907
+ name: string;
790
908
  /**
791
909
  * @description The version of the schema, automatically incremented on each change.
792
910
  */
@@ -850,12 +968,55 @@ type ColumnsToTuple<
850
968
  : never;
851
969
  } & AnyColumn[];
852
970
 
971
+ type UpdateColumn<
972
+ TColumns extends Record<string, AnyColumn>,
973
+ TColumnName extends keyof TColumns,
974
+ TUpdatedColumn extends AnyColumn,
975
+ > = Prettify<Omit<TColumns, TColumnName> & Record<TColumnName, TUpdatedColumn>>;
976
+
977
+ type NonIdColumnName<TColumns extends Record<string, AnyColumn>> = {
978
+ [K in keyof TColumns]: TColumns[K] extends
979
+ | IdColumn<IdColumnType, unknown, unknown>
980
+ | InternalIdColumn<unknown, unknown>
981
+ | VersionColumn<unknown, unknown>
982
+ ? never
983
+ : K;
984
+ }[keyof TColumns];
985
+
986
+ type NullableColumn<TColumn extends AnyColumn, TNullable extends boolean> =
987
+ TColumn extends Column<infer TType, infer TIn, infer TOut>
988
+ ? Column<
989
+ TType,
990
+ TNullable extends true ? TIn | null : Exclude<TIn, null>,
991
+ TNullable extends true ? TOut | null : Exclude<TOut, null>
992
+ >
993
+ : TColumn;
994
+
995
+ type ColumnAlterer<
996
+ TColumns extends Record<string, AnyColumn>,
997
+ TRelations extends Record<string, AnyRelation>,
998
+ TIndexes extends Record<string, Index>,
999
+ TColumnName extends keyof TColumns,
1000
+ > = {
1001
+ nullable<TNullable extends boolean = true>(
1002
+ nullable?: TNullable,
1003
+ ): TableBuilder<
1004
+ UpdateColumn<TColumns, TColumnName, NullableColumn<TColumns[TColumnName], TNullable>>,
1005
+ TRelations,
1006
+ TIndexes
1007
+ >;
1008
+ };
1009
+
853
1010
  export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1011
+ #name: string;
854
1012
  #tables: TTables;
855
1013
  #version: number = 0;
856
1014
  #operations: SchemaOperation[] = [];
1015
+ #tableNames: Set<string> = new Set();
1016
+ #indexNames: Set<string> = new Set();
857
1017
 
858
- constructor(existingSchema?: Schema<TTables>) {
1018
+ constructor(name: string, existingSchema?: Schema<TTables>) {
1019
+ this.#name = name;
859
1020
  if (existingSchema) {
860
1021
  this.#tables = existingSchema.tables;
861
1022
  this.#version = existingSchema.version;
@@ -863,6 +1024,54 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
863
1024
  } else {
864
1025
  this.#tables = {} as TTables;
865
1026
  }
1027
+
1028
+ for (const table of Object.values(this.#tables)) {
1029
+ this.#registerTableName(table.name);
1030
+ for (const index of Object.values(table.indexes)) {
1031
+ this.#registerIndexName(index.name, table.name);
1032
+ }
1033
+ }
1034
+ }
1035
+
1036
+ #registerTableName(name: string): void {
1037
+ if (this.#tableNames.has(name)) {
1038
+ throw new Error(`Duplicate table name "${name}" in schema "${this.#name}".`);
1039
+ }
1040
+ this.#tableNames.add(name);
1041
+ }
1042
+
1043
+ #registerIndexName(name: string, tableName: string): void {
1044
+ if (this.#indexNames.has(name)) {
1045
+ throw new Error(
1046
+ `Duplicate index name "${name}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${tableName}").`,
1047
+ );
1048
+ }
1049
+ this.#indexNames.add(name);
1050
+ }
1051
+
1052
+ #rebindRelations(tableName: string, newTable: AnyTable): void {
1053
+ for (const table of Object.values(this.#tables)) {
1054
+ for (const relation of Object.values(table.relations)) {
1055
+ if (relation.table.name === tableName) {
1056
+ relation.table = newTable;
1057
+ }
1058
+ if (relation.referencer.name === tableName) {
1059
+ relation.referencer = newTable;
1060
+ }
1061
+ }
1062
+ }
1063
+ }
1064
+
1065
+ #isJoinColumnIndexed(table: AnyTable, columnName: string): boolean {
1066
+ const idColumnName = table.getIdColumn().name;
1067
+ const internalIdColumnName = table.getInternalIdColumn().name;
1068
+ if (columnName === idColumnName || columnName === internalIdColumnName) {
1069
+ return true;
1070
+ }
1071
+
1072
+ return Object.values(table.indexes).some((index) =>
1073
+ index.columnNames.some((name) => name === columnName),
1074
+ );
866
1075
  }
867
1076
 
868
1077
  /**
@@ -871,7 +1080,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
871
1080
  *
872
1081
  * @example
873
1082
  * ```ts
874
- * const builder = new SchemaBuilder()
1083
+ * const builder = new SchemaBuilder("combined")
875
1084
  * .add(userSchema)
876
1085
  * .add(postSchema)
877
1086
  * .addTable("comments", ...);
@@ -880,10 +1089,32 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
880
1089
  mergeWithExistingSchema<TNewTables extends Record<string, AnyTable>>(
881
1090
  schema: Schema<TNewTables>,
882
1091
  ): SchemaBuilder<TTables & TNewTables> {
1092
+ for (const table of Object.values(schema.tables)) {
1093
+ if (this.#tableNames.has(table.name)) {
1094
+ throw new Error(
1095
+ `Duplicate table name "${table.name}" in schema "${this.#name}" when merging.`,
1096
+ );
1097
+ }
1098
+ for (const index of Object.values(table.indexes)) {
1099
+ if (this.#indexNames.has(index.name)) {
1100
+ throw new Error(
1101
+ `Duplicate index name "${index.name}" in schema "${this.#name}" when merging (conflict on "${table.name}").`,
1102
+ );
1103
+ }
1104
+ }
1105
+ }
1106
+
883
1107
  this.#tables = { ...this.#tables, ...schema.tables } as TTables & TNewTables;
884
1108
  this.#operations = [...this.#operations, ...schema.operations];
885
1109
  this.#version += schema.version;
886
1110
 
1111
+ for (const table of Object.values(schema.tables)) {
1112
+ this.#tableNames.add(table.name);
1113
+ for (const index of Object.values(table.indexes)) {
1114
+ this.#indexNames.add(index.name);
1115
+ }
1116
+ }
1117
+
887
1118
  return this as unknown as SchemaBuilder<TTables & TNewTables>;
888
1119
  }
889
1120
 
@@ -896,21 +1127,31 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
896
1127
  TRelations extends Record<string, AnyRelation>,
897
1128
  TIndexes extends Record<string, Index> = Record<string, Index>,
898
1129
  >(
899
- ormName: TTableName,
1130
+ name: TTableName,
900
1131
  callback: (
901
- builder: TableBuilder<
902
- Record<string, AnyColumn>,
903
- Record<string, AnyRelation>,
904
- Record<string, Index>
905
- >,
1132
+ builder: TableBuilder<{}, Record<string, AnyRelation>, Record<string, Index>>,
906
1133
  ) => TableBuilder<TColumns, TRelations, TIndexes>,
907
1134
  ): SchemaBuilder<TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>> {
908
1135
  this.#version++;
909
1136
 
910
- const tableBuilder = new TableBuilder(ormName);
1137
+ if (this.#tableNames.has(name)) {
1138
+ throw new Error(`Duplicate table name "${name}" in schema "${this.#name}".`);
1139
+ }
1140
+
1141
+ const tableBuilder = new TableBuilder<{}, Record<string, AnyRelation>, Record<string, Index>>(
1142
+ name,
1143
+ );
911
1144
  const result = callback(tableBuilder);
912
1145
  const builtTable = result.build();
913
- builtTable.ormName = ormName;
1146
+ const indexNames = result.getIndexes().map((idx) => idx.name);
1147
+
1148
+ for (const indexName of indexNames) {
1149
+ if (this.#indexNames.has(indexName)) {
1150
+ throw new Error(
1151
+ `Duplicate index name "${indexName}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${name}").`,
1152
+ );
1153
+ }
1154
+ }
914
1155
 
915
1156
  // Collect sub-operations in order
916
1157
  const subOperations: TableSubOperation[] = [];
@@ -922,7 +1163,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
922
1163
  subOperations.push({
923
1164
  type: "add-column",
924
1165
  columnName: colName,
925
- column: col,
1166
+ column: cloneColumn(col),
926
1167
  });
927
1168
  }
928
1169
 
@@ -931,14 +1172,14 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
931
1172
  subOperations.push({
932
1173
  type: "add-column",
933
1174
  columnName: "_internalId",
934
- column: builtTable.columns["_internalId"],
1175
+ column: cloneColumn(builtTable.columns["_internalId"]),
935
1176
  });
936
1177
  }
937
1178
  if (builtTable.columns["_version"]) {
938
1179
  subOperations.push({
939
1180
  type: "add-column",
940
1181
  columnName: "_version",
941
- column: builtTable.columns["_version"],
1182
+ column: cloneColumn(builtTable.columns["_version"]),
942
1183
  });
943
1184
  }
944
1185
 
@@ -947,7 +1188,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
947
1188
  subOperations.push({
948
1189
  type: "add-index",
949
1190
  name: idx.name,
950
- columns: idx.columns.map((c) => c.ormName),
1191
+ columns: idx.columns.map((c) => c.name),
951
1192
  unique: idx.unique,
952
1193
  });
953
1194
  }
@@ -955,13 +1196,17 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
955
1196
  // Add the add-table operation
956
1197
  this.#operations.push({
957
1198
  type: "add-table",
958
- tableName: ormName,
1199
+ tableName: name,
959
1200
  operations: subOperations,
960
1201
  });
961
1202
 
962
1203
  // Update tables map
963
- this.#tables = { ...this.#tables, [ormName]: builtTable } as TTables &
1204
+ this.#tables = { ...this.#tables, [name]: builtTable } as TTables &
964
1205
  Record<TTableName, Table<TColumns, TRelations, TIndexes>>;
1206
+ this.#tableNames.add(name);
1207
+ for (const indexName of indexNames) {
1208
+ this.#indexNames.add(indexName);
1209
+ }
965
1210
 
966
1211
  return this as unknown as SchemaBuilder<
967
1212
  TTables & Record<TTableName, Table<TColumns, TRelations, TIndexes>>
@@ -977,7 +1222,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
977
1222
  * @example
978
1223
  * ```ts
979
1224
  * // One-to-one or many-to-one: post -> user
980
- * schema(s => s
1225
+ * schema("blog", s => s
981
1226
  * .addTable("users", t => t.addColumn("id", idColumn()))
982
1227
  * .addTable("posts", t => t
983
1228
  * .addColumn("id", idColumn())
@@ -1002,6 +1247,14 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1002
1247
  * from: { table: "users", column: "invitedBy" },
1003
1248
  * to: { table: "users", column: "id" },
1004
1249
  * })
1250
+ *
1251
+ * // Join-only relation (no foreign key)
1252
+ * .addReference("invitedUser", {
1253
+ * type: "one",
1254
+ * from: { table: "invitations", column: "email" },
1255
+ * to: { table: "users", column: "email" },
1256
+ * foreignKey: false,
1257
+ * })
1005
1258
  * ```
1006
1259
  */
1007
1260
  addReference<
@@ -1021,6 +1274,12 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1021
1274
  table: TToTableName;
1022
1275
  column: keyof TTables[TToTableName]["columns"];
1023
1276
  };
1277
+ /**
1278
+ * When false, defines a join-only relation without foreign key migrations.
1279
+ * References to external-id columns still coerce to `_internalId`
1280
+ * (including left-side external IDs for join-only).
1281
+ */
1282
+ foreignKey?: boolean;
1024
1283
  },
1025
1284
  ): SchemaBuilder<
1026
1285
  UpdateTableRelations<TTables, TFromTableName, TReferenceName, TToTableName, TRelationType>
@@ -1030,6 +1289,10 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1030
1289
  const table = this.#tables[config.from.table];
1031
1290
  const referencedTable = this.#tables[config.to.table];
1032
1291
 
1292
+ if (!referenceName || referenceName.trim().length === 0) {
1293
+ throw new Error(`referenceName is required for addReference on ${config.from.table}`);
1294
+ }
1295
+
1033
1296
  if (!table) {
1034
1297
  throw new Error(`Table ${config.from.table} not found in schema`);
1035
1298
  }
@@ -1039,21 +1302,33 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1039
1302
 
1040
1303
  const columnName = config.from.column as string;
1041
1304
  const targetColumnName = config.to.column as string;
1042
-
1043
- // Foreign keys always reference internal IDs, not external IDs
1044
- // If user specifies "id", translate to "_internalId" for the actual FK
1045
- const actualTargetColumnName = targetColumnName === "id" ? "_internalId" : targetColumnName;
1305
+ const foreignKey = config.foreignKey !== false;
1046
1306
 
1047
1307
  const column = table.columns[columnName];
1048
- const referencedColumn = referencedTable.columns[actualTargetColumnName];
1308
+ const targetColumn = referencedTable.columns[targetColumnName];
1049
1309
 
1050
1310
  if (!column) {
1051
1311
  throw new Error(`Column ${columnName} not found in table ${config.from.table}`);
1052
1312
  }
1313
+ if (!targetColumn) {
1314
+ throw new Error(`Column ${targetColumnName} not found in table ${config.to.table}`);
1315
+ }
1316
+
1317
+ // External-id columns always target the internal ID column.
1318
+ const actualTargetColumnName =
1319
+ targetColumn.role === "external-id"
1320
+ ? referencedTable.getInternalIdColumn().name
1321
+ : targetColumnName;
1322
+
1323
+ const referencedColumn = referencedTable.columns[actualTargetColumnName];
1053
1324
  if (!referencedColumn) {
1054
1325
  throw new Error(`Column ${actualTargetColumnName} not found in table ${config.to.table}`);
1055
1326
  }
1056
1327
 
1328
+ if (table.relations[referenceName]) {
1329
+ throw new Error(`Reference ${referenceName} already exists on table ${config.from.table}`);
1330
+ }
1331
+
1057
1332
  // Verify that reference columns are bigint (matching internal ID type)
1058
1333
  if (column.role === "reference" && column.type !== "bigint") {
1059
1334
  throw new Error(
@@ -1061,9 +1336,28 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1061
1336
  );
1062
1337
  }
1063
1338
 
1064
- // Create the relation (use the user-facing column name for the relation)
1065
- const init = new ExplicitRelationInit(config.type, referencedTable, table);
1066
- init.on.push([columnName, targetColumnName]);
1339
+ if (!foreignKey) {
1340
+ const missingIndexes: string[] = [];
1341
+ if (!this.#isJoinColumnIndexed(table, columnName)) {
1342
+ missingIndexes.push(`${table.name}.${columnName}`);
1343
+ }
1344
+ if (!this.#isJoinColumnIndexed(referencedTable, actualTargetColumnName)) {
1345
+ missingIndexes.push(`${referencedTable.name}.${actualTargetColumnName}`);
1346
+ }
1347
+ if (missingIndexes.length > 0) {
1348
+ throw new Error(
1349
+ `Join-only relation "${referenceName}" requires indexed join columns: ${missingIndexes.join(", ")}.`,
1350
+ );
1351
+ }
1352
+ }
1353
+
1354
+ // Join-only relations treat external IDs as internal IDs on the left side.
1355
+ const actualFromColumnName =
1356
+ !foreignKey && column.role === "external-id" ? table.getInternalIdColumn().name : columnName;
1357
+
1358
+ // Create the relation (use user-facing right-side column name)
1359
+ const init = new ExplicitRelationInit(config.type, referencedTable, table, { foreignKey });
1360
+ init.on.push([actualFromColumnName, targetColumnName]);
1067
1361
  const relation = init.init(referenceName);
1068
1362
 
1069
1363
  // Add relation to the table
@@ -1076,8 +1370,9 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1076
1370
  referenceName,
1077
1371
  config: {
1078
1372
  type: config.type,
1079
- from: { table: config.from.table, column: columnName },
1373
+ from: { table: config.from.table, column: actualFromColumnName },
1080
1374
  to: { table: config.to.table, column: actualTargetColumnName },
1375
+ foreignKey,
1081
1376
  },
1082
1377
  });
1083
1378
 
@@ -1089,8 +1384,8 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1089
1384
  }
1090
1385
 
1091
1386
  /**
1092
- * Alter an existing table by adding columns or indexes.
1093
- * This is used for append-only schema modifications.
1387
+ * Alter an existing table by adding columns, altering columns, or adding indexes.
1388
+ * This is used for forward-only schema modifications.
1094
1389
  *
1095
1390
  * @param tableName - The name of the table to modify
1096
1391
  * @param callback - A callback that receives a table builder for adding columns/indexes
@@ -1098,11 +1393,12 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1098
1393
  * @example
1099
1394
  * ```ts
1100
1395
  * // Add a new column to an existing table
1101
- * schema(s => s
1396
+ * schema("blog", s => s
1102
1397
  * .addTable("users", t => t
1103
1398
  * .addColumn("id", idColumn())
1104
1399
  * .addColumn("name", column("string")))
1105
1400
  * .alterTable("users", t => t
1401
+ * .alterColumn("name").nullable()
1106
1402
  * .addColumn("email", column("string"))
1107
1403
  * .addColumn("age", column("integer").nullable())
1108
1404
  * .createIndex("idx_email", ["email"]))
@@ -1139,6 +1435,10 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1139
1435
  // Track existing columns and indexes
1140
1436
  const existingColumns = new Set(Object.keys(table.columns));
1141
1437
  const existingIndexes = new Set(Object.keys(table.indexes));
1438
+ const existingColumnState = new Map<string, { isNullable: boolean }>();
1439
+ for (const [colName, col] of Object.entries(table.columns)) {
1440
+ existingColumnState.set(colName, { isNullable: col.isNullable });
1441
+ }
1142
1442
 
1143
1443
  // Apply modifications
1144
1444
  const resultBuilder = callback(
@@ -1160,7 +1460,25 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1160
1460
  subOperations.push({
1161
1461
  type: "add-column",
1162
1462
  columnName: colName,
1163
- column: newTable.columns[colName],
1463
+ column: cloneColumn(newTable.columns[colName]),
1464
+ });
1465
+ }
1466
+ }
1467
+
1468
+ // Track updates to existing columns
1469
+ for (const [colName, previousState] of existingColumnState.entries()) {
1470
+ const updatedColumn = newTable.columns[colName];
1471
+ if (!updatedColumn) {
1472
+ continue;
1473
+ }
1474
+ if (previousState.isNullable !== updatedColumn.isNullable) {
1475
+ subOperations.push({
1476
+ type: "update-column",
1477
+ columnName: colName,
1478
+ column: cloneColumn(updatedColumn),
1479
+ updateNullable: true,
1480
+ updateDefault: false,
1481
+ updateDataType: false,
1164
1482
  });
1165
1483
  }
1166
1484
  }
@@ -1168,10 +1486,15 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1168
1486
  // Add only new indexes
1169
1487
  for (const idx of resultBuilder.getIndexes()) {
1170
1488
  if (!existingIndexes.has(idx.name)) {
1489
+ if (this.#indexNames.has(idx.name)) {
1490
+ throw new Error(
1491
+ `Duplicate index name "${idx.name}" in schema "${this.#name}". Index names must be unique across tables (conflict on "${tableName}").`,
1492
+ );
1493
+ }
1171
1494
  subOperations.push({
1172
1495
  type: "add-index",
1173
1496
  name: idx.name,
1174
- columns: idx.columns.map((c) => c.ormName),
1497
+ columns: idx.columns.map((c) => c.name),
1175
1498
  unique: idx.unique,
1176
1499
  });
1177
1500
  }
@@ -1188,6 +1511,12 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1188
1511
 
1189
1512
  // Update table reference in schema
1190
1513
  this.#tables[tableName] = newTable as unknown as TTables[TTableName];
1514
+ this.#rebindRelations(tableName, newTable as unknown as AnyTable);
1515
+ for (const idx of resultBuilder.getIndexes()) {
1516
+ if (!existingIndexes.has(idx.name)) {
1517
+ this.#indexNames.add(idx.name);
1518
+ }
1519
+ }
1191
1520
 
1192
1521
  // Set table name for all columns
1193
1522
  for (const col of Object.values(newTable.columns)) {
@@ -1208,6 +1537,7 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1208
1537
  const tables = this.#tables;
1209
1538
 
1210
1539
  const schema: Schema<TTables> = {
1540
+ name: this.#name,
1211
1541
  version,
1212
1542
  tables,
1213
1543
  operations,
@@ -1231,7 +1561,6 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1231
1561
  }
1232
1562
 
1233
1563
  clonedCol.name = col.name;
1234
- clonedCol.ormName = col.ormName;
1235
1564
  clonedCol.isNullable = col.isNullable;
1236
1565
  clonedCol.role = col.role;
1237
1566
  clonedCol.isHidden = col.isHidden;
@@ -1240,20 +1569,28 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1240
1569
  clonedColumns[colName] = clonedCol;
1241
1570
  }
1242
1571
 
1243
- cloneTables[k] = {
1572
+ const clonedTable = {
1244
1573
  ...v,
1245
1574
  columns: clonedColumns,
1246
- };
1575
+ } as AnyTable;
1576
+
1577
+ clonedTable["~standard"] = createTableStandardSchemaProps(clonedTable, validationClasses);
1578
+ clonedTable.validate = createTableValidator(clonedTable, validationClasses);
1579
+
1580
+ cloneTables[k] = clonedTable;
1247
1581
  }
1248
1582
 
1249
- return new SchemaBuilder<TTables>({
1583
+ const clonedSchema: Schema<TTables> = {
1584
+ name: this.#name,
1250
1585
  version,
1251
1586
  tables: cloneTables as TTables,
1252
1587
  operations: [...operations],
1253
1588
  clone: () => {
1254
1589
  throw new Error("Cannot clone during clone");
1255
1590
  },
1256
- }).build();
1591
+ };
1592
+
1593
+ return new SchemaBuilder<TTables>(this.#name, clonedSchema).build();
1257
1594
  },
1258
1595
  };
1259
1596
 
@@ -1272,19 +1609,18 @@ export class SchemaBuilder<TTables extends Record<string, AnyTable> = {}> {
1272
1609
  * Create a new schema with callback pattern.
1273
1610
  */
1274
1611
  export function schema<const TTables extends Record<string, AnyTable> = {}>(
1612
+ name: string,
1275
1613
  callback: (builder: SchemaBuilder<{}>) => SchemaBuilder<TTables>,
1276
1614
  ): Schema<TTables> {
1277
- return callback(new SchemaBuilder()).build();
1615
+ return callback(new SchemaBuilder(name)).build();
1278
1616
  }
1279
1617
 
1280
- export function compileForeignKey(key: ForeignKey, nameType: "sql" | "orm" = "orm") {
1618
+ export function compileForeignKey(key: ForeignKey) {
1281
1619
  return {
1282
1620
  name: key.name,
1283
- table: nameType === "sql" ? key.table.name : key.table.ormName,
1284
- referencedTable: nameType === "sql" ? key.referencedTable.name : key.referencedTable.ormName,
1285
- referencedColumns: key.referencedColumns.map((col) =>
1286
- nameType === "sql" ? col.name : col.ormName,
1287
- ),
1288
- columns: key.columns.map((col) => (nameType === "sql" ? col.name : col.ormName)),
1621
+ table: key.table.name,
1622
+ referencedTable: key.referencedTable.name,
1623
+ referencedColumns: key.referencedColumns.map((col) => col.name),
1624
+ columns: key.columns.map((col) => col.name),
1289
1625
  };
1290
1626
  }