@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
@@ -4,77 +4,93 @@ import {
4
4
  fragnoDatabaseAdapterNameFakeSymbol,
5
5
  fragnoDatabaseAdapterVersionFakeSymbol,
6
6
  } from "../adapters/adapters";
7
- import {
8
- internalFragmentDef,
9
- internalSchema,
10
- SETTINGS_NAMESPACE,
11
- getSchemaVersionFromDatabase,
12
- } from "../fragments/internal-fragment";
7
+ import { generateDrizzleSchema } from "../schema-output/drizzle";
8
+ import { generatePrismaSchema } from "../schema-output/prisma";
9
+ import { internalFragmentDef, getSchemaVersionFromDatabase } from "../fragments/internal-fragment";
10
+ import { internalSchema, SETTINGS_TABLE_NAME } from "../fragments/internal-fragment.schema";
13
11
  import { instantiate } from "@fragno-dev/core";
12
+ import { supportedDatabases, type SupportedDatabase } from "../adapters/generic-sql/driver-config";
14
13
 
15
14
  export interface GenerationEngineResult {
16
15
  schema: string;
17
16
  path: string;
18
- namespace: string;
17
+ namespace: string | null;
18
+ }
19
+
20
+ export type SchemaOutputFormat = "sql" | "drizzle" | "prisma";
21
+
22
+ export interface GenerateSchemaOptions {
23
+ format?: SchemaOutputFormat;
24
+ path?: string;
25
+ toVersion?: number;
26
+ fromVersion?: number;
19
27
  }
20
28
 
21
29
  export interface GenerationInternalResult {
22
30
  schema: string;
23
31
  path: string;
24
- namespace: string;
32
+ namespace: string | null;
33
+ namespaceKey: string;
34
+ schemaName: string;
35
+ isSettings: boolean;
25
36
  fromVersion: number;
26
37
  toVersion: number;
27
38
  }
28
39
 
29
40
  export interface ExecuteMigrationResult {
30
- namespace: string;
41
+ namespace: string | null;
31
42
  didMigrate: boolean;
32
43
  fromVersion: number;
33
44
  toVersion: number;
34
45
  }
35
46
 
36
- export async function generateMigrationsOrSchema<
47
+ const DEFAULT_DRIZZLE_PATH = "fragno-schema.ts";
48
+ const DEFAULT_PRISMA_PATH = "fragno.prisma";
49
+
50
+ const isSupportedDatabase = (value: string): value is SupportedDatabase =>
51
+ supportedDatabases.includes(value as SupportedDatabase);
52
+
53
+ export async function generateSchemaArtifacts<
37
54
  // oxlint-disable-next-line no-explicit-any
38
55
  const TDatabases extends FragnoDatabase<AnySchema, any>[],
39
- >(
40
- databases: TDatabases,
41
- options?: {
42
- path?: string;
43
- toVersion?: number;
44
- fromVersion?: number;
45
- },
46
- ): Promise<GenerationEngineResult[]> {
56
+ >(databases: TDatabases, options?: GenerateSchemaOptions): Promise<GenerationEngineResult[]> {
47
57
  if (databases.length === 0) {
48
58
  throw new Error("No databases provided for schema generation");
49
59
  }
50
60
 
51
61
  const firstDb = databases[0];
52
62
  const adapter = firstDb.adapter;
63
+ const format = options?.format ?? "sql";
53
64
 
54
- // If adapter has createSchemaGenerator, use it for combined generation (e.g., Drizzle)
55
- if (adapter.createSchemaGenerator) {
65
+ if (format !== "sql") {
56
66
  if (options?.toVersion !== undefined || options?.fromVersion !== undefined) {
57
- console.warn(
58
- "⚠️ Warning: --from and --to version options are not supported when generating schemas for multiple fragments and will be ignored.",
67
+ throw new Error("--from and --to are only supported when generating SQL migrations.");
68
+ }
69
+
70
+ const databaseType = adapter.adapterMetadata?.databaseType;
71
+ if (!databaseType || !isSupportedDatabase(databaseType)) {
72
+ throw new Error(
73
+ "Adapter does not expose databaseType metadata required for schema output generation.",
59
74
  );
60
75
  }
61
76
 
62
77
  // Collect all schemas, de-duplicating by namespace.
63
78
  // The internal fragment (settings schema) is always included first since all database
64
79
  // fragments automatically link to it via withDatabase().
65
- const fragmentsMap = new Map<string, { schema: AnySchema; namespace: string }>();
80
+ const fragmentsMap = new Map<string, { schema: AnySchema; namespace: string | null }>();
66
81
 
67
82
  // Include internal fragment first with empty namespace (settings table has no prefix)
68
- fragmentsMap.set("", {
83
+ fragmentsMap.set(internalSchema.name, {
69
84
  schema: internalSchema,
70
- namespace: "",
85
+ namespace: null,
71
86
  });
72
87
 
73
88
  // Add user fragments, de-duplicating by namespace
74
89
  // Each FragnoDatabase has a unique namespace, so this prevents duplicate schema generation
75
90
  for (const db of databases) {
76
- if (!fragmentsMap.has(db.namespace)) {
77
- fragmentsMap.set(db.namespace, {
91
+ const namespaceKey = db.namespace ?? db.schema.name;
92
+ if (!fragmentsMap.has(namespaceKey)) {
93
+ fragmentsMap.set(namespaceKey, {
78
94
  schema: db.schema,
79
95
  namespace: db.namespace,
80
96
  });
@@ -82,22 +98,30 @@ export async function generateMigrationsOrSchema<
82
98
  }
83
99
 
84
100
  const allFragments = Array.from(fragmentsMap.values());
85
- const generator = adapter.createSchemaGenerator(allFragments, {
86
- path: options?.path,
87
- });
101
+ const defaultPath = format === "drizzle" ? DEFAULT_DRIZZLE_PATH : DEFAULT_PRISMA_PATH;
102
+ const schema =
103
+ format === "drizzle"
104
+ ? generateDrizzleSchema(allFragments, databaseType, {
105
+ namingStrategy: adapter.namingStrategy,
106
+ })
107
+ : generatePrismaSchema(allFragments, databaseType, {
108
+ sqliteStorageMode: adapter.adapterMetadata?.sqliteStorageMode,
109
+ namingStrategy: adapter.namingStrategy,
110
+ });
88
111
 
89
112
  return [
90
113
  {
91
- ...generator.generateSchema(),
114
+ schema,
115
+ path: options?.path ?? defaultPath,
92
116
  namespace: firstDb.namespace,
93
117
  },
94
118
  ];
95
119
  }
96
120
 
97
- // Otherwise, use migration engine for individual generation (e.g., Kysely, GenericSQL)
121
+ // Otherwise, use migration engine for SQL migration generation.
98
122
  if (!adapter.prepareMigrations) {
99
123
  throw new Error(
100
- "Adapter does not support migration-based schema generation. Ensure your adapter implements prepareMigrations.",
124
+ "Adapter does not support migration generation. Ensure your adapter implements prepareMigrations.",
101
125
  );
102
126
  }
103
127
 
@@ -110,17 +134,14 @@ export async function generateMigrationsOrSchema<
110
134
  // Use the internal fragment for settings management
111
135
  const internalFragment = instantiate(internalFragmentDef)
112
136
  .withConfig({})
113
- .withOptions({ databaseAdapter: adapter })
137
+ .withOptions({ databaseAdapter: adapter, databaseNamespace: null })
114
138
  .build();
115
139
 
116
- const settingsSourceVersion = await getSchemaVersionFromDatabase(
117
- internalFragment,
118
- SETTINGS_NAMESPACE,
119
- );
140
+ const settingsSourceVersion = await getSchemaVersionFromDatabase(internalFragment, "");
120
141
 
121
142
  const generatedFiles: GenerationInternalResult[] = [];
122
143
 
123
- // Use empty namespace for settings (SETTINGS_NAMESPACE is for prefixing keys, not the database namespace)
144
+ // Internal fragment uses empty-string namespace: no table suffix, version key is ".schema_version"
124
145
  const settingsPreparedMigrations = adapter.prepareMigrations(internalSchema, "");
125
146
  const settingsTargetVersion = internalSchema.version;
126
147
 
@@ -134,7 +155,10 @@ export async function generateMigrationsOrSchema<
134
155
  generatedFiles.push({
135
156
  schema: settingsSql,
136
157
  path: "settings-migration.sql", // Placeholder, will be renamed in post-processing
137
- namespace: "", // Empty namespace for settings table
158
+ namespace: null,
159
+ namespaceKey: SETTINGS_TABLE_NAME,
160
+ schemaName: internalSchema.name,
161
+ isSettings: true,
138
162
  fromVersion: settingsSourceVersion,
139
163
  toVersion: settingsTargetVersion,
140
164
  });
@@ -147,8 +171,8 @@ export async function generateMigrationsOrSchema<
147
171
  // Use migration engine
148
172
  if (!dbAdapter.prepareMigrations) {
149
173
  throw new Error(
150
- `Adapter for ${db.namespace} does not support schema generation. ` +
151
- `Ensure your adapter implements either createSchemaGenerator or prepareMigrations.`,
174
+ `Adapter for ${db.namespace ?? db.schema.name} does not support migration generation. ` +
175
+ `Ensure your adapter implements prepareMigrations.`,
152
176
  );
153
177
  }
154
178
 
@@ -165,6 +189,9 @@ export async function generateMigrationsOrSchema<
165
189
  schema: sql,
166
190
  path: "schema.sql", // Placeholder, will be renamed in post-processing
167
191
  namespace: db.namespace,
192
+ namespaceKey: db.namespace ?? db.schema.name,
193
+ schemaName: db.schema.name,
194
+ isSettings: false,
168
195
  fromVersion: sourceVersion,
169
196
  toVersion: targetVersion,
170
197
  });
@@ -196,7 +223,7 @@ export async function executeMigrations<const TDatabases extends FragnoDatabase<
196
223
  if (!adapter.prepareMigrations) {
197
224
  throw new Error(
198
225
  "Adapter does not support running migrations. The adapter only supports schema generation.\n" +
199
- "Try using 'generateMigrationsOrSchema' instead to generate schema files.",
226
+ "Try using 'generateSchemaArtifacts' instead to generate schema files.",
200
227
  );
201
228
  }
202
229
 
@@ -224,7 +251,8 @@ export async function executeMigrations<const TDatabases extends FragnoDatabase<
224
251
 
225
252
  const results: ExecuteMigrationResult[] = [];
226
253
  const migrationsToExecute: Array<{
227
- namespace: string;
254
+ namespace: string | null;
255
+ namespaceKey: string;
228
256
  fromVersion: number;
229
257
  toVersion: number;
230
258
  execute: () => Promise<void>;
@@ -234,15 +262,12 @@ export async function executeMigrations<const TDatabases extends FragnoDatabase<
234
262
  // Use the internal fragment for settings management
235
263
  const internalFragment = instantiate(internalFragmentDef)
236
264
  .withConfig({})
237
- .withOptions({ databaseAdapter: adapter })
265
+ .withOptions({ databaseAdapter: adapter, databaseNamespace: null })
238
266
  .build();
239
267
 
240
- const settingsSourceVersion = await getSchemaVersionFromDatabase(
241
- internalFragment,
242
- SETTINGS_NAMESPACE,
243
- );
268
+ const settingsSourceVersion = await getSchemaVersionFromDatabase(internalFragment, "");
244
269
 
245
- // Use empty namespace for settings (SETTINGS_NAMESPACE is for prefixing keys, not the database namespace)
270
+ // Internal fragment uses empty-string namespace: no table suffix, version key is ".schema_version"
246
271
  const settingsPreparedMigrations = adapter.prepareMigrations(internalSchema, "");
247
272
  const settingsTargetVersion = internalSchema.version;
248
273
 
@@ -255,7 +280,8 @@ export async function executeMigrations<const TDatabases extends FragnoDatabase<
255
280
 
256
281
  if (compiledMigration.statements.length > 0) {
257
282
  migrationsToExecute.push({
258
- namespace: "", // Empty namespace for settings table
283
+ namespace: null,
284
+ namespaceKey: SETTINGS_TABLE_NAME,
259
285
  fromVersion: settingsSourceVersion,
260
286
  toVersion: settingsTargetVersion,
261
287
  execute: () =>
@@ -267,11 +293,15 @@ export async function executeMigrations<const TDatabases extends FragnoDatabase<
267
293
  }
268
294
 
269
295
  // 2. Prepare fragment migrations (sorted alphabetically)
270
- const sortedDatabases = [...databases].sort((a, b) => a.namespace.localeCompare(b.namespace));
296
+ const getNamespaceKey = (db: FragnoDatabase<AnySchema>) => db.namespace ?? db.schema.name;
297
+ const sortedDatabases = [...databases].sort((a, b) =>
298
+ getNamespaceKey(a).localeCompare(getNamespaceKey(b)),
299
+ );
271
300
 
272
301
  for (const fragnoDb of sortedDatabases) {
302
+ const namespaceKey = getNamespaceKey(fragnoDb);
273
303
  const preparedMigrations = adapter.prepareMigrations(fragnoDb.schema, fragnoDb.namespace);
274
- const currentVersion = await getSchemaVersionFromDatabase(internalFragment, fragnoDb.namespace);
304
+ const currentVersion = await getSchemaVersionFromDatabase(internalFragment, namespaceKey);
275
305
  const targetVersion = fragnoDb.schema.version;
276
306
 
277
307
  if (currentVersion < targetVersion) {
@@ -282,6 +312,7 @@ export async function executeMigrations<const TDatabases extends FragnoDatabase<
282
312
  if (compiledMigration.statements.length > 0) {
283
313
  migrationsToExecute.push({
284
314
  namespace: fragnoDb.namespace,
315
+ namespaceKey,
285
316
  fromVersion: currentVersion,
286
317
  toVersion: targetVersion,
287
318
  execute: () =>
@@ -294,6 +325,7 @@ export async function executeMigrations<const TDatabases extends FragnoDatabase<
294
325
  }
295
326
 
296
327
  // 3. Execute all migrations in order
328
+ const executedNamespaceKeys = new Set<string>();
297
329
  for (const migration of migrationsToExecute) {
298
330
  await migration.execute();
299
331
  results.push({
@@ -302,11 +334,13 @@ export async function executeMigrations<const TDatabases extends FragnoDatabase<
302
334
  fromVersion: migration.fromVersion,
303
335
  toVersion: migration.toVersion,
304
336
  });
337
+ executedNamespaceKeys.add(migration.namespaceKey);
305
338
  }
306
339
 
307
340
  // 4. Add skipped migrations (already up-to-date)
308
341
  for (const fragnoDb of databases) {
309
- if (!results.find((r) => r.namespace === fragnoDb.namespace)) {
342
+ const namespaceKey = getNamespaceKey(fragnoDb);
343
+ if (!executedNamespaceKeys.has(namespaceKey)) {
310
344
  results.push({
311
345
  namespace: fragnoDb.namespace,
312
346
  didMigrate: false,
@@ -322,7 +356,7 @@ export async function executeMigrations<const TDatabases extends FragnoDatabase<
322
356
  /**
323
357
  * Post-processes migration files to add ordering and standardize naming.
324
358
  *
325
- * Sorts files with settings namespace first, then alphabetically by namespace,
359
+ * Sorts files with settings namespace first, then alphabetically by namespace key,
326
360
  * and assigns ordering numbers. Transforms filenames to format:
327
361
  * `<date>_<n>_f<from>_t<to>_<namespace>.sql`
328
362
  *
@@ -336,16 +370,15 @@ export function postProcessMigrationFilenames(
336
370
  return [];
337
371
  }
338
372
 
339
- // Sort files: settings namespace first (empty string), then alphabetically by namespace
373
+ // Sort files: settings first, then alphabetically by namespace key
340
374
  const sortedFiles = [...files].sort((a, b) => {
341
- // Settings table has empty namespace - sort it first
342
- if (a.namespace === "") {
375
+ if (a.isSettings) {
343
376
  return -1;
344
377
  }
345
- if (b.namespace === "") {
378
+ if (b.isSettings) {
346
379
  return 1;
347
380
  }
348
- return a.namespace.localeCompare(b.namespace);
381
+ return a.namespaceKey.localeCompare(b.namespaceKey);
349
382
  });
350
383
 
351
384
  // Generate date prefix for filenames
@@ -361,10 +394,7 @@ export function postProcessMigrationFilenames(
361
394
  const fromPadded = fromVersion.toString().padStart(3, "0");
362
395
  const toPadded = toVersion.toString().padStart(3, "0");
363
396
 
364
- // For settings table (empty namespace), use "fragno_db_settings" in the filename
365
- // For other tables, use their namespace
366
- const safeName =
367
- file.namespace === "" ? "fragno_db_settings" : file.namespace.replace(/[^a-z0-9-]/gi, "_");
397
+ const safeName = file.namespaceKey.replace(/[^a-z0-9-]/gi, "_");
368
398
  const newPath = `${date}_${orderNum}_f${fromPadded}_t${toPadded}_${safeName}.sql`;
369
399
 
370
400
  return {
@@ -54,6 +54,7 @@ export type MigrationOperation<
54
54
  type: "drop-foreign-key";
55
55
  table: string;
56
56
  name: string;
57
+ referencedTable: string;
57
58
  } & { metadata?: TMeta })
58
59
  | ({
59
60
  type: "drop-index";
package/src/mod.ts CHANGED
@@ -2,6 +2,7 @@ import type { DatabaseAdapter } from "./adapters/adapters";
2
2
  import type { AnySchema } from "./schema/create";
3
3
  import type { CursorResult } from "./query/cursor";
4
4
  import { Cursor } from "./query/cursor";
5
+ import { dbNow, type DbNow } from "./query/db-now";
5
6
  import type { FragnoInstantiatedFragment, AnyFragnoInstantiatedFragment } from "@fragno-dev/core";
6
7
  import type {
7
8
  FragnoPublicConfigWithDatabase,
@@ -11,15 +12,20 @@ import {
11
12
  getSchemaVersionFromDatabase,
12
13
  type InternalFragmentInstance,
13
14
  } from "./fragments/internal-fragment";
15
+ import { resolveDatabaseAdapter } from "./util/default-database-adapter";
14
16
 
15
17
  export type { DatabaseAdapter, CursorResult };
16
18
  export { Cursor };
19
+ export { dbNow };
20
+ export type { DbNow };
21
+ export { InMemoryAdapter, type InMemoryAdapterOptions } from "./adapters/in-memory";
22
+ export { internalSchema } from "./fragments/internal-fragment";
17
23
 
18
24
  export const fragnoDatabaseFakeSymbol = "$fragno-database" as const;
19
25
  export const fragnoDatabaseLibraryVersion = "0.1" as const;
20
26
 
21
27
  export interface CreateFragnoDatabaseDefinitionOptions<T extends AnySchema> {
22
- namespace: string;
28
+ namespace: string | null;
23
29
  schema: T;
24
30
  }
25
31
 
@@ -43,11 +49,15 @@ export function isFragnoDatabase(value: unknown): value is FragnoDatabase<AnySch
43
49
  * Created from a FragnoDatabaseDefinition by calling .create(adapter).
44
50
  */
45
51
  export class FragnoDatabase<const T extends AnySchema, TUOWConfig = void> {
46
- #namespace: string;
52
+ #namespace: string | null;
47
53
  #schema: T;
48
54
  #adapter: DatabaseAdapter<TUOWConfig>;
49
55
 
50
- constructor(options: { namespace: string; schema: T; adapter: DatabaseAdapter<TUOWConfig> }) {
56
+ constructor(options: {
57
+ namespace: string | null;
58
+ schema: T;
59
+ adapter: DatabaseAdapter<TUOWConfig>;
60
+ }) {
51
61
  this.#namespace = options.namespace;
52
62
  this.#schema = options.schema;
53
63
  this.#adapter = options.adapter;
@@ -74,6 +84,7 @@ export {
74
84
  DatabaseFragmentDefinitionBuilder,
75
85
  type FragnoPublicConfigWithDatabase,
76
86
  type DatabaseFragmentContext,
87
+ type DatabaseServiceContext,
77
88
  type DatabaseHandlerContext as DatabaseRequestContext,
78
89
  type ImplicitDatabaseDependencies,
79
90
  } from "./db-fragment-definition-builder";
@@ -121,25 +132,47 @@ export type { BoundServices } from "@fragno-dev/core";
121
132
 
122
133
  export { internalFragmentDef } from "./fragments/internal-fragment";
123
134
  export type { InternalFragmentInstance } from "./fragments/internal-fragment";
124
-
125
- export type { HookContext, HooksMap, HookFn, HookPayload, TriggerHookOptions } from "./hooks/hooks";
126
-
127
- export type AnyFragnoInstantiatedDatabaseFragment = FragnoInstantiatedFragment<
128
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
129
- any,
130
- ImplicitDatabaseDependencies<AnySchema>,
131
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
132
- any,
133
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
134
- any,
135
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
136
- any,
137
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
138
- any,
139
- FragnoPublicConfigWithDatabase,
140
- // Ensure the fragment has the internal fragment linked
141
- { _fragno_internal: InternalFragmentInstance } & Record<string, AnyFragnoInstantiatedFragment>
142
- >;
135
+ export type {
136
+ OutboxConfig,
137
+ OutboxEntry,
138
+ OutboxPayload,
139
+ OutboxMutation,
140
+ OutboxRefMap,
141
+ } from "./outbox/outbox";
142
+
143
+ export type {
144
+ HookContext,
145
+ HooksMap,
146
+ HookFn,
147
+ HookPayload,
148
+ TriggerHookOptions,
149
+ DurableHooksProcessingOptions,
150
+ StuckHookProcessingInfo,
151
+ StuckHookProcessingEvent,
152
+ StuckHookProcessingTimeoutMinutes,
153
+ } from "./hooks/hooks";
154
+ export {
155
+ createDurableHooksProcessor,
156
+ type DurableHooksProcessor,
157
+ } from "./hooks/durable-hooks-processor";
158
+
159
+ export type AnyFragnoInstantiatedDatabaseFragment<TSchema extends AnySchema = AnySchema> =
160
+ FragnoInstantiatedFragment<
161
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
162
+ any,
163
+ ImplicitDatabaseDependencies<TSchema>,
164
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
165
+ any,
166
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
167
+ any,
168
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
169
+ any,
170
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
171
+ any,
172
+ FragnoPublicConfigWithDatabase,
173
+ // Ensure the fragment has the internal fragment linked
174
+ { _fragno_internal: InternalFragmentInstance } & Record<string, AnyFragnoInstantiatedFragment>
175
+ >;
143
176
 
144
177
  /**
145
178
  * Helper function to run migrations for a database fragment.
@@ -163,9 +196,11 @@ export type AnyFragnoInstantiatedDatabaseFragment = FragnoInstantiatedFragment<
163
196
  * await migrate(fragment);
164
197
  * ```
165
198
  */
166
- export async function migrate(fragment: AnyFragnoInstantiatedDatabaseFragment): Promise<void> {
199
+ export async function migrate<TSchema extends AnySchema>(
200
+ fragment: AnyFragnoInstantiatedDatabaseFragment<TSchema>,
201
+ ): Promise<void> {
167
202
  const { options, deps, linkedFragments } = fragment.$internal;
168
- const adapter = options.databaseAdapter;
203
+ const adapter = resolveDatabaseAdapter(options, deps.schema);
169
204
 
170
205
  // Check if adapter supports prepareMigrations
171
206
  if (!adapter.prepareMigrations) {
@@ -175,7 +210,7 @@ export async function migrate(fragment: AnyFragnoInstantiatedDatabaseFragment):
175
210
  }
176
211
 
177
212
  const schema = deps.schema;
178
- const namespace = deps.namespace;
213
+ const namespace = deps.namespace ?? schema.name;
179
214
 
180
215
  // Step 1: Ensure the internal fragment (settings table) is migrated first
181
216
  const internalFragment = linkedFragments._fragno_internal;
@@ -192,7 +227,10 @@ export async function migrate(fragment: AnyFragnoInstantiatedDatabaseFragment):
192
227
 
193
228
  const internalDeps = internalFragment.$internal.deps;
194
229
  const internalSchema = internalDeps.schema;
195
- const internalNamespace = internalDeps.namespace;
230
+ // Internal fragment uses databaseNamespace: null (no table suffix).
231
+ // Version tracking uses empty string so the key is ".schema_version",
232
+ // which matches both the legacy format and how the internal fragment was designed.
233
+ const internalNamespace = internalDeps.namespace ?? "";
196
234
 
197
235
  const internalCurrentVersion = await getSchemaVersionFromDatabase(
198
236
  internalFragment,