@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
@@ -0,0 +1,275 @@
1
+ import type { Condition } from "../../query/condition-builder";
2
+ import { ReferenceSubquery, resolveFragnoIdValue } from "../../query/value-encoding";
3
+ import { isDbNow } from "../../query/db-now";
4
+ import type { AnyColumn, AnyTable } from "../../schema/create";
5
+ import { Column, FragnoId, FragnoReference } from "../../schema/create";
6
+ import type { InMemoryNamespaceStore, InMemoryRow } from "./store";
7
+ import { normalizeIndexValue } from "./store";
8
+ import { resolveReferenceSubquery } from "./reference-resolution";
9
+ import { compareNormalizedValues } from "./value-comparison";
10
+ import type { NamingResolver } from "../../naming/sql-naming";
11
+
12
+ const isNullish = (value: unknown): value is null | undefined =>
13
+ value === null || value === undefined;
14
+
15
+ const resolveReferenceValue = (
16
+ value: unknown,
17
+ column: AnyColumn,
18
+ table: AnyTable,
19
+ namespaceStore?: InMemoryNamespaceStore,
20
+ resolver?: NamingResolver,
21
+ ): unknown => {
22
+ if (value instanceof FragnoReference) {
23
+ return value.internalId;
24
+ }
25
+
26
+ if (value instanceof FragnoId) {
27
+ if (value.internalId !== undefined) {
28
+ return value.internalId;
29
+ }
30
+ return resolveReferenceValue(value.externalId, column, table, namespaceStore, resolver);
31
+ }
32
+
33
+ if (value instanceof ReferenceSubquery) {
34
+ if (!namespaceStore) {
35
+ throw new Error("In-memory condition evaluation requires a namespace store.");
36
+ }
37
+ return resolveReferenceSubquery(namespaceStore, value, resolver);
38
+ }
39
+
40
+ if (typeof value === "string") {
41
+ if (!namespaceStore) {
42
+ throw new Error("In-memory condition evaluation requires a namespace store.");
43
+ }
44
+
45
+ const relation = Object.values(table.relations).find((rel) =>
46
+ rel.on.some(([localCol]) => localCol === column.name),
47
+ );
48
+ if (!relation) {
49
+ throw new Error(`Missing relation for reference column "${column.name}".`);
50
+ }
51
+
52
+ return resolveReferenceSubquery(
53
+ namespaceStore,
54
+ new ReferenceSubquery(relation.table, value),
55
+ resolver,
56
+ );
57
+ }
58
+
59
+ return resolveFragnoIdValue(value, column);
60
+ };
61
+
62
+ const resolveComparisonValue = (
63
+ value: unknown,
64
+ column: AnyColumn,
65
+ table: AnyTable,
66
+ row: InMemoryRow,
67
+ namespaceStore?: InMemoryNamespaceStore,
68
+ resolver?: NamingResolver,
69
+ now: () => Date = () => new Date(),
70
+ ): { value: unknown; column: AnyColumn } => {
71
+ if (value instanceof Column) {
72
+ const columnName = resolver ? resolver.getColumnName(table.name, value.name) : value.name;
73
+ return { value: row[columnName], column: value };
74
+ }
75
+
76
+ if (isDbNow(value)) {
77
+ return { value: now(), column };
78
+ }
79
+
80
+ if (column.role === "reference") {
81
+ return {
82
+ value: resolveReferenceValue(value, column, table, namespaceStore, resolver),
83
+ column,
84
+ };
85
+ }
86
+
87
+ return { value: resolveFragnoIdValue(value, column), column };
88
+ };
89
+
90
+ const normalizeLikeValue = (value: unknown, column: AnyColumn): string | null => {
91
+ const normalized = normalizeIndexValue(value, column);
92
+ if (normalized === null || normalized === undefined) {
93
+ return null;
94
+ }
95
+ if (normalized instanceof Buffer) {
96
+ return normalized.toString("hex");
97
+ }
98
+ return String(normalized);
99
+ };
100
+
101
+ const compareNormalized = (left: unknown, right: unknown): number =>
102
+ compareNormalizedValues(left, right);
103
+
104
+ export const evaluateCondition = (
105
+ condition: Condition | boolean,
106
+ table: AnyTable,
107
+ row: InMemoryRow,
108
+ namespaceStore?: InMemoryNamespaceStore,
109
+ resolver?: NamingResolver,
110
+ now: () => Date = () => new Date(),
111
+ ): boolean => {
112
+ if (typeof condition === "boolean") {
113
+ return condition;
114
+ }
115
+
116
+ switch (condition.type) {
117
+ case "and": {
118
+ for (const item of condition.items) {
119
+ if (!evaluateCondition(item, table, row, namespaceStore, resolver, now)) {
120
+ return false;
121
+ }
122
+ }
123
+ return true;
124
+ }
125
+ case "or": {
126
+ for (const item of condition.items) {
127
+ if (evaluateCondition(item, table, row, namespaceStore, resolver, now)) {
128
+ return true;
129
+ }
130
+ }
131
+ return false;
132
+ }
133
+ case "not":
134
+ return !evaluateCondition(condition.item, table, row, namespaceStore, resolver, now);
135
+ case "compare":
136
+ break;
137
+ default: {
138
+ const exhaustiveCheck: never = condition;
139
+ throw new Error(`Unsupported condition type: ${JSON.stringify(exhaustiveCheck)}`);
140
+ }
141
+ }
142
+
143
+ const leftColumn = condition.a;
144
+ const leftColumnName = resolver
145
+ ? resolver.getColumnName(table.name, leftColumn.name)
146
+ : leftColumn.name;
147
+ const leftValue = row[leftColumnName];
148
+ const right = resolveComparisonValue(
149
+ condition.b,
150
+ leftColumn,
151
+ table,
152
+ row,
153
+ namespaceStore,
154
+ resolver,
155
+ now,
156
+ );
157
+
158
+ const op = condition.operator;
159
+ const rightValue = right.value;
160
+
161
+ if (op === "is" || op === "is not") {
162
+ if (isNullish(rightValue)) {
163
+ const matches = isNullish(leftValue);
164
+ return op === "is" ? matches : !matches;
165
+ }
166
+
167
+ if (isNullish(leftValue)) {
168
+ return op === "is not";
169
+ }
170
+
171
+ const leftNormalized = normalizeIndexValue(leftValue, leftColumn);
172
+ const rightNormalized = normalizeIndexValue(rightValue, right.column);
173
+ const matches = compareNormalized(leftNormalized, rightNormalized) === 0;
174
+ return op === "is" ? matches : !matches;
175
+ }
176
+
177
+ if (isNullish(leftValue) || isNullish(rightValue)) {
178
+ return false;
179
+ }
180
+
181
+ if (op === "in" || op === "not in") {
182
+ if (!Array.isArray(rightValue)) {
183
+ throw new Error(`Operator "${op}" expects an array value.`);
184
+ }
185
+
186
+ const leftNormalized = normalizeIndexValue(leftValue, leftColumn);
187
+ let hasNull = false;
188
+ let hasMatch = false;
189
+
190
+ for (const item of rightValue) {
191
+ const resolved = resolveComparisonValue(
192
+ item,
193
+ leftColumn,
194
+ table,
195
+ row,
196
+ namespaceStore,
197
+ resolver,
198
+ now,
199
+ );
200
+ if (isNullish(resolved.value)) {
201
+ hasNull = true;
202
+ continue;
203
+ }
204
+ const normalized = normalizeIndexValue(resolved.value, leftColumn);
205
+ if (compareNormalized(leftNormalized, normalized) === 0) {
206
+ hasMatch = true;
207
+ break;
208
+ }
209
+ }
210
+
211
+ if (hasMatch) {
212
+ return op === "in";
213
+ }
214
+
215
+ if (hasNull) {
216
+ return false;
217
+ }
218
+
219
+ return op === "not in";
220
+ }
221
+
222
+ if (
223
+ op === "contains" ||
224
+ op === "starts with" ||
225
+ op === "ends with" ||
226
+ op === "not contains" ||
227
+ op === "not starts with" ||
228
+ op === "not ends with"
229
+ ) {
230
+ const leftLike = normalizeLikeValue(leftValue, leftColumn);
231
+ const rightLike = normalizeLikeValue(rightValue, right.column);
232
+
233
+ if (leftLike === null || rightLike === null) {
234
+ return false;
235
+ }
236
+
237
+ const leftText = leftLike.toLowerCase();
238
+ const rightText = rightLike.toLowerCase();
239
+ let matches = false;
240
+
241
+ if (op.includes("contains")) {
242
+ matches = leftText.includes(rightText);
243
+ } else if (op.includes("starts with")) {
244
+ matches = leftText.startsWith(rightText);
245
+ } else {
246
+ matches = leftText.endsWith(rightText);
247
+ }
248
+
249
+ if (op.startsWith("not ")) {
250
+ return !matches;
251
+ }
252
+ return matches;
253
+ }
254
+
255
+ const leftNormalized = normalizeIndexValue(leftValue, leftColumn);
256
+ const rightNormalized = normalizeIndexValue(rightValue, right.column);
257
+ const comparison = compareNormalized(leftNormalized, rightNormalized);
258
+
259
+ switch (op) {
260
+ case "=":
261
+ return comparison === 0;
262
+ case "!=":
263
+ return comparison !== 0;
264
+ case ">":
265
+ return comparison > 0;
266
+ case ">=":
267
+ return comparison >= 0;
268
+ case "<":
269
+ return comparison < 0;
270
+ case "<=":
271
+ return comparison <= 0;
272
+ default:
273
+ throw new Error(`Unsupported operator "${op}".`);
274
+ }
275
+ };
@@ -0,0 +1,20 @@
1
+ export class UniqueConstraintError extends Error {
2
+ constructor(message: string) {
3
+ super(message);
4
+ this.name = "UniqueConstraintError";
5
+ }
6
+ }
7
+
8
+ export class ForeignKeyConstraintError extends Error {
9
+ constructor(message: string) {
10
+ super(message);
11
+ this.name = "ForeignKeyConstraintError";
12
+ }
13
+ }
14
+
15
+ export class NotFoundError extends Error {
16
+ constructor(message: string) {
17
+ super(message);
18
+ this.name = "NotFoundError";
19
+ }
20
+ }
@@ -0,0 +1,277 @@
1
+ import { RequestContextStorage } from "@fragno-dev/core/internal/request-context-storage";
2
+ import {
3
+ fragnoDatabaseAdapterNameFakeSymbol,
4
+ fragnoDatabaseAdapterVersionFakeSymbol,
5
+ type DatabaseAdapter,
6
+ type DatabaseContextStorage,
7
+ } from "../adapters";
8
+ import type { AnySchema, AnyTable, FragnoId } from "../../schema/create";
9
+ import type { SimpleQueryInterface, TableToUpdateValues } from "../../query/simple-query-interface";
10
+ import {
11
+ resolveInMemoryAdapterOptions,
12
+ type InMemoryAdapterOptions,
13
+ type ResolvedInMemoryAdapterOptions,
14
+ } from "./options";
15
+ import { createInMemoryStore, ensureNamespaceStore } from "./store";
16
+ import {
17
+ createInMemoryUowCompiler,
18
+ createInMemoryUowExecutor,
19
+ InMemoryUowDecoder,
20
+ } from "./in-memory-uow";
21
+ import { UnitOfWork, type UnitOfWorkConfig } from "../../query/unit-of-work/unit-of-work";
22
+ import type { CursorResult } from "../../query/cursor";
23
+ import {
24
+ createNamingResolver,
25
+ suffixNamingStrategy,
26
+ type SqlNamingStrategy,
27
+ } from "../../naming/sql-naming";
28
+
29
+ class UpdateManySpecialBuilder<TTable extends AnyTable> {
30
+ #indexName?: string;
31
+ #condition?: unknown;
32
+ #setValues?: TableToUpdateValues<TTable>;
33
+
34
+ whereIndex(indexName: string, condition?: unknown): this {
35
+ this.#indexName = indexName;
36
+ this.#condition = condition;
37
+ return this;
38
+ }
39
+
40
+ set(values: TableToUpdateValues<TTable>): this {
41
+ this.#setValues = values;
42
+ return this;
43
+ }
44
+
45
+ getConfig() {
46
+ return {
47
+ indexName: this.#indexName,
48
+ condition: this.#condition,
49
+ setValues: this.#setValues,
50
+ };
51
+ }
52
+ }
53
+
54
+ const hasIdField = (record: unknown): record is { id: string | FragnoId } =>
55
+ record !== null && typeof record === "object" && "id" in record;
56
+
57
+ export type InMemoryUowConfig = UnitOfWorkConfig;
58
+
59
+ export class InMemoryAdapter implements DatabaseAdapter<InMemoryUowConfig> {
60
+ readonly options: ResolvedInMemoryAdapterOptions;
61
+ readonly namingStrategy: SqlNamingStrategy;
62
+
63
+ #contextStorage: RequestContextStorage<DatabaseContextStorage>;
64
+ #store = createInMemoryStore();
65
+ #schemaNamespaceMap = new WeakMap<AnySchema, string | null>();
66
+ #schemaByNamespace = new Map<string, { schema: AnySchema; namespace: string | null }>();
67
+
68
+ constructor(options: InMemoryAdapterOptions = {}) {
69
+ this.options = resolveInMemoryAdapterOptions(options);
70
+ this.namingStrategy = options.namingStrategy ?? suffixNamingStrategy;
71
+ this.#contextStorage = new RequestContextStorage();
72
+ }
73
+
74
+ get [fragnoDatabaseAdapterNameFakeSymbol](): string {
75
+ return "in-memory";
76
+ }
77
+
78
+ get [fragnoDatabaseAdapterVersionFakeSymbol](): number {
79
+ return 0;
80
+ }
81
+
82
+ get contextStorage(): RequestContextStorage<DatabaseContextStorage> {
83
+ return this.#contextStorage;
84
+ }
85
+
86
+ async getSchemaVersion(_namespace: string): Promise<string | undefined> {
87
+ return undefined;
88
+ }
89
+
90
+ async isConnectionHealthy(): Promise<boolean> {
91
+ return true;
92
+ }
93
+
94
+ async close(): Promise<void> {
95
+ return;
96
+ }
97
+
98
+ async reset(): Promise<void> {
99
+ this.#store.namespaces.clear();
100
+ for (const [namespaceKey, { schema, namespace }] of this.#schemaByNamespace) {
101
+ const resolver = createNamingResolver(schema, namespace, this.namingStrategy);
102
+ ensureNamespaceStore(this.#store, namespaceKey, schema, resolver);
103
+ }
104
+ }
105
+
106
+ createQueryEngine<T extends AnySchema>(
107
+ schema: T,
108
+ namespace: string | null,
109
+ ): SimpleQueryInterface<T, InMemoryUowConfig> {
110
+ this.#schemaNamespaceMap.set(schema, namespace);
111
+ const namespaceKey = namespace ?? schema.name;
112
+ this.#schemaByNamespace.set(namespaceKey, { schema, namespace });
113
+ const resolverFactory = (schemaForResolver: AnySchema, namespaceForResolver: string | null) =>
114
+ createNamingResolver(schemaForResolver, namespaceForResolver, this.namingStrategy);
115
+ const resolver = resolverFactory(schema, namespace);
116
+ ensureNamespaceStore(this.#store, namespaceKey, schema, resolver);
117
+
118
+ const compiler = createInMemoryUowCompiler();
119
+ const executor = createInMemoryUowExecutor(this.#store, this.options, resolverFactory);
120
+ const decoder = new InMemoryUowDecoder(resolverFactory);
121
+
122
+ const createUow = (opts?: { name?: string; config?: UnitOfWorkConfig }) =>
123
+ new UnitOfWork(
124
+ compiler,
125
+ executor,
126
+ decoder,
127
+ opts?.name,
128
+ opts?.config,
129
+ this.#schemaNamespaceMap,
130
+ ).forSchema(schema);
131
+
132
+ const queryEngine = {
133
+ now: async () => this.options.clock.now(),
134
+ async find(tableName, builderFn) {
135
+ const uow = createUow();
136
+ uow.find(tableName, builderFn);
137
+ const [result]: unknown[][] = await uow.executeRetrieve();
138
+ return result ?? [];
139
+ },
140
+
141
+ async findWithCursor(tableName, builderFn) {
142
+ const uow = createUow().findWithCursor(tableName, builderFn);
143
+ const [result] = await uow.executeRetrieve();
144
+ return result as CursorResult<unknown>;
145
+ },
146
+
147
+ async findFirst(tableName, builderFn) {
148
+ const uow = createUow();
149
+ if (builderFn) {
150
+ uow.find(tableName, (b) => {
151
+ builderFn(b);
152
+ return b.pageSize(1);
153
+ });
154
+ } else {
155
+ uow.find(tableName, (b) => b.whereIndex("primary").pageSize(1));
156
+ }
157
+ const [result]: unknown[][] = await uow.executeRetrieve();
158
+ return result?.[0] ?? null;
159
+ },
160
+
161
+ async create(tableName, values) {
162
+ const uow = createUow();
163
+ uow.create(tableName, values);
164
+ const { success } = await uow.executeMutations();
165
+ if (!success) {
166
+ throw new Error("Failed to create record");
167
+ }
168
+
169
+ const createdId = uow.getCreatedIds()[0];
170
+ if (!createdId) {
171
+ throw new Error("Failed to get created ID");
172
+ }
173
+ return createdId;
174
+ },
175
+
176
+ async createMany(tableName, valuesArray) {
177
+ const uow = createUow();
178
+ for (const values of valuesArray) {
179
+ uow.create(tableName, values);
180
+ }
181
+ const { success } = await uow.executeMutations();
182
+ if (!success) {
183
+ throw new Error("Failed to create records");
184
+ }
185
+ return uow.getCreatedIds();
186
+ },
187
+
188
+ async update(tableName, id, builderFn) {
189
+ const uow = createUow();
190
+ uow.update(tableName, id, builderFn);
191
+ const { success } = await uow.executeMutations();
192
+ if (!success) {
193
+ throw new Error("Failed to update record (version conflict or record not found)");
194
+ }
195
+ },
196
+
197
+ async updateMany(tableName, builderFn) {
198
+ const table = schema.tables[tableName];
199
+ if (!table) {
200
+ throw new Error(`Table ${tableName} not found in schema`);
201
+ }
202
+
203
+ const specialBuilder = new UpdateManySpecialBuilder<typeof table>();
204
+ builderFn(specialBuilder);
205
+ const { indexName, condition, setValues } = specialBuilder.getConfig();
206
+
207
+ if (!indexName) {
208
+ throw new Error("whereIndex() must be called in updateMany");
209
+ }
210
+ if (!setValues) {
211
+ throw new Error("set() must be called in updateMany");
212
+ }
213
+
214
+ const findUow = createUow();
215
+ findUow.find(tableName, (b) => {
216
+ if (condition !== undefined && condition !== null) {
217
+ return b.whereIndex(indexName as never, condition as never);
218
+ }
219
+ return b.whereIndex(indexName as never);
220
+ });
221
+ const [records]: unknown[][] = await findUow.executeRetrieve();
222
+
223
+ if (!records || records.length === 0) {
224
+ return;
225
+ }
226
+
227
+ const updateUow = createUow();
228
+ for (const record of records) {
229
+ if (!hasIdField(record)) {
230
+ throw new Error("Record missing id field");
231
+ }
232
+ updateUow.update(tableName, record.id, (b) => b.set(setValues).check());
233
+ }
234
+ const { success } = await updateUow.executeMutations();
235
+ if (!success) {
236
+ throw new Error("Failed to update records (version conflict)");
237
+ }
238
+ },
239
+
240
+ async delete(tableName, id, builderFn) {
241
+ const uow = createUow();
242
+ uow.delete(tableName, id, builderFn);
243
+ const { success } = await uow.executeMutations();
244
+ if (!success) {
245
+ throw new Error("Failed to delete record (version conflict or record not found)");
246
+ }
247
+ },
248
+
249
+ async deleteMany(tableName, builderFn) {
250
+ const findUow = createUow();
251
+ findUow.find(tableName, builderFn);
252
+ const [records]: unknown[][] = await findUow.executeRetrieve();
253
+
254
+ if (!records || records.length === 0) {
255
+ return;
256
+ }
257
+
258
+ const deleteUow = createUow();
259
+ for (const record of records) {
260
+ if (!hasIdField(record)) {
261
+ throw new Error("Record missing id field");
262
+ }
263
+ deleteUow.delete(tableName, record.id);
264
+ }
265
+ const { success } = await deleteUow.executeMutations();
266
+ if (!success) {
267
+ throw new Error("Failed to delete records (version conflict)");
268
+ }
269
+ },
270
+
271
+ createUnitOfWork(name, config) {
272
+ return createUow({ name, config });
273
+ },
274
+ } as SimpleQueryInterface<T, InMemoryUowConfig>;
275
+ return queryEngine;
276
+ }
277
+ }