@fragno-dev/db 0.2.1 → 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 (362) hide show
  1. package/.turbo/turbo-build.log +206 -140
  2. package/CHANGELOG.md +67 -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 +38 -28
  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 +45 -96
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  81. package/dist/db-fragment-definition-builder.js +121 -99
  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 +172 -9
  92. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  93. package/dist/fragments/internal-fragment.js +193 -74
  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 +47 -4
  106. package/dist/hooks/hooks.d.ts.map +1 -1
  107. package/dist/hooks/hooks.js +106 -39
  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 +17 -10
  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 +351 -100
  165. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  166. package/dist/query/unit-of-work/execute-unit-of-work.js +440 -267
  167. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  168. package/dist/query/unit-of-work/unit-of-work.d.ts +67 -22
  169. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  170. package/dist/query/unit-of-work/unit-of-work.js +110 -13
  171. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  172. package/dist/query/value-decoding.js +8 -5
  173. package/dist/query/value-decoding.js.map +1 -1
  174. package/dist/query/value-encoding.js +29 -9
  175. package/dist/query/value-encoding.js.map +1 -1
  176. package/dist/schema/create.d.ts +40 -14
  177. package/dist/schema/create.d.ts.map +1 -1
  178. package/dist/schema/create.js +82 -42
  179. package/dist/schema/create.js.map +1 -1
  180. package/dist/schema/generate-id.d.ts +20 -0
  181. package/dist/schema/generate-id.d.ts.map +1 -0
  182. package/dist/schema/generate-id.js +28 -0
  183. package/dist/schema/generate-id.js.map +1 -0
  184. package/dist/schema/type-conversion/create-sql-type-mapper.js +3 -2
  185. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  186. package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
  187. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  188. package/dist/schema/validator.d.ts +10 -0
  189. package/dist/schema/validator.d.ts.map +1 -0
  190. package/dist/schema/validator.js +123 -0
  191. package/dist/schema/validator.js.map +1 -0
  192. package/dist/schema-output/drizzle.d.ts +30 -0
  193. package/dist/schema-output/drizzle.d.ts.map +1 -0
  194. package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +82 -56
  195. package/dist/schema-output/drizzle.js.map +1 -0
  196. package/dist/schema-output/prisma.d.ts +17 -0
  197. package/dist/schema-output/prisma.d.ts.map +1 -0
  198. package/dist/schema-output/prisma.js +296 -0
  199. package/dist/schema-output/prisma.js.map +1 -0
  200. package/dist/util/default-database-adapter.js +61 -0
  201. package/dist/util/default-database-adapter.js.map +1 -0
  202. package/dist/with-database.d.ts +1 -1
  203. package/dist/with-database.d.ts.map +1 -1
  204. package/dist/with-database.js +12 -3
  205. package/dist/with-database.js.map +1 -1
  206. package/package.json +43 -28
  207. package/src/adapters/adapters.ts +30 -24
  208. package/src/adapters/drizzle/migrate-drizzle.test.ts +54 -33
  209. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +599 -0
  210. package/src/adapters/drizzle/test-utils.ts +12 -8
  211. package/src/adapters/generic-sql/driver-config.ts +38 -0
  212. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -5
  213. package/src/adapters/generic-sql/generic-sql-adapter.ts +110 -24
  214. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +54 -0
  215. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +231 -3
  216. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +118 -0
  217. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +26 -8
  218. package/src/adapters/generic-sql/migration/dialect/mysql.ts +46 -8
  219. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +25 -7
  220. package/src/adapters/generic-sql/migration/dialect/postgres.ts +8 -4
  221. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +47 -8
  222. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +27 -12
  223. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +128 -39
  224. package/src/adapters/generic-sql/migration/prepared-migrations.ts +15 -8
  225. package/src/adapters/generic-sql/migration/sql-generator.ts +142 -65
  226. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +9 -6
  227. package/src/adapters/generic-sql/query/cursor-utils.test.ts +271 -0
  228. package/src/adapters/generic-sql/query/cursor-utils.ts +41 -6
  229. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +27 -27
  230. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +38 -24
  231. package/src/adapters/generic-sql/query/select-builder.test.ts +15 -11
  232. package/src/adapters/generic-sql/query/select-builder.ts +6 -2
  233. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +52 -2
  234. package/src/adapters/generic-sql/query/sql-query-compiler.ts +50 -15
  235. package/src/adapters/generic-sql/query/where-builder.test.ts +91 -17
  236. package/src/adapters/generic-sql/query/where-builder.ts +90 -38
  237. package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +6 -6
  238. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +806 -0
  239. package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +11 -11
  240. package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +49 -35
  241. package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +48 -32
  242. package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +6 -6
  243. package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
  244. package/src/adapters/generic-sql/uow-decoder.test.ts +1 -1
  245. package/src/adapters/generic-sql/uow-decoder.ts +21 -3
  246. package/src/adapters/generic-sql/uow-encoder.test.ts +33 -2
  247. package/src/adapters/generic-sql/uow-encoder.ts +50 -11
  248. package/src/adapters/in-memory/condition-evaluator.test.ts +193 -0
  249. package/src/adapters/in-memory/condition-evaluator.ts +275 -0
  250. package/src/adapters/in-memory/errors.ts +20 -0
  251. package/src/adapters/in-memory/in-memory-adapter.ts +277 -0
  252. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +296 -0
  253. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +100 -0
  254. package/src/adapters/in-memory/in-memory-uow.ts +1348 -0
  255. package/src/adapters/in-memory/index.ts +3 -0
  256. package/src/adapters/in-memory/options.test.ts +41 -0
  257. package/src/adapters/in-memory/options.ts +87 -0
  258. package/src/adapters/in-memory/reference-resolution.test.ts +50 -0
  259. package/src/adapters/in-memory/reference-resolution.ts +67 -0
  260. package/src/adapters/in-memory/sorted-array-index.test.ts +123 -0
  261. package/src/adapters/in-memory/sorted-array-index.ts +228 -0
  262. package/src/adapters/in-memory/store.test.ts +68 -0
  263. package/src/adapters/in-memory/store.ts +145 -0
  264. package/src/adapters/in-memory/value-comparison.ts +53 -0
  265. package/src/adapters/in-memory/value-normalization.test.ts +57 -0
  266. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1163 -0
  267. package/src/adapters/shared/from-unit-of-work-compiler.ts +3 -1
  268. package/src/adapters/shared/uow-operation-compiler.ts +26 -16
  269. package/src/adapters/sql/index.ts +12 -0
  270. package/src/db-fragment-definition-builder.test.ts +88 -54
  271. package/src/db-fragment-definition-builder.ts +201 -322
  272. package/src/db-fragment-instantiator.test.ts +169 -101
  273. package/src/db-fragment-integration.test.ts +301 -149
  274. package/src/dispatchers/cloudflare-do/index.test.ts +73 -0
  275. package/src/dispatchers/cloudflare-do/index.ts +104 -0
  276. package/src/dispatchers/node/index.test.ts +91 -0
  277. package/src/dispatchers/node/index.ts +87 -0
  278. package/src/fragments/internal-fragment.routes.ts +42 -0
  279. package/src/fragments/internal-fragment.schema.ts +51 -0
  280. package/src/fragments/internal-fragment.test.ts +730 -274
  281. package/src/fragments/internal-fragment.ts +447 -154
  282. package/src/hooks/durable-hooks-processor.test.ts +117 -0
  283. package/src/hooks/durable-hooks-processor.ts +67 -0
  284. package/src/hooks/hooks.test.ts +411 -259
  285. package/src/hooks/hooks.ts +265 -66
  286. package/src/migration-engine/auto-from-schema.test.ts +14 -14
  287. package/src/migration-engine/auto-from-schema.ts +5 -2
  288. package/src/migration-engine/create.test.ts +2 -2
  289. package/src/migration-engine/generation-engine.test.ts +229 -104
  290. package/src/migration-engine/generation-engine.ts +94 -64
  291. package/src/migration-engine/shared.ts +1 -0
  292. package/src/mod.ts +78 -30
  293. package/src/naming/sql-naming.ts +180 -0
  294. package/src/outbox/outbox-builder.ts +241 -0
  295. package/src/outbox/outbox.test.ts +253 -0
  296. package/src/outbox/outbox.ts +137 -0
  297. package/src/query/column-defaults.ts +41 -3
  298. package/src/query/condition-builder.test.ts +3 -3
  299. package/src/query/cursor.test.ts +116 -18
  300. package/src/query/cursor.ts +75 -26
  301. package/src/query/db-now.ts +6 -0
  302. package/src/query/query-type.test.ts +2 -2
  303. package/src/query/serialize/create-sql-serializer.ts +7 -2
  304. package/src/query/serialize/dialect/mysql-serializer.ts +12 -4
  305. package/src/query/serialize/dialect/postgres-serializer.ts +34 -4
  306. package/src/query/serialize/dialect/sqlite-serializer.test.ts +51 -1
  307. package/src/query/serialize/dialect/sqlite-serializer.ts +92 -9
  308. package/src/query/serialize/sql-serializer.ts +4 -4
  309. package/src/query/simple-query-interface.ts +5 -0
  310. package/src/query/unit-of-work/execute-unit-of-work.test.ts +1512 -1458
  311. package/src/query/unit-of-work/execute-unit-of-work.ts +1708 -596
  312. package/src/query/unit-of-work/tx-builder.test.ts +1041 -0
  313. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +32 -32
  314. package/src/query/unit-of-work/unit-of-work-types.test.ts +1 -1
  315. package/src/query/unit-of-work/unit-of-work.test.ts +231 -36
  316. package/src/query/unit-of-work/unit-of-work.ts +229 -31
  317. package/src/query/value-decoding.test.ts +13 -2
  318. package/src/query/value-decoding.ts +17 -4
  319. package/src/query/value-encoding.test.ts +85 -2
  320. package/src/query/value-encoding.ts +56 -6
  321. package/src/schema/create.test.ts +129 -42
  322. package/src/schema/create.ts +187 -47
  323. package/src/schema/generate-id.test.ts +57 -0
  324. package/src/schema/generate-id.ts +38 -0
  325. package/src/schema/serialize.test.ts +14 -2
  326. package/src/schema/type-conversion/create-sql-type-mapper.ts +7 -2
  327. package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
  328. package/src/schema/type-conversion/type-mapping.test.ts +25 -1
  329. package/src/schema/validator.test.ts +197 -0
  330. package/src/schema/validator.ts +231 -0
  331. package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +179 -129
  332. package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +143 -93
  333. package/src/schema-output/prisma.test.ts +536 -0
  334. package/src/schema-output/prisma.ts +573 -0
  335. package/src/util/default-database-adapter.ts +106 -0
  336. package/src/with-database.ts +22 -3
  337. package/tsdown.config.ts +6 -4
  338. package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
  339. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
  340. package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
  341. package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
  342. package/dist/adapters/drizzle/generate.d.ts +0 -30
  343. package/dist/adapters/drizzle/generate.d.ts.map +0 -1
  344. package/dist/adapters/drizzle/generate.js.map +0 -1
  345. package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
  346. package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
  347. package/dist/adapters/kysely/kysely-adapter.js +0 -17
  348. package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
  349. package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
  350. package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
  351. package/dist/adapters/shared/table-name-mapper.js +0 -43
  352. package/dist/adapters/shared/table-name-mapper.js.map +0 -1
  353. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
  354. package/dist/schema-generator/schema-generator.d.ts +0 -15
  355. package/dist/schema-generator/schema-generator.d.ts.map +0 -1
  356. package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
  357. package/src/adapters/kysely/kysely-adapter.ts +0 -27
  358. package/src/adapters/shared/table-name-mapper.ts +0 -50
  359. package/src/schema-generator/schema-generator.ts +0 -12
  360. package/src/shared/config.ts +0 -10
  361. package/src/shared/connection-pool.ts +0 -24
  362. package/src/shared/prisma.ts +0 -45
@@ -0,0 +1,296 @@
1
+ import { sqliteStorageDefault, sqliteStoragePrisma } from "../adapters/generic-sql/sqlite-storage.js";
2
+ import { createNamingResolver, sanitizeNamespace } from "../naming/sql-naming.js";
3
+ import { defaultNamingStrategyForDatabase } from "../adapters/generic-sql/driver-config.js";
4
+ import { parseVarchar } from "../util/parse.js";
5
+
6
+ //#region src/schema-output/prisma.ts
7
+ const VALID_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
8
+ function isValidIdentifier(name) {
9
+ return VALID_IDENTIFIER.test(name);
10
+ }
11
+ function sanitizeIdentifier(name) {
12
+ const sanitized = name.replace(/[^A-Za-z0-9_]/g, "_");
13
+ if (sanitized.length === 0) return "_";
14
+ if (/^[0-9]/.test(sanitized)) return `_${sanitized}`;
15
+ return sanitized;
16
+ }
17
+ function ensureUniqueName(base, used) {
18
+ if (!used.has(base)) return base;
19
+ let index = 1;
20
+ let candidate = `${base}_${index}`;
21
+ while (used.has(candidate)) {
22
+ index += 1;
23
+ candidate = `${base}_${index}`;
24
+ }
25
+ return candidate;
26
+ }
27
+ function toPascalCase(value) {
28
+ return value.split(/[_-]+/).filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join("");
29
+ }
30
+ function isVarcharType(value) {
31
+ return value.startsWith("varchar(");
32
+ }
33
+ function getModelName(table, namespace) {
34
+ const base = toPascalCase(table.name);
35
+ if (!namespace) return base;
36
+ return `${base}_${sanitizeNamespace(namespace)}`;
37
+ }
38
+ function getPhysicalTableName(table, resolver) {
39
+ return resolver ? resolver.getTableName(table.name) : table.name;
40
+ }
41
+ function getRelationName(namespace, from, referenceName, to) {
42
+ if (!namespace) return `${from}_${referenceName}_${to}`;
43
+ return `${namespace}_${from}_${referenceName}_${to}`;
44
+ }
45
+ function getForeignKeyMapName(table, relation, _namespace, resolver) {
46
+ if (resolver) return resolver.getForeignKeyName({
47
+ logicalTable: table.name,
48
+ logicalReferencedTable: relation.table.name,
49
+ referenceName: relation.name
50
+ });
51
+ return `${table.name}_${relation.table.name}_${relation.name}_fk`;
52
+ }
53
+ function getIndexMapName(indexName, tableName, namespace, resolver, unique) {
54
+ if (!resolver) return namespace ? `${indexName}_${namespace}` : indexName;
55
+ return unique ? resolver.getUniqueIndexName(indexName, tableName) : resolver.getIndexName(indexName, tableName);
56
+ }
57
+ function getPrismaScalarType(column, provider, sqliteStorageMode) {
58
+ const internalIdType = provider === "sqlite" ? "Int" : "BigInt";
59
+ if (column.role === "internal-id") return { type: internalIdType };
60
+ if (column.role === "reference") return { type: internalIdType };
61
+ if (isVarcharType(column.type)) {
62
+ const length = parseVarchar(column.type);
63
+ if (provider === "postgresql" || provider === "mysql") return {
64
+ type: "String",
65
+ nativeType: `@db.VarChar(${length})`
66
+ };
67
+ return { type: "String" };
68
+ }
69
+ switch (column.type) {
70
+ case "string": return { type: "String" };
71
+ case "integer": return { type: "Int" };
72
+ case "bigint":
73
+ if (provider === "sqlite" && sqliteStorageMode.bigintStorage === "blob") return { type: "Bytes" };
74
+ return { type: "BigInt" };
75
+ case "bool": return { type: "Boolean" };
76
+ case "decimal":
77
+ if (provider === "sqlite") return { type: "Float" };
78
+ return { type: "Decimal" };
79
+ case "binary": return { type: "Bytes" };
80
+ case "json":
81
+ if (provider === "postgresql") return {
82
+ type: "Json",
83
+ nativeType: "@db.Json"
84
+ };
85
+ return { type: "Json" };
86
+ case "timestamp":
87
+ if (provider === "sqlite" && sqliteStorageMode.timestampStorage === "epoch-ms") return { type: "Int" };
88
+ return { type: "DateTime" };
89
+ case "date":
90
+ if (provider === "sqlite" && sqliteStorageMode.dateStorage === "epoch-ms") return { type: "Int" };
91
+ if (provider === "postgresql" || provider === "mysql") return {
92
+ type: "DateTime",
93
+ nativeType: "@db.Date"
94
+ };
95
+ return { type: "DateTime" };
96
+ default: {
97
+ const exhaustiveCheck = column.type;
98
+ throw new Error(`Unsupported column type: ${exhaustiveCheck}`);
99
+ }
100
+ }
101
+ }
102
+ function formatDefaultValue(value) {
103
+ if (value instanceof Date) return JSON.stringify(value.toISOString());
104
+ if (typeof value === "bigint") return value.toString();
105
+ return JSON.stringify(value);
106
+ }
107
+ function getColumnDefault(column, provider, sqliteStorageMode) {
108
+ if (!column.default) return;
109
+ if ("value" in column.default) return `@default(${formatDefaultValue(column.default.value)})`;
110
+ if ("dbSpecial" in column.default && column.default.dbSpecial === "now") {
111
+ if (getPrismaScalarType(column, provider, sqliteStorageMode).type === "DateTime") return "@default(now())";
112
+ if (provider === "sqlite") {
113
+ if ((column.type === "date" ? sqliteStorageMode.dateStorage : sqliteStorageMode.timestampStorage) === "epoch-ms") return `@default(dbgenerated("CURRENT_TIMESTAMP"))`;
114
+ }
115
+ }
116
+ }
117
+ function getColumnFieldName(columnName, usedNames) {
118
+ const fieldName = ensureUniqueName(isValidIdentifier(columnName) ? columnName : sanitizeIdentifier(columnName), usedNames);
119
+ return {
120
+ fieldName,
121
+ needsMap: fieldName !== columnName
122
+ };
123
+ }
124
+ function getRelationFieldName(baseName, usedNames) {
125
+ return ensureUniqueName(isValidIdentifier(baseName) ? baseName : sanitizeIdentifier(baseName), usedNames);
126
+ }
127
+ function isRelationOptional(relation, columnFieldNames) {
128
+ for (const [localColumn] of relation.on) if (columnFieldNames.get(localColumn)?.isNullable) return true;
129
+ return false;
130
+ }
131
+ function getColumnFieldMappings(table) {
132
+ const fieldNameByColumn = /* @__PURE__ */ new Map();
133
+ const columnByName = /* @__PURE__ */ new Map();
134
+ const usedNames = /* @__PURE__ */ new Set();
135
+ for (const column of Object.values(table.columns)) {
136
+ const { fieldName } = getColumnFieldName(column.name, usedNames);
137
+ usedNames.add(fieldName);
138
+ fieldNameByColumn.set(column.name, fieldName);
139
+ columnByName.set(column.name, column);
140
+ }
141
+ return {
142
+ fieldNameByColumn,
143
+ columnByName
144
+ };
145
+ }
146
+ function areInverseRelations(one, many) {
147
+ if (one.type !== "one" || many.type !== "many") return false;
148
+ if (one.referencer !== many.table || one.table !== many.referencer) return false;
149
+ return one.on.every(([left, right]) => many.on.some(([manyLeft, manyRight]) => manyLeft === right && manyRight === left));
150
+ }
151
+ function findMatchingManyRelation(one) {
152
+ for (const relation of Object.values(one.table.relations)) {
153
+ if (relation.type !== "many") continue;
154
+ if (areInverseRelations(one, relation)) return relation;
155
+ }
156
+ }
157
+ function findMatchingOneRelation(many) {
158
+ for (const relation of Object.values(many.table.relations)) {
159
+ if (relation.type !== "one") continue;
160
+ if (areInverseRelations(relation, many)) return relation;
161
+ }
162
+ }
163
+ function generateColumnFields(table, provider, sqliteStorageMode, fieldNameByColumn, resolver) {
164
+ const lines = [];
165
+ for (const column of Object.values(table.columns)) {
166
+ const fieldName = fieldNameByColumn.get(column.name);
167
+ const scalar = getPrismaScalarType(column, provider, sqliteStorageMode);
168
+ const isOptional = column.isNullable;
169
+ const attributes = [];
170
+ if (column.role === "internal-id") attributes.push("@id", "@default(autoincrement())");
171
+ if (column.role === "external-id") attributes.push("@unique", "@default(cuid())");
172
+ const defaultValue = getColumnDefault(column, provider, sqliteStorageMode);
173
+ if (defaultValue) attributes.push(defaultValue);
174
+ if (scalar.nativeType) attributes.push(scalar.nativeType);
175
+ const physicalName = resolver ? resolver.getColumnName(table.name, column.name) : column.name;
176
+ if (fieldName !== physicalName) attributes.push(`@map("${physicalName}")`);
177
+ const suffix = isOptional ? "?" : "";
178
+ const attrSuffix = attributes.length > 0 ? ` ${attributes.join(" ")}` : "";
179
+ lines.push(` ${fieldName} ${scalar.type}${suffix}${attrSuffix}`);
180
+ }
181
+ return lines;
182
+ }
183
+ function generateRelationFields(table, namespace, fieldNameByColumn, columnByName, fieldNameByTableColumn, resolver) {
184
+ const lines = [];
185
+ const usedNames = new Set(fieldNameByColumn.values());
186
+ const relations = Object.values(table.relations).slice().sort((a, b) => a.name.localeCompare(b.name));
187
+ for (const relation of relations) {
188
+ if (relation.type !== "one") continue;
189
+ const fieldName = getRelationFieldName(relation.name, usedNames);
190
+ usedNames.add(fieldName);
191
+ const relationName = getRelationName(namespace, table.name, relation.name, relation.table.name);
192
+ const relatedModel = getModelName(relation.table, namespace);
193
+ const localFields = relation.on.map(([left]) => fieldNameByColumn.get(left) ?? left);
194
+ const referenceFields = relation.on.map(([, right]) => {
195
+ const actualRight = right === "id" ? "_internalId" : right;
196
+ return fieldNameByTableColumn.get(relation.table)?.get(actualRight) ?? actualRight;
197
+ });
198
+ const fkMapName = getForeignKeyMapName(table, relation, namespace, resolver);
199
+ const relationParts = [
200
+ `"${relationName}"`,
201
+ `fields: [${localFields.join(", ")}]`,
202
+ `references: [${referenceFields.join(", ")}]`,
203
+ `map: "${fkMapName}"`
204
+ ];
205
+ const suffix = isRelationOptional(relation, columnByName) ? "?" : "";
206
+ lines.push(` ${fieldName} ${relatedModel}${suffix} @relation(${relationParts.join(", ")})`);
207
+ }
208
+ for (const relation of relations) {
209
+ if (relation.type !== "many") continue;
210
+ const matchingOne = findMatchingOneRelation(relation);
211
+ const relationName = matchingOne ? getRelationName(namespace, matchingOne.referencer.name, matchingOne.name, matchingOne.table.name) : getRelationName(namespace, relation.referencer.name, relation.name, relation.table.name);
212
+ const fieldName = getRelationFieldName(relation.name, usedNames);
213
+ usedNames.add(fieldName);
214
+ const relatedModel = getModelName(relation.table, namespace);
215
+ lines.push(` ${fieldName} ${relatedModel}[] @relation("${relationName}")`);
216
+ }
217
+ const inverseCandidates = [];
218
+ for (const sourceTable of fieldNameByTableColumn.keys()) for (const rel of Object.values(sourceTable.relations)) if (rel.type === "one" && rel.table === table) inverseCandidates.push(rel);
219
+ for (const rel of inverseCandidates.sort((a, b) => a.name.localeCompare(b.name))) {
220
+ if (findMatchingManyRelation(rel)) continue;
221
+ const baseName = rel.referencer.name;
222
+ let fieldName = baseName;
223
+ if (usedNames.has(fieldName)) fieldName = `${baseName}_${rel.name}`;
224
+ fieldName = getRelationFieldName(fieldName, usedNames);
225
+ usedNames.add(fieldName);
226
+ const relationName = getRelationName(namespace, rel.referencer.name, rel.name, rel.table.name);
227
+ const relatedModel = getModelName(rel.referencer, namespace);
228
+ lines.push(` ${fieldName} ${relatedModel}[] @relation("${relationName}")`);
229
+ }
230
+ return lines;
231
+ }
232
+ function generateModel(table, namespace, provider, sqliteStorageMode, fieldNameByTableColumn, columnByTableName, resolver) {
233
+ const modelName = getModelName(table, namespace);
234
+ const physicalName = getPhysicalTableName(table, resolver);
235
+ const fieldNameByColumn = fieldNameByTableColumn.get(table);
236
+ const columnByName = columnByTableName.get(table);
237
+ const fieldLines = [...generateColumnFields(table, provider, sqliteStorageMode, fieldNameByColumn, resolver), ...generateRelationFields(table, namespace, fieldNameByColumn, columnByName, fieldNameByTableColumn, resolver)];
238
+ const indexLines = [];
239
+ const sortedIndexes = Object.values(table.indexes).slice().sort((a, b) => a.name.localeCompare(b.name));
240
+ for (const index of sortedIndexes) {
241
+ const fields = index.columnNames.map((name) => fieldNameByColumn.get(name) ?? name).join(", ");
242
+ const mapName = getIndexMapName(index.name, table.name, namespace, resolver, index.unique);
243
+ const directive = index.unique ? "@@unique" : "@@index";
244
+ indexLines.push(` ${directive}([${fields}], map: "${mapName}")`);
245
+ }
246
+ indexLines.push(` @@map("${physicalName}")`);
247
+ return [
248
+ `model ${modelName} {`,
249
+ ...fieldLines,
250
+ ...indexLines,
251
+ `}`
252
+ ].join("\n");
253
+ }
254
+ function generatePrismaSchema(fragments, provider, options) {
255
+ const sqliteStorageMode = options?.sqliteStorageMode ?? (provider === "sqlite" ? sqliteStoragePrisma : sqliteStorageDefault);
256
+ const namingStrategy = options?.namingStrategy ?? defaultNamingStrategyForDatabase(provider);
257
+ const sortedNamespaces = Array.from(new Set(fragments.map((fragment) => fragment.namespace))).sort((a, b) => {
258
+ const aKey = a ?? "";
259
+ const bKey = b ?? "";
260
+ if (aKey === "") return -1;
261
+ if (bKey === "") return 1;
262
+ return aKey.localeCompare(bKey);
263
+ });
264
+ const sortedFragments = sortedNamespaces.map((namespace) => fragments.find((fragment) => fragment.namespace === namespace)).filter((fragment) => !!fragment);
265
+ const fieldNameByTableColumn = /* @__PURE__ */ new Map();
266
+ const columnByTableName = /* @__PURE__ */ new Map();
267
+ for (const fragment of sortedFragments) for (const table of Object.values(fragment.schema.tables)) {
268
+ const mapping = getColumnFieldMappings(table);
269
+ fieldNameByTableColumn.set(table, mapping.fieldNameByColumn);
270
+ columnByTableName.set(table, mapping.columnByName);
271
+ }
272
+ const headerNamespaces = sortedNamespaces.filter(Boolean);
273
+ const headerSuffix = headerNamespaces.length > 0 ? headerNamespaces.join(", ") : "(internal)";
274
+ const lines = [
275
+ "// Generated by Fragno Prisma adapter.",
276
+ `// Provider: ${provider}`,
277
+ `// Namespaces: ${headerSuffix}`,
278
+ ""
279
+ ];
280
+ const models = [];
281
+ for (const fragment of sortedFragments) {
282
+ const resolver = createNamingResolver(fragment.schema, fragment.namespace, namingStrategy);
283
+ const tables = Object.values(fragment.schema.tables).slice().sort((a, b) => {
284
+ const aName = getPhysicalTableName(a, resolver);
285
+ const bName = getPhysicalTableName(b, resolver);
286
+ return aName.localeCompare(bName);
287
+ });
288
+ for (const table of tables) models.push(generateModel(table, fragment.namespace, provider, sqliteStorageMode, fieldNameByTableColumn, columnByTableName, resolver));
289
+ }
290
+ lines.push(models.join("\n\n"));
291
+ return lines.join("\n");
292
+ }
293
+
294
+ //#endregion
295
+ export { generatePrismaSchema };
296
+ //# sourceMappingURL=prisma.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prisma.js","names":["exhaustiveCheck: never","lines: string[]","attributes: string[]","inverseCandidates: Relation[]","indexLines: string[]","models: string[]"],"sources":["../../src/schema-output/prisma.ts"],"sourcesContent":["import { parseVarchar } from \"../util/parse\";\nimport type { AnyColumn, AnySchema, AnyTable, Relation } from \"../schema/create\";\nimport {\n defaultNamingStrategyForDatabase,\n type SupportedDatabase,\n} from \"../adapters/generic-sql/driver-config\";\nimport type { SQLiteStorageMode } from \"../adapters/generic-sql/sqlite-storage\";\nimport { sqliteStorageDefault, sqliteStoragePrisma } from \"../adapters/generic-sql/sqlite-storage\";\nimport {\n sanitizeNamespace,\n createNamingResolver,\n type NamingResolver,\n type SqlNamingStrategy,\n} from \"../naming/sql-naming\";\n\nexport interface GeneratePrismaSchemaOptions {\n sqliteStorageMode?: SQLiteStorageMode;\n namingStrategy?: SqlNamingStrategy;\n}\n\nconst VALID_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nfunction isValidIdentifier(name: string): boolean {\n return VALID_IDENTIFIER.test(name);\n}\n\nfunction sanitizeIdentifier(name: string): string {\n const sanitized = name.replace(/[^A-Za-z0-9_]/g, \"_\");\n if (sanitized.length === 0) {\n return \"_\";\n }\n if (/^[0-9]/.test(sanitized)) {\n return `_${sanitized}`;\n }\n return sanitized;\n}\n\nfunction ensureUniqueName(base: string, used: Set<string>): string {\n if (!used.has(base)) {\n return base;\n }\n let index = 1;\n let candidate = `${base}_${index}`;\n while (used.has(candidate)) {\n index += 1;\n candidate = `${base}_${index}`;\n }\n return candidate;\n}\n\nfunction toPascalCase(value: string): string {\n return value\n .split(/[_-]+/)\n .filter(Boolean)\n .map((part) => part[0]?.toUpperCase() + part.slice(1))\n .join(\"\");\n}\n\nfunction isVarcharType(value: string): value is `varchar(${number})` {\n return value.startsWith(\"varchar(\");\n}\n\nfunction getModelName(table: AnyTable, namespace: string | null): string {\n const base = toPascalCase(table.name);\n if (!namespace) {\n return base;\n }\n return `${base}_${sanitizeNamespace(namespace)}`;\n}\n\nfunction getPhysicalTableName(table: AnyTable, resolver?: NamingResolver): string {\n return resolver ? resolver.getTableName(table.name) : table.name;\n}\n\nfunction getRelationName(\n namespace: string | null,\n from: string,\n referenceName: string,\n to: string,\n): string {\n if (!namespace) {\n return `${from}_${referenceName}_${to}`;\n }\n return `${namespace}_${from}_${referenceName}_${to}`;\n}\n\nfunction getForeignKeyMapName(\n table: AnyTable,\n relation: Relation,\n _namespace: string | null,\n resolver?: NamingResolver,\n): string {\n if (resolver) {\n return resolver.getForeignKeyName({\n logicalTable: table.name,\n logicalReferencedTable: relation.table.name,\n referenceName: relation.name,\n });\n }\n return `${table.name}_${relation.table.name}_${relation.name}_fk`;\n}\n\nfunction getIndexMapName(\n indexName: string,\n tableName: string,\n namespace: string | null,\n resolver?: NamingResolver,\n unique?: boolean,\n): string {\n if (!resolver) {\n return namespace ? `${indexName}_${namespace}` : indexName;\n }\n return unique\n ? resolver.getUniqueIndexName(indexName, tableName)\n : resolver.getIndexName(indexName, tableName);\n}\n\nfunction getPrismaScalarType(\n column: AnyColumn,\n provider: SupportedDatabase,\n sqliteStorageMode: SQLiteStorageMode,\n): { type: string; nativeType?: string } {\n const internalIdType = provider === \"sqlite\" ? \"Int\" : \"BigInt\";\n\n if (column.role === \"internal-id\") {\n return { type: internalIdType };\n }\n\n if (column.role === \"reference\") {\n return { type: internalIdType };\n }\n\n if (isVarcharType(column.type)) {\n const length = parseVarchar(column.type);\n if (provider === \"postgresql\" || provider === \"mysql\") {\n return { type: \"String\", nativeType: `@db.VarChar(${length})` };\n }\n return { type: \"String\" };\n }\n\n switch (column.type) {\n case \"string\":\n return { type: \"String\" };\n case \"integer\":\n return { type: \"Int\" };\n case \"bigint\":\n if (provider === \"sqlite\" && sqliteStorageMode.bigintStorage === \"blob\") {\n return { type: \"Bytes\" };\n }\n return { type: \"BigInt\" };\n case \"bool\":\n return { type: \"Boolean\" };\n case \"decimal\":\n if (provider === \"sqlite\") {\n return { type: \"Float\" };\n }\n return { type: \"Decimal\" };\n case \"binary\":\n return { type: \"Bytes\" };\n case \"json\":\n if (provider === \"postgresql\") {\n return { type: \"Json\", nativeType: \"@db.Json\" };\n }\n return { type: \"Json\" };\n case \"timestamp\":\n if (provider === \"sqlite\" && sqliteStorageMode.timestampStorage === \"epoch-ms\") {\n return { type: \"Int\" };\n }\n return { type: \"DateTime\" };\n case \"date\":\n if (provider === \"sqlite\" && sqliteStorageMode.dateStorage === \"epoch-ms\") {\n return { type: \"Int\" };\n }\n if (provider === \"postgresql\" || provider === \"mysql\") {\n return { type: \"DateTime\", nativeType: \"@db.Date\" };\n }\n return { type: \"DateTime\" };\n default: {\n const exhaustiveCheck: never = column.type;\n throw new Error(`Unsupported column type: ${exhaustiveCheck}`);\n }\n }\n}\n\nfunction formatDefaultValue(value: unknown): string {\n if (value instanceof Date) {\n return JSON.stringify(value.toISOString());\n }\n if (typeof value === \"bigint\") {\n return value.toString();\n }\n return JSON.stringify(value);\n}\n\nfunction getColumnDefault(\n column: AnyColumn,\n provider: SupportedDatabase,\n sqliteStorageMode: SQLiteStorageMode,\n): string | undefined {\n if (!column.default) {\n return undefined;\n }\n\n if (\"value\" in column.default) {\n return `@default(${formatDefaultValue(column.default.value)})`;\n }\n\n if (\"dbSpecial\" in column.default && column.default.dbSpecial === \"now\") {\n const scalar = getPrismaScalarType(column, provider, sqliteStorageMode);\n if (scalar.type === \"DateTime\") {\n return \"@default(now())\";\n }\n if (provider === \"sqlite\") {\n const storage =\n column.type === \"date\" ? sqliteStorageMode.dateStorage : sqliteStorageMode.timestampStorage;\n if (storage === \"epoch-ms\") {\n return `@default(dbgenerated(\"CURRENT_TIMESTAMP\"))`;\n }\n }\n }\n\n return undefined;\n}\n\nfunction getColumnFieldName(\n columnName: string,\n usedNames: Set<string>,\n): { fieldName: string; needsMap: boolean } {\n const isValid = isValidIdentifier(columnName);\n const baseName = isValid ? columnName : sanitizeIdentifier(columnName);\n const fieldName = ensureUniqueName(baseName, usedNames);\n return { fieldName, needsMap: fieldName !== columnName };\n}\n\nfunction getRelationFieldName(baseName: string, usedNames: Set<string>): string {\n const validBase = isValidIdentifier(baseName) ? baseName : sanitizeIdentifier(baseName);\n return ensureUniqueName(validBase, usedNames);\n}\n\nfunction isRelationOptional(relation: Relation, columnFieldNames: Map<string, AnyColumn>): boolean {\n for (const [localColumn] of relation.on) {\n const column = columnFieldNames.get(localColumn);\n if (column?.isNullable) {\n return true;\n }\n }\n return false;\n}\n\nfunction getColumnFieldMappings(table: AnyTable): {\n fieldNameByColumn: Map<string, string>;\n columnByName: Map<string, AnyColumn>;\n} {\n const fieldNameByColumn = new Map<string, string>();\n const columnByName = new Map<string, AnyColumn>();\n const usedNames = new Set<string>();\n\n for (const column of Object.values(table.columns)) {\n const { fieldName } = getColumnFieldName(column.name, usedNames);\n usedNames.add(fieldName);\n fieldNameByColumn.set(column.name, fieldName);\n columnByName.set(column.name, column);\n }\n\n return { fieldNameByColumn, columnByName };\n}\n\nfunction areInverseRelations(one: Relation, many: Relation): boolean {\n if (one.type !== \"one\" || many.type !== \"many\") {\n return false;\n }\n if (one.referencer !== many.table || one.table !== many.referencer) {\n return false;\n }\n return one.on.every(([left, right]) =>\n many.on.some(([manyLeft, manyRight]) => manyLeft === right && manyRight === left),\n );\n}\n\nfunction findMatchingManyRelation(one: Relation): Relation | undefined {\n for (const relation of Object.values(one.table.relations)) {\n if (relation.type !== \"many\") {\n continue;\n }\n if (areInverseRelations(one, relation)) {\n return relation;\n }\n }\n return undefined;\n}\n\nfunction findMatchingOneRelation(many: Relation): Relation | undefined {\n for (const relation of Object.values(many.table.relations)) {\n if (relation.type !== \"one\") {\n continue;\n }\n if (areInverseRelations(relation, many)) {\n return relation;\n }\n }\n return undefined;\n}\n\nfunction generateColumnFields(\n table: AnyTable,\n provider: SupportedDatabase,\n sqliteStorageMode: SQLiteStorageMode,\n fieldNameByColumn: Map<string, string>,\n resolver?: NamingResolver,\n): string[] {\n const lines: string[] = [];\n\n for (const column of Object.values(table.columns)) {\n const fieldName = fieldNameByColumn.get(column.name)!;\n const scalar = getPrismaScalarType(column, provider, sqliteStorageMode);\n const isOptional = column.isNullable;\n\n const attributes: string[] = [];\n\n if (column.role === \"internal-id\") {\n attributes.push(\"@id\", \"@default(autoincrement())\");\n }\n\n if (column.role === \"external-id\") {\n attributes.push(\"@unique\", \"@default(cuid())\");\n }\n\n const defaultValue = getColumnDefault(column, provider, sqliteStorageMode);\n if (defaultValue) {\n attributes.push(defaultValue);\n }\n\n if (scalar.nativeType) {\n attributes.push(scalar.nativeType);\n }\n\n const physicalName = resolver ? resolver.getColumnName(table.name, column.name) : column.name;\n if (fieldName !== physicalName) {\n attributes.push(`@map(\"${physicalName}\")`);\n }\n\n const suffix = isOptional ? \"?\" : \"\";\n const attrSuffix = attributes.length > 0 ? ` ${attributes.join(\" \")}` : \"\";\n lines.push(` ${fieldName} ${scalar.type}${suffix}${attrSuffix}`);\n }\n\n return lines;\n}\n\nfunction generateRelationFields(\n table: AnyTable,\n namespace: string | null,\n fieldNameByColumn: Map<string, string>,\n columnByName: Map<string, AnyColumn>,\n fieldNameByTableColumn: Map<AnyTable, Map<string, string>>,\n resolver?: NamingResolver,\n): string[] {\n const lines: string[] = [];\n const usedNames = new Set<string>(fieldNameByColumn.values());\n const relations = Object.values(table.relations)\n .slice()\n .sort((a, b) => a.name.localeCompare(b.name));\n\n for (const relation of relations) {\n if (relation.type !== \"one\") {\n continue;\n }\n\n const fieldName = getRelationFieldName(relation.name, usedNames);\n usedNames.add(fieldName);\n\n const relationName = getRelationName(namespace, table.name, relation.name, relation.table.name);\n\n const relatedModel = getModelName(relation.table, namespace);\n const localFields = relation.on.map(([left]) => fieldNameByColumn.get(left) ?? left);\n const referenceFields = relation.on.map(([, right]) => {\n const actualRight = right === \"id\" ? \"_internalId\" : right;\n const refFieldNames = fieldNameByTableColumn.get(relation.table);\n return refFieldNames?.get(actualRight) ?? actualRight;\n });\n\n const fkMapName = getForeignKeyMapName(table, relation, namespace, resolver);\n\n const relationParts = [\n `\"${relationName}\"`,\n `fields: [${localFields.join(\", \")}]`,\n `references: [${referenceFields.join(\", \")}]`,\n `map: \"${fkMapName}\"`,\n ];\n\n const optional = isRelationOptional(relation, columnByName);\n const suffix = optional ? \"?\" : \"\";\n\n lines.push(` ${fieldName} ${relatedModel}${suffix} @relation(${relationParts.join(\", \")})`);\n }\n\n for (const relation of relations) {\n if (relation.type !== \"many\") {\n continue;\n }\n\n const matchingOne = findMatchingOneRelation(relation);\n const relationName = matchingOne\n ? getRelationName(\n namespace,\n matchingOne.referencer.name,\n matchingOne.name,\n matchingOne.table.name,\n )\n : getRelationName(namespace, relation.referencer.name, relation.name, relation.table.name);\n\n const fieldName = getRelationFieldName(relation.name, usedNames);\n usedNames.add(fieldName);\n\n const relatedModel = getModelName(relation.table, namespace);\n lines.push(` ${fieldName} ${relatedModel}[] @relation(\"${relationName}\")`);\n }\n\n const inverseCandidates: Relation[] = [];\n for (const sourceTable of fieldNameByTableColumn.keys()) {\n for (const rel of Object.values(sourceTable.relations)) {\n if (rel.type === \"one\" && rel.table === table) {\n inverseCandidates.push(rel);\n }\n }\n }\n\n for (const rel of inverseCandidates.sort((a, b) => a.name.localeCompare(b.name))) {\n const matchingMany = findMatchingManyRelation(rel);\n if (matchingMany) {\n continue;\n }\n\n const baseName = rel.referencer.name;\n let fieldName = baseName;\n if (usedNames.has(fieldName)) {\n fieldName = `${baseName}_${rel.name}`;\n }\n fieldName = getRelationFieldName(fieldName, usedNames);\n usedNames.add(fieldName);\n\n const relationName = getRelationName(namespace, rel.referencer.name, rel.name, rel.table.name);\n\n const relatedModel = getModelName(rel.referencer, namespace);\n lines.push(` ${fieldName} ${relatedModel}[] @relation(\"${relationName}\")`);\n }\n\n return lines;\n}\n\nfunction generateModel(\n table: AnyTable,\n namespace: string | null,\n provider: SupportedDatabase,\n sqliteStorageMode: SQLiteStorageMode,\n fieldNameByTableColumn: Map<AnyTable, Map<string, string>>,\n columnByTableName: Map<AnyTable, Map<string, AnyColumn>>,\n resolver?: NamingResolver,\n): string {\n const modelName = getModelName(table, namespace);\n const physicalName = getPhysicalTableName(table, resolver);\n\n const fieldNameByColumn = fieldNameByTableColumn.get(table)!;\n const columnByName = columnByTableName.get(table)!;\n\n const fieldLines = [\n ...generateColumnFields(table, provider, sqliteStorageMode, fieldNameByColumn, resolver),\n ...generateRelationFields(\n table,\n namespace,\n fieldNameByColumn,\n columnByName,\n fieldNameByTableColumn,\n resolver,\n ),\n ];\n\n const indexLines: string[] = [];\n const sortedIndexes = Object.values(table.indexes)\n .slice()\n .sort((a, b) => a.name.localeCompare(b.name));\n\n for (const index of sortedIndexes) {\n const fields = index.columnNames\n .map((name) => fieldNameByColumn.get(name as string) ?? name)\n .join(\", \");\n const mapName = getIndexMapName(index.name, table.name, namespace, resolver, index.unique);\n const directive = index.unique ? \"@@unique\" : \"@@index\";\n indexLines.push(` ${directive}([${fields}], map: \"${mapName}\")`);\n }\n\n indexLines.push(` @@map(\"${physicalName}\")`);\n\n const lines = [`model ${modelName} {`, ...fieldLines, ...indexLines, `}`];\n return lines.join(\"\\n\");\n}\n\nexport function generatePrismaSchema(\n fragments: { namespace: string | null; schema: AnySchema }[],\n provider: SupportedDatabase,\n options?: GeneratePrismaSchemaOptions,\n): string {\n const sqliteStorageMode =\n options?.sqliteStorageMode ??\n (provider === \"sqlite\" ? sqliteStoragePrisma : sqliteStorageDefault);\n const namingStrategy = options?.namingStrategy ?? defaultNamingStrategyForDatabase(provider);\n const namespaces = Array.from(new Set(fragments.map((fragment) => fragment.namespace)));\n const sortedNamespaces = namespaces.sort((a, b) => {\n const aKey = a ?? \"\";\n const bKey = b ?? \"\";\n if (aKey === \"\") {\n return -1;\n }\n if (bKey === \"\") {\n return 1;\n }\n return aKey.localeCompare(bKey);\n });\n\n const sortedFragments = sortedNamespaces\n .map((namespace) => fragments.find((fragment) => fragment.namespace === namespace))\n .filter((fragment): fragment is { namespace: string | null; schema: AnySchema } => !!fragment);\n\n const fieldNameByTableColumn = new Map<AnyTable, Map<string, string>>();\n const columnByTableName = new Map<AnyTable, Map<string, AnyColumn>>();\n\n for (const fragment of sortedFragments) {\n for (const table of Object.values(fragment.schema.tables)) {\n const mapping = getColumnFieldMappings(table);\n fieldNameByTableColumn.set(table, mapping.fieldNameByColumn);\n columnByTableName.set(table, mapping.columnByName);\n }\n }\n\n const headerNamespaces = sortedNamespaces.filter(Boolean);\n const headerSuffix = headerNamespaces.length > 0 ? headerNamespaces.join(\", \") : \"(internal)\";\n const lines: string[] = [\n \"// Generated by Fragno Prisma adapter.\",\n `// Provider: ${provider}`,\n `// Namespaces: ${headerSuffix}`,\n \"\",\n ];\n\n const models: string[] = [];\n\n for (const fragment of sortedFragments) {\n const resolver = createNamingResolver(fragment.schema, fragment.namespace, namingStrategy);\n const tables = Object.values(fragment.schema.tables)\n .slice()\n .sort((a, b) => {\n const aName = getPhysicalTableName(a, resolver);\n const bName = getPhysicalTableName(b, resolver);\n return aName.localeCompare(bName);\n });\n\n for (const table of tables) {\n models.push(\n generateModel(\n table,\n fragment.namespace,\n provider,\n sqliteStorageMode,\n fieldNameByTableColumn,\n columnByTableName,\n resolver,\n ),\n );\n }\n }\n\n lines.push(models.join(\"\\n\\n\"));\n return lines.join(\"\\n\");\n}\n"],"mappings":";;;;;;AAoBA,MAAM,mBAAmB;AAEzB,SAAS,kBAAkB,MAAuB;AAChD,QAAO,iBAAiB,KAAK,KAAK;;AAGpC,SAAS,mBAAmB,MAAsB;CAChD,MAAM,YAAY,KAAK,QAAQ,kBAAkB,IAAI;AACrD,KAAI,UAAU,WAAW,EACvB,QAAO;AAET,KAAI,SAAS,KAAK,UAAU,CAC1B,QAAO,IAAI;AAEb,QAAO;;AAGT,SAAS,iBAAiB,MAAc,MAA2B;AACjE,KAAI,CAAC,KAAK,IAAI,KAAK,CACjB,QAAO;CAET,IAAI,QAAQ;CACZ,IAAI,YAAY,GAAG,KAAK,GAAG;AAC3B,QAAO,KAAK,IAAI,UAAU,EAAE;AAC1B,WAAS;AACT,cAAY,GAAG,KAAK,GAAG;;AAEzB,QAAO;;AAGT,SAAS,aAAa,OAAuB;AAC3C,QAAO,MACJ,MAAM,QAAQ,CACd,OAAO,QAAQ,CACf,KAAK,SAAS,KAAK,IAAI,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,CACrD,KAAK,GAAG;;AAGb,SAAS,cAAc,OAA8C;AACnE,QAAO,MAAM,WAAW,WAAW;;AAGrC,SAAS,aAAa,OAAiB,WAAkC;CACvE,MAAM,OAAO,aAAa,MAAM,KAAK;AACrC,KAAI,CAAC,UACH,QAAO;AAET,QAAO,GAAG,KAAK,GAAG,kBAAkB,UAAU;;AAGhD,SAAS,qBAAqB,OAAiB,UAAmC;AAChF,QAAO,WAAW,SAAS,aAAa,MAAM,KAAK,GAAG,MAAM;;AAG9D,SAAS,gBACP,WACA,MACA,eACA,IACQ;AACR,KAAI,CAAC,UACH,QAAO,GAAG,KAAK,GAAG,cAAc,GAAG;AAErC,QAAO,GAAG,UAAU,GAAG,KAAK,GAAG,cAAc,GAAG;;AAGlD,SAAS,qBACP,OACA,UACA,YACA,UACQ;AACR,KAAI,SACF,QAAO,SAAS,kBAAkB;EAChC,cAAc,MAAM;EACpB,wBAAwB,SAAS,MAAM;EACvC,eAAe,SAAS;EACzB,CAAC;AAEJ,QAAO,GAAG,MAAM,KAAK,GAAG,SAAS,MAAM,KAAK,GAAG,SAAS,KAAK;;AAG/D,SAAS,gBACP,WACA,WACA,WACA,UACA,QACQ;AACR,KAAI,CAAC,SACH,QAAO,YAAY,GAAG,UAAU,GAAG,cAAc;AAEnD,QAAO,SACH,SAAS,mBAAmB,WAAW,UAAU,GACjD,SAAS,aAAa,WAAW,UAAU;;AAGjD,SAAS,oBACP,QACA,UACA,mBACuC;CACvC,MAAM,iBAAiB,aAAa,WAAW,QAAQ;AAEvD,KAAI,OAAO,SAAS,cAClB,QAAO,EAAE,MAAM,gBAAgB;AAGjC,KAAI,OAAO,SAAS,YAClB,QAAO,EAAE,MAAM,gBAAgB;AAGjC,KAAI,cAAc,OAAO,KAAK,EAAE;EAC9B,MAAM,SAAS,aAAa,OAAO,KAAK;AACxC,MAAI,aAAa,gBAAgB,aAAa,QAC5C,QAAO;GAAE,MAAM;GAAU,YAAY,eAAe,OAAO;GAAI;AAEjE,SAAO,EAAE,MAAM,UAAU;;AAG3B,SAAQ,OAAO,MAAf;EACE,KAAK,SACH,QAAO,EAAE,MAAM,UAAU;EAC3B,KAAK,UACH,QAAO,EAAE,MAAM,OAAO;EACxB,KAAK;AACH,OAAI,aAAa,YAAY,kBAAkB,kBAAkB,OAC/D,QAAO,EAAE,MAAM,SAAS;AAE1B,UAAO,EAAE,MAAM,UAAU;EAC3B,KAAK,OACH,QAAO,EAAE,MAAM,WAAW;EAC5B,KAAK;AACH,OAAI,aAAa,SACf,QAAO,EAAE,MAAM,SAAS;AAE1B,UAAO,EAAE,MAAM,WAAW;EAC5B,KAAK,SACH,QAAO,EAAE,MAAM,SAAS;EAC1B,KAAK;AACH,OAAI,aAAa,aACf,QAAO;IAAE,MAAM;IAAQ,YAAY;IAAY;AAEjD,UAAO,EAAE,MAAM,QAAQ;EACzB,KAAK;AACH,OAAI,aAAa,YAAY,kBAAkB,qBAAqB,WAClE,QAAO,EAAE,MAAM,OAAO;AAExB,UAAO,EAAE,MAAM,YAAY;EAC7B,KAAK;AACH,OAAI,aAAa,YAAY,kBAAkB,gBAAgB,WAC7D,QAAO,EAAE,MAAM,OAAO;AAExB,OAAI,aAAa,gBAAgB,aAAa,QAC5C,QAAO;IAAE,MAAM;IAAY,YAAY;IAAY;AAErD,UAAO,EAAE,MAAM,YAAY;EAC7B,SAAS;GACP,MAAMA,kBAAyB,OAAO;AACtC,SAAM,IAAI,MAAM,4BAA4B,kBAAkB;;;;AAKpE,SAAS,mBAAmB,OAAwB;AAClD,KAAI,iBAAiB,KACnB,QAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAE5C,KAAI,OAAO,UAAU,SACnB,QAAO,MAAM,UAAU;AAEzB,QAAO,KAAK,UAAU,MAAM;;AAG9B,SAAS,iBACP,QACA,UACA,mBACoB;AACpB,KAAI,CAAC,OAAO,QACV;AAGF,KAAI,WAAW,OAAO,QACpB,QAAO,YAAY,mBAAmB,OAAO,QAAQ,MAAM,CAAC;AAG9D,KAAI,eAAe,OAAO,WAAW,OAAO,QAAQ,cAAc,OAAO;AAEvE,MADe,oBAAoB,QAAQ,UAAU,kBAAkB,CAC5D,SAAS,WAClB,QAAO;AAET,MAAI,aAAa,UAGf;QADE,OAAO,SAAS,SAAS,kBAAkB,cAAc,kBAAkB,sBAC7D,WACd,QAAO;;;;AAQf,SAAS,mBACP,YACA,WAC0C;CAG1C,MAAM,YAAY,iBAFF,kBAAkB,WAAW,GAClB,aAAa,mBAAmB,WAAW,EACzB,UAAU;AACvD,QAAO;EAAE;EAAW,UAAU,cAAc;EAAY;;AAG1D,SAAS,qBAAqB,UAAkB,WAAgC;AAE9E,QAAO,iBADW,kBAAkB,SAAS,GAAG,WAAW,mBAAmB,SAAS,EACpD,UAAU;;AAG/C,SAAS,mBAAmB,UAAoB,kBAAmD;AACjG,MAAK,MAAM,CAAC,gBAAgB,SAAS,GAEnC,KADe,iBAAiB,IAAI,YAAY,EACpC,WACV,QAAO;AAGX,QAAO;;AAGT,SAAS,uBAAuB,OAG9B;CACA,MAAM,oCAAoB,IAAI,KAAqB;CACnD,MAAM,+BAAe,IAAI,KAAwB;CACjD,MAAM,4BAAY,IAAI,KAAa;AAEnC,MAAK,MAAM,UAAU,OAAO,OAAO,MAAM,QAAQ,EAAE;EACjD,MAAM,EAAE,cAAc,mBAAmB,OAAO,MAAM,UAAU;AAChE,YAAU,IAAI,UAAU;AACxB,oBAAkB,IAAI,OAAO,MAAM,UAAU;AAC7C,eAAa,IAAI,OAAO,MAAM,OAAO;;AAGvC,QAAO;EAAE;EAAmB;EAAc;;AAG5C,SAAS,oBAAoB,KAAe,MAAyB;AACnE,KAAI,IAAI,SAAS,SAAS,KAAK,SAAS,OACtC,QAAO;AAET,KAAI,IAAI,eAAe,KAAK,SAAS,IAAI,UAAU,KAAK,WACtD,QAAO;AAET,QAAO,IAAI,GAAG,OAAO,CAAC,MAAM,WAC1B,KAAK,GAAG,MAAM,CAAC,UAAU,eAAe,aAAa,SAAS,cAAc,KAAK,CAClF;;AAGH,SAAS,yBAAyB,KAAqC;AACrE,MAAK,MAAM,YAAY,OAAO,OAAO,IAAI,MAAM,UAAU,EAAE;AACzD,MAAI,SAAS,SAAS,OACpB;AAEF,MAAI,oBAAoB,KAAK,SAAS,CACpC,QAAO;;;AAMb,SAAS,wBAAwB,MAAsC;AACrE,MAAK,MAAM,YAAY,OAAO,OAAO,KAAK,MAAM,UAAU,EAAE;AAC1D,MAAI,SAAS,SAAS,MACpB;AAEF,MAAI,oBAAoB,UAAU,KAAK,CACrC,QAAO;;;AAMb,SAAS,qBACP,OACA,UACA,mBACA,mBACA,UACU;CACV,MAAMC,QAAkB,EAAE;AAE1B,MAAK,MAAM,UAAU,OAAO,OAAO,MAAM,QAAQ,EAAE;EACjD,MAAM,YAAY,kBAAkB,IAAI,OAAO,KAAK;EACpD,MAAM,SAAS,oBAAoB,QAAQ,UAAU,kBAAkB;EACvE,MAAM,aAAa,OAAO;EAE1B,MAAMC,aAAuB,EAAE;AAE/B,MAAI,OAAO,SAAS,cAClB,YAAW,KAAK,OAAO,4BAA4B;AAGrD,MAAI,OAAO,SAAS,cAClB,YAAW,KAAK,WAAW,mBAAmB;EAGhD,MAAM,eAAe,iBAAiB,QAAQ,UAAU,kBAAkB;AAC1E,MAAI,aACF,YAAW,KAAK,aAAa;AAG/B,MAAI,OAAO,WACT,YAAW,KAAK,OAAO,WAAW;EAGpC,MAAM,eAAe,WAAW,SAAS,cAAc,MAAM,MAAM,OAAO,KAAK,GAAG,OAAO;AACzF,MAAI,cAAc,aAChB,YAAW,KAAK,SAAS,aAAa,IAAI;EAG5C,MAAM,SAAS,aAAa,MAAM;EAClC,MAAM,aAAa,WAAW,SAAS,IAAI,IAAI,WAAW,KAAK,IAAI,KAAK;AACxE,QAAM,KAAK,KAAK,UAAU,GAAG,OAAO,OAAO,SAAS,aAAa;;AAGnE,QAAO;;AAGT,SAAS,uBACP,OACA,WACA,mBACA,cACA,wBACA,UACU;CACV,MAAMD,QAAkB,EAAE;CAC1B,MAAM,YAAY,IAAI,IAAY,kBAAkB,QAAQ,CAAC;CAC7D,MAAM,YAAY,OAAO,OAAO,MAAM,UAAU,CAC7C,OAAO,CACP,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;AAE/C,MAAK,MAAM,YAAY,WAAW;AAChC,MAAI,SAAS,SAAS,MACpB;EAGF,MAAM,YAAY,qBAAqB,SAAS,MAAM,UAAU;AAChE,YAAU,IAAI,UAAU;EAExB,MAAM,eAAe,gBAAgB,WAAW,MAAM,MAAM,SAAS,MAAM,SAAS,MAAM,KAAK;EAE/F,MAAM,eAAe,aAAa,SAAS,OAAO,UAAU;EAC5D,MAAM,cAAc,SAAS,GAAG,KAAK,CAAC,UAAU,kBAAkB,IAAI,KAAK,IAAI,KAAK;EACpF,MAAM,kBAAkB,SAAS,GAAG,KAAK,GAAG,WAAW;GACrD,MAAM,cAAc,UAAU,OAAO,gBAAgB;AAErD,UADsB,uBAAuB,IAAI,SAAS,MAAM,EAC1C,IAAI,YAAY,IAAI;IAC1C;EAEF,MAAM,YAAY,qBAAqB,OAAO,UAAU,WAAW,SAAS;EAE5E,MAAM,gBAAgB;GACpB,IAAI,aAAa;GACjB,YAAY,YAAY,KAAK,KAAK,CAAC;GACnC,gBAAgB,gBAAgB,KAAK,KAAK,CAAC;GAC3C,SAAS,UAAU;GACpB;EAGD,MAAM,SADW,mBAAmB,UAAU,aAAa,GACjC,MAAM;AAEhC,QAAM,KAAK,KAAK,UAAU,GAAG,eAAe,OAAO,aAAa,cAAc,KAAK,KAAK,CAAC,GAAG;;AAG9F,MAAK,MAAM,YAAY,WAAW;AAChC,MAAI,SAAS,SAAS,OACpB;EAGF,MAAM,cAAc,wBAAwB,SAAS;EACrD,MAAM,eAAe,cACjB,gBACE,WACA,YAAY,WAAW,MACvB,YAAY,MACZ,YAAY,MAAM,KACnB,GACD,gBAAgB,WAAW,SAAS,WAAW,MAAM,SAAS,MAAM,SAAS,MAAM,KAAK;EAE5F,MAAM,YAAY,qBAAqB,SAAS,MAAM,UAAU;AAChE,YAAU,IAAI,UAAU;EAExB,MAAM,eAAe,aAAa,SAAS,OAAO,UAAU;AAC5D,QAAM,KAAK,KAAK,UAAU,GAAG,aAAa,gBAAgB,aAAa,IAAI;;CAG7E,MAAME,oBAAgC,EAAE;AACxC,MAAK,MAAM,eAAe,uBAAuB,MAAM,CACrD,MAAK,MAAM,OAAO,OAAO,OAAO,YAAY,UAAU,CACpD,KAAI,IAAI,SAAS,SAAS,IAAI,UAAU,MACtC,mBAAkB,KAAK,IAAI;AAKjC,MAAK,MAAM,OAAO,kBAAkB,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC,EAAE;AAEhF,MADqB,yBAAyB,IAAI,CAEhD;EAGF,MAAM,WAAW,IAAI,WAAW;EAChC,IAAI,YAAY;AAChB,MAAI,UAAU,IAAI,UAAU,CAC1B,aAAY,GAAG,SAAS,GAAG,IAAI;AAEjC,cAAY,qBAAqB,WAAW,UAAU;AACtD,YAAU,IAAI,UAAU;EAExB,MAAM,eAAe,gBAAgB,WAAW,IAAI,WAAW,MAAM,IAAI,MAAM,IAAI,MAAM,KAAK;EAE9F,MAAM,eAAe,aAAa,IAAI,YAAY,UAAU;AAC5D,QAAM,KAAK,KAAK,UAAU,GAAG,aAAa,gBAAgB,aAAa,IAAI;;AAG7E,QAAO;;AAGT,SAAS,cACP,OACA,WACA,UACA,mBACA,wBACA,mBACA,UACQ;CACR,MAAM,YAAY,aAAa,OAAO,UAAU;CAChD,MAAM,eAAe,qBAAqB,OAAO,SAAS;CAE1D,MAAM,oBAAoB,uBAAuB,IAAI,MAAM;CAC3D,MAAM,eAAe,kBAAkB,IAAI,MAAM;CAEjD,MAAM,aAAa,CACjB,GAAG,qBAAqB,OAAO,UAAU,mBAAmB,mBAAmB,SAAS,EACxF,GAAG,uBACD,OACA,WACA,mBACA,cACA,wBACA,SACD,CACF;CAED,MAAMC,aAAuB,EAAE;CAC/B,MAAM,gBAAgB,OAAO,OAAO,MAAM,QAAQ,CAC/C,OAAO,CACP,MAAM,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;AAE/C,MAAK,MAAM,SAAS,eAAe;EACjC,MAAM,SAAS,MAAM,YAClB,KAAK,SAAS,kBAAkB,IAAI,KAAe,IAAI,KAAK,CAC5D,KAAK,KAAK;EACb,MAAM,UAAU,gBAAgB,MAAM,MAAM,MAAM,MAAM,WAAW,UAAU,MAAM,OAAO;EAC1F,MAAM,YAAY,MAAM,SAAS,aAAa;AAC9C,aAAW,KAAK,KAAK,UAAU,IAAI,OAAO,WAAW,QAAQ,IAAI;;AAGnE,YAAW,KAAK,YAAY,aAAa,IAAI;AAG7C,QADc;EAAC,SAAS,UAAU;EAAK,GAAG;EAAY,GAAG;EAAY;EAAI,CAC5D,KAAK,KAAK;;AAGzB,SAAgB,qBACd,WACA,UACA,SACQ;CACR,MAAM,oBACJ,SAAS,sBACR,aAAa,WAAW,sBAAsB;CACjD,MAAM,iBAAiB,SAAS,kBAAkB,iCAAiC,SAAS;CAE5F,MAAM,mBADa,MAAM,KAAK,IAAI,IAAI,UAAU,KAAK,aAAa,SAAS,UAAU,CAAC,CAAC,CACnD,MAAM,GAAG,MAAM;EACjD,MAAM,OAAO,KAAK;EAClB,MAAM,OAAO,KAAK;AAClB,MAAI,SAAS,GACX,QAAO;AAET,MAAI,SAAS,GACX,QAAO;AAET,SAAO,KAAK,cAAc,KAAK;GAC/B;CAEF,MAAM,kBAAkB,iBACrB,KAAK,cAAc,UAAU,MAAM,aAAa,SAAS,cAAc,UAAU,CAAC,CAClF,QAAQ,aAA0E,CAAC,CAAC,SAAS;CAEhG,MAAM,yCAAyB,IAAI,KAAoC;CACvE,MAAM,oCAAoB,IAAI,KAAuC;AAErE,MAAK,MAAM,YAAY,gBACrB,MAAK,MAAM,SAAS,OAAO,OAAO,SAAS,OAAO,OAAO,EAAE;EACzD,MAAM,UAAU,uBAAuB,MAAM;AAC7C,yBAAuB,IAAI,OAAO,QAAQ,kBAAkB;AAC5D,oBAAkB,IAAI,OAAO,QAAQ,aAAa;;CAItD,MAAM,mBAAmB,iBAAiB,OAAO,QAAQ;CACzD,MAAM,eAAe,iBAAiB,SAAS,IAAI,iBAAiB,KAAK,KAAK,GAAG;CACjF,MAAMH,QAAkB;EACtB;EACA,gBAAgB;EAChB,kBAAkB;EAClB;EACD;CAED,MAAMI,SAAmB,EAAE;AAE3B,MAAK,MAAM,YAAY,iBAAiB;EACtC,MAAM,WAAW,qBAAqB,SAAS,QAAQ,SAAS,WAAW,eAAe;EAC1F,MAAM,SAAS,OAAO,OAAO,SAAS,OAAO,OAAO,CACjD,OAAO,CACP,MAAM,GAAG,MAAM;GACd,MAAM,QAAQ,qBAAqB,GAAG,SAAS;GAC/C,MAAM,QAAQ,qBAAqB,GAAG,SAAS;AAC/C,UAAO,MAAM,cAAc,MAAM;IACjC;AAEJ,OAAK,MAAM,SAAS,OAClB,QAAO,KACL,cACE,OACA,SAAS,WACT,UACA,mBACA,wBACA,mBACA,SACD,CACF;;AAIL,OAAM,KAAK,OAAO,KAAK,OAAO,CAAC;AAC/B,QAAO,MAAM,KAAK,KAAK"}
@@ -0,0 +1,61 @@
1
+ import { SqlAdapter } from "../adapters/generic-sql/generic-sql-adapter.js";
2
+ import { BetterSQLite3DriverConfig } from "../adapters/generic-sql/driver-config.js";
3
+ import { createRequire } from "node:module";
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+ import { SqliteDialect } from "kysely";
7
+
8
+ //#region src/util/default-database-adapter.ts
9
+ const createNodeRequire = () => {
10
+ try {
11
+ const metaUrl = typeof import.meta !== "undefined" ? import.meta.url : void 0;
12
+ if (!metaUrl || typeof metaUrl !== "string") return null;
13
+ return createRequire(metaUrl);
14
+ } catch {
15
+ return null;
16
+ }
17
+ };
18
+ const loadBetterSqlite3 = () => {
19
+ const requireFn = createNodeRequire();
20
+ if (!requireFn) return null;
21
+ try {
22
+ const module = requireFn("better-sqlite3");
23
+ return module.default ?? module;
24
+ } catch {
25
+ return null;
26
+ }
27
+ };
28
+ const betterSqlite3Constructor = loadBetterSqlite3();
29
+ const defaultDataDir = () => {
30
+ const configured = process.env["FRAGNO_DATA_DIR"];
31
+ if (configured && configured.trim().length > 0) return configured;
32
+ return path.join(process.env["HOME"] ?? process.cwd(), ".fragno");
33
+ };
34
+ const sanitizeFileSegment = (name) => {
35
+ const sanitized = name.replace(/[^a-z0-9-]/gi, "_");
36
+ return sanitized.length > 0 ? sanitized : "fragno";
37
+ };
38
+ const resolveSqliteDatabasePath = (options, schema) => {
39
+ const fileName = `${sanitizeFileSegment(typeof options.databaseNamespace === "string" && options.databaseNamespace.length > 0 ? options.databaseNamespace : schema.name)}.sqlite`;
40
+ return path.join(defaultDataDir(), fileName);
41
+ };
42
+ const createDefaultSqliteAdapter = (options, schema) => {
43
+ if (!betterSqlite3Constructor) return null;
44
+ const dbPath = resolveSqliteDatabasePath(options, schema);
45
+ fs.mkdirSync(path.dirname(dbPath), { recursive: true });
46
+ return new SqlAdapter({
47
+ dialect: new SqliteDialect({ database: new betterSqlite3Constructor(dbPath) }),
48
+ driverConfig: new BetterSQLite3DriverConfig()
49
+ });
50
+ };
51
+ const resolveDatabaseAdapter = (options, schema) => {
52
+ if (options.databaseAdapter) return options.databaseAdapter;
53
+ const defaultAdapter = createDefaultSqliteAdapter(options, schema);
54
+ if (!defaultAdapter) throw new Error("Database fragment requires options.databaseAdapter, or install better-sqlite3 to use the default SQLite adapter.");
55
+ options.databaseAdapter = defaultAdapter;
56
+ return defaultAdapter;
57
+ };
58
+
59
+ //#endregion
60
+ export { resolveDatabaseAdapter };
61
+ //# sourceMappingURL=default-database-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-database-adapter.js","names":[],"sources":["../../src/util/default-database-adapter.ts"],"sourcesContent":["import fs from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport path from \"node:path\";\nimport { SqliteDialect } from \"kysely\";\nimport { SqlAdapter } from \"../adapters/generic-sql/generic-sql-adapter\";\nimport { BetterSQLite3DriverConfig } from \"../adapters/generic-sql/driver-config\";\nimport type { DatabaseAdapter } from \"../adapters/adapters\";\nimport type { AnySchema } from \"../schema/create\";\ntype DatabaseAdapterConfig = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n databaseAdapter?: DatabaseAdapter<any>;\n databaseNamespace?: string | null;\n};\n\ntype BetterSqlite3Constructor = typeof import(\"better-sqlite3\");\n\nconst createNodeRequire = (): NodeRequire | null => {\n try {\n const metaUrl = typeof import.meta !== \"undefined\" ? import.meta.url : undefined;\n if (!metaUrl || typeof metaUrl !== \"string\") {\n return null;\n }\n return createRequire(metaUrl);\n } catch {\n return null;\n }\n};\n\nconst loadBetterSqlite3 = (): BetterSqlite3Constructor | null => {\n const requireFn = createNodeRequire();\n if (!requireFn) {\n return null;\n }\n try {\n const module = requireFn(\"better-sqlite3\");\n return (module.default ?? module) as BetterSqlite3Constructor;\n } catch {\n return null;\n }\n};\n\nconst betterSqlite3Constructor = loadBetterSqlite3();\n\nconst defaultDataDir = (): string => {\n const configured = process.env[\"FRAGNO_DATA_DIR\"];\n if (configured && configured.trim().length > 0) {\n return configured;\n }\n return path.join(process.env[\"HOME\"] ?? process.cwd(), \".fragno\");\n};\n\nconst sanitizeFileSegment = (name: string): string => {\n const sanitized = name.replace(/[^a-z0-9-]/gi, \"_\");\n return sanitized.length > 0 ? sanitized : \"fragno\";\n};\n\nconst resolveSqliteDatabasePath = <TSchema extends AnySchema>(\n options: DatabaseAdapterConfig,\n schema: TSchema,\n): string => {\n const baseName =\n typeof options.databaseNamespace === \"string\" && options.databaseNamespace.length > 0\n ? options.databaseNamespace\n : schema.name;\n const fileName = `${sanitizeFileSegment(baseName)}.sqlite`;\n return path.join(defaultDataDir(), fileName);\n};\n\nconst createDefaultSqliteAdapter = <TSchema extends AnySchema>(\n options: DatabaseAdapterConfig,\n schema: TSchema,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): DatabaseAdapter<any> | null => {\n if (!betterSqlite3Constructor) {\n return null;\n }\n\n const dbPath = resolveSqliteDatabasePath(options, schema);\n fs.mkdirSync(path.dirname(dbPath), { recursive: true });\n\n const dialect = new SqliteDialect({\n database: new betterSqlite3Constructor(dbPath),\n });\n const driverConfig = new BetterSQLite3DriverConfig();\n return new SqlAdapter({ dialect, driverConfig });\n};\n\nexport const resolveDatabaseAdapter = <TSchema extends AnySchema>(\n options: DatabaseAdapterConfig,\n schema: TSchema,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): DatabaseAdapter<any> => {\n if (options.databaseAdapter) {\n return options.databaseAdapter;\n }\n\n const defaultAdapter = createDefaultSqliteAdapter(options, schema);\n if (!defaultAdapter) {\n throw new Error(\n \"Database fragment requires options.databaseAdapter, or install better-sqlite3 to use the default SQLite adapter.\",\n );\n }\n\n options.databaseAdapter = defaultAdapter;\n return defaultAdapter;\n};\n"],"mappings":";;;;;;;;AAgBA,MAAM,0BAA8C;AAClD,KAAI;EACF,MAAM,UAAU,OAAO,OAAO,SAAS,cAAc,OAAO,KAAK,MAAM;AACvE,MAAI,CAAC,WAAW,OAAO,YAAY,SACjC,QAAO;AAET,SAAO,cAAc,QAAQ;SACvB;AACN,SAAO;;;AAIX,MAAM,0BAA2D;CAC/D,MAAM,YAAY,mBAAmB;AACrC,KAAI,CAAC,UACH,QAAO;AAET,KAAI;EACF,MAAM,SAAS,UAAU,iBAAiB;AAC1C,SAAQ,OAAO,WAAW;SACpB;AACN,SAAO;;;AAIX,MAAM,2BAA2B,mBAAmB;AAEpD,MAAM,uBAA+B;CACnC,MAAM,aAAa,QAAQ,IAAI;AAC/B,KAAI,cAAc,WAAW,MAAM,CAAC,SAAS,EAC3C,QAAO;AAET,QAAO,KAAK,KAAK,QAAQ,IAAI,WAAW,QAAQ,KAAK,EAAE,UAAU;;AAGnE,MAAM,uBAAuB,SAAyB;CACpD,MAAM,YAAY,KAAK,QAAQ,gBAAgB,IAAI;AACnD,QAAO,UAAU,SAAS,IAAI,YAAY;;AAG5C,MAAM,6BACJ,SACA,WACW;CAKX,MAAM,WAAW,GAAG,oBAHlB,OAAO,QAAQ,sBAAsB,YAAY,QAAQ,kBAAkB,SAAS,IAChF,QAAQ,oBACR,OAAO,KACoC,CAAC;AAClD,QAAO,KAAK,KAAK,gBAAgB,EAAE,SAAS;;AAG9C,MAAM,8BACJ,SACA,WAEgC;AAChC,KAAI,CAAC,yBACH,QAAO;CAGT,MAAM,SAAS,0BAA0B,SAAS,OAAO;AACzD,IAAG,UAAU,KAAK,QAAQ,OAAO,EAAE,EAAE,WAAW,MAAM,CAAC;AAMvD,QAAO,IAAI,WAAW;EAAE,SAJR,IAAI,cAAc,EAChC,UAAU,IAAI,yBAAyB,OAAO,EAC/C,CAAC;EAE+B,cADZ,IAAI,2BAA2B;EACL,CAAC;;AAGlD,MAAa,0BACX,SACA,WAEyB;AACzB,KAAI,QAAQ,gBACV,QAAO,QAAQ;CAGjB,MAAM,iBAAiB,2BAA2B,SAAS,OAAO;AAClE,KAAI,CAAC,eACH,OAAM,IAAI,MACR,mHACD;AAGH,SAAQ,kBAAkB;AAC1B,QAAO"}
@@ -24,7 +24,7 @@ import { AnyFragnoInstantiatedFragment, FragmentDefinitionBuilder, FragnoPublicC
24
24
  * .build();
25
25
  * ```
26
26
  */
27
- declare function withDatabase<TSchema extends AnySchema>(schema: TSchema, namespace?: string): <TConfig, TDeps, TBaseServices, TServices, TServiceDeps, TPrivateServices, TServiceThisContext extends RequestThisContext, THandlerThisContext extends RequestThisContext, TRequestStorage, TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment>>(builder: FragmentDefinitionBuilder<TConfig, FragnoPublicConfig, TDeps, TBaseServices, TServices, TServiceDeps, TPrivateServices, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments>) => DatabaseFragmentDefinitionBuilder<TSchema, TConfig, TDeps & ImplicitDatabaseDependencies<TSchema>, TBaseServices, TServices, TServiceDeps, TPrivateServices, HooksMap, DatabaseServiceContext<HooksMap>, DatabaseHandlerContext, TLinkedFragments & {
27
+ declare function withDatabase<TSchema extends AnySchema>(schema: TSchema): <TConfig, TDeps, TBaseServices, TServices, TServiceDeps, TPrivateServices, TServiceThisContext extends RequestThisContext, THandlerThisContext extends RequestThisContext, TRequestStorage, TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment>>(builder: FragmentDefinitionBuilder<TConfig, FragnoPublicConfig, TDeps, TBaseServices, TServices, TServiceDeps, TPrivateServices, TServiceThisContext, THandlerThisContext, TRequestStorage, TLinkedFragments>) => DatabaseFragmentDefinitionBuilder<TSchema, TConfig, TDeps & ImplicitDatabaseDependencies<TSchema>, TBaseServices, TServices, TServiceDeps, TPrivateServices, HooksMap, DatabaseServiceContext<HooksMap>, DatabaseHandlerContext, TLinkedFragments & {
28
28
  _fragno_internal: InternalFragmentInstance;
29
29
  }>;
30
30
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"with-database.d.ts","names":[],"sources":["../src/with-database.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAoCA;;;;;;;;;;;;;;;;;AA0BI,iBA1BY,YA0BZ,CAAA,gBA1ByC,SA0BzC,CAAA,CAAA,MAAA,EAzBM,OAyBN,EAAA,SAAA,CAAA,EAAA,MAAA,CAAA,EAAA,CAAA,OAAA,EAAA,KAAA,EAAA,aAAA,EAAA,SAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,4BAhB0B,kBAgB1B,EAAA,4BAf0B,kBAe1B,EAAA,eAAA,EAAA,yBAbuB,MAavB,CAAA,MAAA,EAbsC,6BAatC,CAAA,CAAA,CAAA,OAAA,EAXO,yBAWP,CAVA,OAUA,EATA,kBASA,EARA,KAQA,EAPA,aAOA,EANA,SAMA,EALA,YAKA,EAJA,gBAIA,EAHA,mBAGA,EAFA,mBAEA,EADA,eACA,EAAA,gBAAA,CAAA,EAAA,GAEC,iCAFD,CAGF,OAHE,EAIF,OAJE,EAKF,KALE,GAKM,4BALN,CAKmC,OALnC,CAAA,EAMF,aANE,EAOF,SAPE,EAQF,YARE,EASF,gBATE,EAUF,QAVE,EAWF,sBAXE,CAWqB,QAXrB,CAAA,EAYF,sBAZE,EAaF,gBAbE,GAAA;EAXO,gBAAA,EAwB8B,wBAxB9B;CAcT,CAAA"}
1
+ {"version":3,"file":"with-database.d.ts","names":[],"sources":["../src/with-database.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AA8CA;;;;;;;;;;;;;;;;;AAyBI,iBAzBY,YAyBZ,CAAA,gBAzByC,SAyBzC,CAAA,CAAA,MAAA,EAxBM,OAwBN,CAAA,EAAA,CAAA,OAAA,EAAA,KAAA,EAAA,aAAA,EAAA,SAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,4BAhB0B,kBAgB1B,EAAA,4BAf0B,kBAe1B,EAAA,eAAA,EAAA,yBAbuB,MAavB,CAAA,MAAA,EAbsC,6BAatC,CAAA,CAAA,CAAA,OAAA,EAXO,yBAWP,CAVA,OAUA,EATA,kBASA,EARA,KAQA,EAPA,aAOA,EANA,SAMA,EALA,YAKA,EAJA,gBAIA,EAHA,mBAGA,EAFA,mBAEA,EADA,eACA,EAAA,gBAAA,CAAA,EAAA,GAEC,iCAFD,CAGF,OAHE,EAIF,OAJE,EAKF,KALE,GAKM,4BALN,CAKmC,OALnC,CAAA,EAMF,aANE,EAOF,SAPE,EAQF,YARE,EASF,gBATE,EAUF,QAVE,EAWF,sBAXE,CAWqB,QAXrB,CAAA,EAYF,sBAZE,EAaF,gBAbE,GAAA;EAXO,gBAAA,EAwB8B,wBAxB9B;CAcT,CAAA"}
@@ -1,8 +1,13 @@
1
1
  import { instantiate } from "./packages/fragno/dist/api/fragment-instantiator.js";
2
+ import { resolveDatabaseAdapter } from "./util/default-database-adapter.js";
2
3
  import { DatabaseFragmentDefinitionBuilder } from "./db-fragment-definition-builder.js";
3
4
  import { internalFragmentDef } from "./fragments/internal-fragment.js";
5
+ import { internalFragmentRoutes } from "./fragments/internal-fragment.routes.js";
4
6
 
5
7
  //#region src/with-database.ts
8
+ function shouldExposeOutboxRoutes(options, schema) {
9
+ return resolveDatabaseAdapter(options, schema).outbox?.enabled ?? false;
10
+ }
6
11
  /**
7
12
  * Helper to add database support to a fragment builder.
8
13
  * Automatically links the internal fragment and adds ImplicitDatabaseDependencies to the TDeps type.
@@ -21,11 +26,15 @@ import { internalFragmentDef } from "./fragments/internal-fragment.js";
21
26
  * .build();
22
27
  * ```
23
28
  */
24
- function withDatabase(schema, namespace) {
29
+ function withDatabase(schema) {
25
30
  return (builder) => {
26
31
  return new DatabaseFragmentDefinitionBuilder(builder.withLinkedFragment("_fragno_internal", ({ config, options }) => {
27
- return instantiate(internalFragmentDef).withConfig(config).withOptions(options).build();
28
- }), schema, namespace);
32
+ const internalRoutes = shouldExposeOutboxRoutes(options, schema) ? [internalFragmentRoutes] : [];
33
+ return instantiate(internalFragmentDef).withConfig(config).withOptions({
34
+ ...options,
35
+ databaseNamespace: null
36
+ }).withRoutes(internalRoutes).build();
37
+ }), schema);
29
38
  };
30
39
  }
31
40
 
@@ -1 +1 @@
1
- {"version":3,"file":"with-database.js","names":[],"sources":["../src/with-database.ts"],"sourcesContent":["import type { AnySchema } from \"./schema/create\";\nimport type {\n RequestThisContext,\n FragnoPublicConfig,\n AnyFragnoInstantiatedFragment,\n} from \"@fragno-dev/core\";\nimport { FragmentDefinitionBuilder, instantiate } from \"@fragno-dev/core\";\nimport {\n DatabaseFragmentDefinitionBuilder,\n type DatabaseServiceContext,\n type DatabaseHandlerContext,\n type ImplicitDatabaseDependencies,\n type FragnoPublicConfigWithDatabase,\n type DatabaseRequestStorage,\n} from \"./db-fragment-definition-builder\";\nimport { internalFragmentDef, type InternalFragmentInstance } from \"./fragments/internal-fragment\";\nimport type { HooksMap } from \"./hooks/hooks\";\n\n/**\n * Helper to add database support to a fragment builder.\n * Automatically links the internal fragment and adds ImplicitDatabaseDependencies to the TDeps type.\n *\n * @example\n * ```typescript\n * // With .extend() - recommended\n * const def = defineFragment(\"my-frag\")\n * .extend(withDatabase(mySchema))\n * .withDependencies(...)\n * .build();\n *\n * // Or as a function wrapper\n * const def = withDatabase(mySchema)(defineFragment(\"my-frag\"))\n * .withDependencies(...)\n * .build();\n * ```\n */\nexport function withDatabase<TSchema extends AnySchema>(\n schema: TSchema,\n namespace?: string,\n): <\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n TServiceThisContext extends RequestThisContext,\n THandlerThisContext extends RequestThisContext,\n TRequestStorage,\n TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment>,\n>(\n builder: FragmentDefinitionBuilder<\n TConfig,\n FragnoPublicConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n TServiceThisContext,\n THandlerThisContext,\n TRequestStorage,\n TLinkedFragments\n >,\n) => DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps & ImplicitDatabaseDependencies<TSchema>,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n HooksMap,\n DatabaseServiceContext<HooksMap>,\n DatabaseHandlerContext,\n TLinkedFragments & { _fragno_internal: InternalFragmentInstance }\n> {\n return <\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n TServiceThisContext extends RequestThisContext,\n THandlerThisContext extends RequestThisContext,\n TRequestStorage,\n TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment>,\n >(\n builder: FragmentDefinitionBuilder<\n TConfig,\n FragnoPublicConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n TServiceThisContext,\n THandlerThisContext,\n TRequestStorage,\n TLinkedFragments\n >,\n ) => {\n const builderWithInternal = builder.withLinkedFragment(\n \"_fragno_internal\",\n ({ config, options }) => {\n // Cast is safe: by the time this callback is invoked during fragment instantiation,\n // the options will be FragnoPublicConfigWithDatabase (enforced by DatabaseFragmentDefinitionBuilder)\n return instantiate(internalFragmentDef)\n .withConfig(config as {})\n .withOptions(options as FragnoPublicConfigWithDatabase)\n .build();\n },\n );\n\n // Cast is safe: we're creating a DatabaseFragmentDefinitionBuilder which internally uses\n // FragnoPublicConfigWithDatabase, but the input builder uses FragnoPublicConfig.\n // The database builder's build() method will enforce FragnoPublicConfigWithDatabase at the end.\n // We also add ImplicitDatabaseDependencies to TDeps so they're available in service constructors.\n // Note: We discard TRequestStorage here because database fragments manage their own storage (DatabaseRequestStorage).\n // We set TServiceThisContext to DatabaseServiceContext (restricted) and THandlerThisContext to DatabaseHandlerContext (full).\n return new DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps & ImplicitDatabaseDependencies<TSchema>,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n {}, // Start with empty hooks, provideHooks() will update this\n DatabaseServiceContext<{}>,\n DatabaseHandlerContext,\n TLinkedFragments & { _fragno_internal: InternalFragmentInstance }\n >(\n builderWithInternal as unknown as FragmentDefinitionBuilder<\n TConfig,\n FragnoPublicConfigWithDatabase,\n TDeps & ImplicitDatabaseDependencies<TSchema>,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n DatabaseServiceContext<{}>,\n DatabaseHandlerContext,\n DatabaseRequestStorage,\n TLinkedFragments & { _fragno_internal: InternalFragmentInstance }\n >,\n schema,\n namespace,\n );\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,aACd,QACA,WAsCA;AACA,SAYE,YAaG;AAmBH,SAAO,IAAI,kCAlBiB,QAAQ,mBAClC,qBACC,EAAE,QAAQ,cAAc;AAGvB,UAAO,YAAY,oBAAoB,CACpC,WAAW,OAAa,CACxB,YAAY,QAA0C,CACtD,OAAO;IAEb,EAkCC,QACA,UACD"}
1
+ {"version":3,"file":"with-database.js","names":[],"sources":["../src/with-database.ts"],"sourcesContent":["import type { AnySchema } from \"./schema/create\";\nimport type {\n RequestThisContext,\n FragnoPublicConfig,\n AnyFragnoInstantiatedFragment,\n} from \"@fragno-dev/core\";\nimport { FragmentDefinitionBuilder, instantiate } from \"@fragno-dev/core\";\nimport {\n DatabaseFragmentDefinitionBuilder,\n type DatabaseServiceContext,\n type DatabaseHandlerContext,\n type ImplicitDatabaseDependencies,\n type FragnoPublicConfigWithDatabase,\n type DatabaseRequestStorage,\n} from \"./db-fragment-definition-builder\";\nimport { internalFragmentDef, type InternalFragmentInstance } from \"./fragments/internal-fragment\";\nimport { internalFragmentRoutes } from \"./fragments/internal-fragment.routes\";\nimport type { HooksMap } from \"./hooks/hooks\";\nimport { resolveDatabaseAdapter } from \"./util/default-database-adapter\";\n\nfunction shouldExposeOutboxRoutes(\n options: FragnoPublicConfigWithDatabase,\n schema: AnySchema,\n): boolean {\n const adapter = resolveDatabaseAdapter(options, schema) as { outbox?: { enabled?: boolean } };\n return adapter.outbox?.enabled ?? false;\n}\n\n/**\n * Helper to add database support to a fragment builder.\n * Automatically links the internal fragment and adds ImplicitDatabaseDependencies to the TDeps type.\n *\n * @example\n * ```typescript\n * // With .extend() - recommended\n * const def = defineFragment(\"my-frag\")\n * .extend(withDatabase(mySchema))\n * .withDependencies(...)\n * .build();\n *\n * // Or as a function wrapper\n * const def = withDatabase(mySchema)(defineFragment(\"my-frag\"))\n * .withDependencies(...)\n * .build();\n * ```\n */\nexport function withDatabase<TSchema extends AnySchema>(\n schema: TSchema,\n): <\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n TServiceThisContext extends RequestThisContext,\n THandlerThisContext extends RequestThisContext,\n TRequestStorage,\n TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment>,\n>(\n builder: FragmentDefinitionBuilder<\n TConfig,\n FragnoPublicConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n TServiceThisContext,\n THandlerThisContext,\n TRequestStorage,\n TLinkedFragments\n >,\n) => DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps & ImplicitDatabaseDependencies<TSchema>,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n HooksMap,\n DatabaseServiceContext<HooksMap>,\n DatabaseHandlerContext,\n TLinkedFragments & { _fragno_internal: InternalFragmentInstance }\n> {\n return <\n TConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n TServiceThisContext extends RequestThisContext,\n THandlerThisContext extends RequestThisContext,\n TRequestStorage,\n TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment>,\n >(\n builder: FragmentDefinitionBuilder<\n TConfig,\n FragnoPublicConfig,\n TDeps,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n TServiceThisContext,\n THandlerThisContext,\n TRequestStorage,\n TLinkedFragments\n >,\n ) => {\n const builderWithInternal = builder.withLinkedFragment(\n \"_fragno_internal\",\n ({ config, options }) => {\n const internalRoutes = shouldExposeOutboxRoutes(\n options as FragnoPublicConfigWithDatabase,\n schema,\n )\n ? [internalFragmentRoutes]\n : [];\n\n // Cast is safe: by the time this callback is invoked during fragment instantiation,\n // the options will be FragnoPublicConfigWithDatabase (enforced by DatabaseFragmentDefinitionBuilder)\n return instantiate(internalFragmentDef)\n .withConfig(config as {})\n .withOptions({\n ...(options as FragnoPublicConfigWithDatabase),\n databaseNamespace: null,\n })\n .withRoutes(internalRoutes)\n .build();\n },\n );\n\n // Cast is safe: we're creating a DatabaseFragmentDefinitionBuilder which internally uses\n // FragnoPublicConfigWithDatabase, but the input builder uses FragnoPublicConfig.\n // The database builder's build() method will enforce FragnoPublicConfigWithDatabase at the end.\n // We also add ImplicitDatabaseDependencies to TDeps so they're available in service constructors.\n // Note: We discard TRequestStorage here because database fragments manage their own storage (DatabaseRequestStorage).\n // We set TServiceThisContext to DatabaseServiceContext (restricted) and THandlerThisContext to DatabaseHandlerContext (full).\n return new DatabaseFragmentDefinitionBuilder<\n TSchema,\n TConfig,\n TDeps & ImplicitDatabaseDependencies<TSchema>,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n {}, // Start with empty hooks, provideHooks() will update this\n DatabaseServiceContext<{}>,\n DatabaseHandlerContext,\n TLinkedFragments & { _fragno_internal: InternalFragmentInstance }\n >(\n builderWithInternal as unknown as FragmentDefinitionBuilder<\n TConfig,\n FragnoPublicConfigWithDatabase,\n TDeps & ImplicitDatabaseDependencies<TSchema>,\n TBaseServices,\n TServices,\n TServiceDeps,\n TPrivateServices,\n DatabaseServiceContext<{}>,\n DatabaseHandlerContext,\n DatabaseRequestStorage,\n TLinkedFragments & { _fragno_internal: InternalFragmentInstance }\n >,\n schema,\n );\n };\n}\n"],"mappings":";;;;;;;AAoBA,SAAS,yBACP,SACA,QACS;AAET,QADgB,uBAAuB,SAAS,OAAO,CACxC,QAAQ,WAAW;;;;;;;;;;;;;;;;;;;;AAqBpC,SAAgB,aACd,QAsCA;AACA,SAYE,YAaG;AA8BH,SAAO,IAAI,kCA7BiB,QAAQ,mBAClC,qBACC,EAAE,QAAQ,cAAc;GACvB,MAAM,iBAAiB,yBACrB,SACA,OACD,GACG,CAAC,uBAAuB,GACxB,EAAE;AAIN,UAAO,YAAY,oBAAoB,CACpC,WAAW,OAAa,CACxB,YAAY;IACX,GAAI;IACJ,mBAAmB;IACpB,CAAC,CACD,WAAW,eAAe,CAC1B,OAAO;IAEb,EAkCC,OACD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fragno-dev/db",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -48,25 +48,25 @@
48
48
  "types": "./dist/adapters/adapters.d.ts",
49
49
  "default": "./dist/adapters/adapters.js"
50
50
  },
51
- "./adapters/kysely": {
52
- "development": "./src/adapters/kysely/kysely-adapter.ts",
53
- "types": "./dist/adapters/kysely/kysely-adapter.d.ts",
54
- "default": "./dist/adapters/kysely/kysely-adapter.js"
51
+ "./adapters/in-memory": {
52
+ "development": "./src/adapters/in-memory/index.ts",
53
+ "types": "./dist/adapters/in-memory/index.d.ts",
54
+ "default": "./dist/adapters/in-memory/index.js"
55
55
  },
56
- "./adapters/drizzle": {
57
- "development": "./src/adapters/drizzle/drizzle-adapter.ts",
58
- "types": "./dist/adapters/drizzle/drizzle-adapter.d.ts",
59
- "default": "./dist/adapters/drizzle/drizzle-adapter.js"
56
+ "./adapters/sql": {
57
+ "development": "./src/adapters/sql/index.ts",
58
+ "types": "./dist/adapters/sql/index.d.ts",
59
+ "default": "./dist/adapters/sql/index.js"
60
60
  },
61
- "./adapters/drizzle/generate": {
62
- "development": "./src/adapters/drizzle/generate.ts",
63
- "types": "./dist/adapters/drizzle/generate.d.ts",
64
- "default": "./dist/adapters/drizzle/generate.js"
61
+ "./schema-output/drizzle": {
62
+ "development": "./src/schema-output/drizzle.ts",
63
+ "types": "./dist/schema-output/drizzle.d.ts",
64
+ "default": "./dist/schema-output/drizzle.js"
65
65
  },
66
- "./adapters/generic-sql": {
67
- "development": "./src/adapters/generic-sql/generic-sql-adapter.ts",
68
- "types": "./dist/adapters/generic-sql/generic-sql-adapter.d.ts",
69
- "default": "./dist/adapters/generic-sql/generic-sql-adapter.js"
66
+ "./schema-output/prisma": {
67
+ "development": "./src/schema-output/prisma.ts",
68
+ "types": "./dist/schema-output/prisma.d.ts",
69
+ "default": "./dist/schema-output/prisma.js"
70
70
  },
71
71
  "./unit-of-work": {
72
72
  "development": "./src/query/unit-of-work/unit-of-work.ts",
@@ -88,6 +88,16 @@
88
88
  "types": "./dist/db-fragment-definition-builder.d.ts",
89
89
  "default": "./dist/db-fragment-definition-builder.js"
90
90
  },
91
+ "./dispatchers/node": {
92
+ "development": "./src/dispatchers/node/index.ts",
93
+ "types": "./dist/dispatchers/node/index.d.ts",
94
+ "default": "./dist/dispatchers/node/index.js"
95
+ },
96
+ "./dispatchers/cloudflare-do": {
97
+ "development": "./src/dispatchers/cloudflare-do/index.ts",
98
+ "types": "./dist/dispatchers/cloudflare-do/index.d.ts",
99
+ "default": "./dist/dispatchers/cloudflare-do/index.js"
100
+ },
91
101
  "./generation-engine": {
92
102
  "development": "./src/migration-engine/generation-engine.ts",
93
103
  "types": "./dist/migration-engine/generation-engine.d.ts",
@@ -95,22 +105,22 @@
95
105
  }
96
106
  },
97
107
  "devDependencies": {
98
- "@electric-sql/pglite": "^0.3.10",
108
+ "@electric-sql/pglite": "^0.3.15",
99
109
  "@libsql/client": "^0.15.15",
100
110
  "@types/better-sqlite3": "^7.6.13",
101
- "@types/node": "^22",
111
+ "@types/node": "^22.19.7",
102
112
  "@vitest/coverage-istanbul": "^3.2.4",
103
- "better-sqlite3": "^12.5.0",
104
- "drizzle-kit": "^0.31.5",
105
- "drizzle-orm": "^0.44.6",
113
+ "better-sqlite3": "^12.6.2",
114
+ "drizzle-kit": "^0.31.8",
115
+ "drizzle-orm": "^0.44.7",
106
116
  "kysely-pglite": "^0.6.1",
107
- "mysql2": "^3.11.5",
117
+ "mysql2": "^3.16.1",
108
118
  "sqlocal": "^0.15.2",
109
119
  "vitest": "^3.2.4",
110
- "zod": "^4.1.12",
111
- "@fragno-dev/core": "0.1.11",
112
- "@fragno-private/vitest-config": "0.0.0",
113
- "@fragno-private/typescript-config": "0.0.1"
120
+ "zod": "^4.3.5",
121
+ "@fragno-dev/core": "0.2.0",
122
+ "@fragno-private/typescript-config": "0.0.1",
123
+ "@fragno-private/vitest-config": "0.0.0"
114
124
  },
115
125
  "repository": {
116
126
  "type": "git",
@@ -121,7 +131,12 @@
121
131
  "license": "MIT",
122
132
  "dependencies": {
123
133
  "@paralleldrive/cuid2": "^2.3.1",
124
- "kysely": "^0.28.7"
134
+ "@standard-schema/spec": "^1.1.0",
135
+ "kysely": "^0.28.10",
136
+ "superjson": "^2.2.1"
137
+ },
138
+ "optionalDependencies": {
139
+ "better-sqlite3": "^12.6.2"
125
140
  },
126
141
  "peerDependencies": {
127
142
  "drizzle-orm": "^0.44.6"