@fragno-dev/db 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. package/.turbo/turbo-build.log +327 -160
  2. package/CHANGELOG.md +74 -0
  3. package/README.md +24 -0
  4. package/dist/adapters/adapters.d.ts +1 -1
  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/generic-sql-adapter.d.ts +0 -3
  8. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/generic-sql-adapter.js +11 -12
  10. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +46 -6
  12. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  13. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -1
  14. package/dist/adapters/generic-sql/migration/dialect/mysql.js +1 -1
  15. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  16. package/dist/adapters/generic-sql/migration/dialect/postgres.js +1 -1
  17. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  18. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +185 -19
  19. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  20. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -1
  21. package/dist/adapters/generic-sql/migration/executor.js +30 -3
  22. package/dist/adapters/generic-sql/migration/executor.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 +3 -3
  25. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  26. package/dist/adapters/generic-sql/migration/sql-generator.js +1 -1
  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 +1 -1
  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.map +1 -1
  31. package/dist/adapters/generic-sql/query/db-now-sql.js +27 -0
  32. package/dist/adapters/generic-sql/query/db-now-sql.js.map +1 -0
  33. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +9 -6
  34. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  35. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/sql-query-compiler.js +37 -9
  37. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  38. package/dist/adapters/generic-sql/query/where-builder.js +24 -20
  39. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  40. package/dist/adapters/generic-sql/uow-decoder.js +1 -1
  41. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  42. package/dist/adapters/generic-sql/uow-encoder.js +8 -9
  43. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  44. package/dist/adapters/in-memory/condition-evaluator.js +10 -6
  45. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -1
  46. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -1
  47. package/dist/adapters/in-memory/in-memory-adapter.js +45 -25
  48. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -1
  49. package/dist/adapters/in-memory/in-memory-uow.js +236 -13
  50. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -1
  51. package/dist/adapters/in-memory/options.d.ts +2 -0
  52. package/dist/adapters/in-memory/options.d.ts.map +1 -1
  53. package/dist/adapters/in-memory/options.js +3 -2
  54. package/dist/adapters/in-memory/options.js.map +1 -1
  55. package/dist/adapters/in-memory/reference-resolution.js.map +1 -1
  56. package/dist/adapters/in-memory/store.js +1 -1
  57. package/dist/adapters/in-memory/store.js.map +1 -1
  58. package/dist/adapters/shared/from-unit-of-work-compiler.js +51 -24
  59. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  60. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  61. package/dist/browser/adapters/adapters.d.ts +61 -0
  62. package/dist/browser/adapters/adapters.d.ts.map +1 -0
  63. package/dist/browser/adapters/generic-sql/migration/executor.d.ts +15 -0
  64. package/dist/browser/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  65. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  66. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  67. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts +11 -0
  68. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  69. package/dist/browser/adapters/in-memory/in-memory-adapter.d.ts +5 -0
  70. package/dist/browser/adapters/in-memory/index.d.ts +2 -0
  71. package/dist/browser/adapters/in-memory/options.d.ts +1 -0
  72. package/dist/browser/db-fragment-definition-builder.d.ts +237 -0
  73. package/dist/browser/db-fragment-definition-builder.d.ts.map +1 -0
  74. package/dist/browser/durable-hooks.d.ts +3 -0
  75. package/dist/browser/fragments/internal-fragment.d.ts +317 -0
  76. package/dist/browser/fragments/internal-fragment.d.ts.map +1 -0
  77. package/dist/browser/fragments/internal-fragment.schema.d.ts +1 -0
  78. package/dist/browser/hooks/durable-hooks-logger.d.ts +10 -0
  79. package/dist/browser/hooks/durable-hooks-logger.d.ts.map +1 -0
  80. package/dist/browser/hooks/hooks.d.ts +146 -0
  81. package/dist/browser/hooks/hooks.d.ts.map +1 -0
  82. package/dist/browser/id.js +1 -0
  83. package/dist/browser/internal/adapter-registry.d.ts +4 -0
  84. package/dist/browser/internal/outbox-state.d.ts +2 -0
  85. package/dist/browser/mod.d.ts +15 -0
  86. package/dist/browser/mod.d.ts.map +1 -0
  87. package/dist/browser/mod.js +17 -0
  88. package/dist/browser/mod.js.map +1 -0
  89. package/dist/browser/mod2.d.ts +48 -0
  90. package/dist/browser/mod2.d.ts.map +1 -0
  91. package/dist/browser/naming/sql-naming.d.ts +19 -0
  92. package/dist/browser/naming/sql-naming.d.ts.map +1 -0
  93. package/dist/browser/outbox/outbox.d.ts +21 -0
  94. package/dist/browser/outbox/outbox.d.ts.map +1 -0
  95. package/dist/browser/query/column-defaults.js +1 -0
  96. package/dist/browser/query/condition-builder.d.ts +44 -0
  97. package/dist/browser/query/condition-builder.d.ts.map +1 -0
  98. package/dist/browser/query/condition-builder.js +97 -0
  99. package/dist/browser/query/condition-builder.js.map +1 -0
  100. package/dist/browser/query/cursor.d.ts +105 -0
  101. package/dist/browser/query/cursor.d.ts.map +1 -0
  102. package/dist/browser/query/cursor.js +150 -0
  103. package/dist/browser/query/cursor.js.map +1 -0
  104. package/dist/browser/query/db-now.d.ts +22 -0
  105. package/dist/browser/query/db-now.d.ts.map +1 -0
  106. package/dist/browser/query/db-now.js +33 -0
  107. package/dist/browser/query/db-now.js.map +1 -0
  108. package/dist/browser/query/orm/orm.d.ts +18 -0
  109. package/dist/browser/query/orm/orm.d.ts.map +1 -0
  110. package/dist/browser/query/simple-query-interface.d.ts +108 -0
  111. package/dist/browser/query/simple-query-interface.d.ts.map +1 -0
  112. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts +423 -0
  113. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  114. package/dist/browser/query/unit-of-work/execute-unit-of-work.js +507 -0
  115. package/dist/browser/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  116. package/dist/browser/query/unit-of-work/retry-policy.d.ts +23 -0
  117. package/dist/browser/query/unit-of-work/retry-policy.d.ts.map +1 -0
  118. package/dist/browser/query/unit-of-work/retry-policy.js +40 -0
  119. package/dist/browser/query/unit-of-work/retry-policy.js.map +1 -0
  120. package/dist/browser/query/unit-of-work/unit-of-work.d.ts +703 -0
  121. package/dist/browser/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  122. package/dist/browser/query/unit-of-work/unit-of-work.js +1206 -0
  123. package/dist/browser/query/unit-of-work/unit-of-work.js.map +1 -0
  124. package/dist/browser/query/value-encoding.js +38 -0
  125. package/dist/browser/query/value-encoding.js.map +1 -0
  126. package/dist/browser/schema/create.d.ts +326 -0
  127. package/dist/browser/schema/create.d.ts.map +1 -0
  128. package/dist/browser/schema/create.js +89 -0
  129. package/dist/browser/schema/create.js.map +1 -0
  130. package/dist/browser/schema/generate-id.js +28 -0
  131. package/dist/browser/schema/generate-id.js.map +1 -0
  132. package/dist/browser/shared/providers.d.ts +6 -0
  133. package/dist/browser/shared/providers.d.ts.map +1 -0
  134. package/dist/browser/sql-driver/connection/connection-provider.d.ts +13 -0
  135. package/dist/browser/sql-driver/connection/connection-provider.d.ts.map +1 -0
  136. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  137. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  138. package/dist/browser/sql-driver/driver/runtime-driver.d.ts +23 -0
  139. package/dist/browser/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  140. package/dist/browser/sql-driver/query-executor/plugin.d.ts +17 -0
  141. package/dist/browser/sql-driver/query-executor/plugin.d.ts.map +1 -0
  142. package/dist/browser/sql-driver/query-executor/query-executor.d.ts +36 -0
  143. package/dist/browser/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  144. package/dist/browser/sql-driver/sql-driver-adapter.d.ts +29 -0
  145. package/dist/browser/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  146. package/dist/browser/sql-driver/sql-driver.d.ts +38 -0
  147. package/dist/browser/sql-driver/sql-driver.d.ts.map +1 -0
  148. package/dist/browser/sync/commands.d.ts +15 -0
  149. package/dist/browser/sync/commands.d.ts.map +1 -0
  150. package/dist/browser/sync/commands.js +27 -0
  151. package/dist/browser/sync/commands.js.map +1 -0
  152. package/dist/browser/sync/types.d.ts +63 -0
  153. package/dist/browser/sync/types.d.ts.map +1 -0
  154. package/dist/browser/util/types.d.ts +8 -0
  155. package/dist/browser/util/types.d.ts.map +1 -0
  156. package/dist/browser/with-database.d.ts +29 -0
  157. package/dist/browser/with-database.d.ts.map +1 -0
  158. package/dist/client.d.ts +4 -0
  159. package/dist/client.js +5 -0
  160. package/dist/db-fragment-definition-builder.d.ts +85 -28
  161. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  162. package/dist/db-fragment-definition-builder.js +374 -46
  163. package/dist/db-fragment-definition-builder.js.map +1 -1
  164. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts +20 -0
  165. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts.map +1 -0
  166. package/dist/dispatchers/cloudflare-do/dispatcher.js +147 -0
  167. package/dist/dispatchers/cloudflare-do/dispatcher.js.map +1 -0
  168. package/dist/dispatchers/cloudflare-do/index.d.ts +5 -20
  169. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -1
  170. package/dist/dispatchers/cloudflare-do/index.js +23 -55
  171. package/dist/dispatchers/cloudflare-do/index.js.map +1 -1
  172. package/dist/dispatchers/node/dispatcher.d.ts +14 -0
  173. package/dist/dispatchers/node/dispatcher.d.ts.map +1 -0
  174. package/dist/dispatchers/node/dispatcher.js +80 -0
  175. package/dist/dispatchers/node/dispatcher.js.map +1 -0
  176. package/dist/dispatchers/node/index.d.ts +5 -10
  177. package/dist/dispatchers/node/index.d.ts.map +1 -1
  178. package/dist/dispatchers/node/index.js +21 -53
  179. package/dist/dispatchers/node/index.js.map +1 -1
  180. package/dist/durable-hooks.d.ts +31 -0
  181. package/dist/durable-hooks.d.ts.map +1 -0
  182. package/dist/durable-hooks.js +23 -0
  183. package/dist/durable-hooks.js.map +1 -0
  184. package/dist/fragments/internal-fragment.d.ts +128 -27
  185. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  186. package/dist/fragments/internal-fragment.js +125 -78
  187. package/dist/fragments/internal-fragment.js.map +1 -1
  188. package/dist/fragments/internal-fragment.routes.js +138 -3
  189. package/dist/fragments/internal-fragment.routes.js.map +1 -1
  190. package/dist/fragments/internal-fragment.schema.d.ts +7 -1
  191. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -1
  192. package/dist/fragments/internal-fragment.schema.js +18 -1
  193. package/dist/fragments/internal-fragment.schema.js.map +1 -1
  194. package/dist/hooks/durable-hooks-logger.d.ts +10 -0
  195. package/dist/hooks/durable-hooks-logger.d.ts.map +1 -0
  196. package/dist/hooks/durable-hooks-logger.js +75 -0
  197. package/dist/hooks/durable-hooks-logger.js.map +1 -0
  198. package/dist/hooks/durable-hooks-processor.d.ts +1 -14
  199. package/dist/hooks/durable-hooks-processor.js +58 -10
  200. package/dist/hooks/durable-hooks-processor.js.map +1 -1
  201. package/dist/hooks/durable-hooks-runtime.js +44 -0
  202. package/dist/hooks/durable-hooks-runtime.js.map +1 -0
  203. package/dist/hooks/hooks.d.ts +60 -2
  204. package/dist/hooks/hooks.d.ts.map +1 -1
  205. package/dist/hooks/hooks.js +214 -53
  206. package/dist/hooks/hooks.js.map +1 -1
  207. package/dist/id.d.ts +2 -2
  208. package/dist/id.js +2 -2
  209. package/dist/internal/adapter-registry.d.ts +11 -0
  210. package/dist/internal/adapter-registry.d.ts.map +1 -0
  211. package/dist/internal/adapter-registry.js +135 -0
  212. package/dist/internal/adapter-registry.js.map +1 -0
  213. package/dist/internal/outbox-state.d.ts +2 -0
  214. package/dist/internal/outbox-state.js +26 -0
  215. package/dist/internal/outbox-state.js.map +1 -0
  216. package/dist/migration-engine/auto-from-schema.d.ts +33 -0
  217. package/dist/migration-engine/auto-from-schema.d.ts.map +1 -0
  218. package/dist/migration-engine/auto-from-schema.js +210 -27
  219. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  220. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  221. package/dist/migration-engine/generation-engine.js +17 -5
  222. package/dist/migration-engine/generation-engine.js.map +1 -1
  223. package/dist/migration-engine/shared.d.ts +113 -0
  224. package/dist/migration-engine/shared.d.ts.map +1 -0
  225. package/dist/migration-engine/shared.js.map +1 -1
  226. package/dist/mod.d.ts +12 -11
  227. package/dist/mod.d.ts.map +1 -1
  228. package/dist/mod.js +10 -10
  229. package/dist/mod.js.map +1 -1
  230. package/dist/naming/sql-naming.d.ts.map +1 -1
  231. package/dist/naming/sql-naming.js.map +1 -1
  232. package/dist/outbox/outbox-builder.js.map +1 -1
  233. package/dist/outbox/outbox.d.ts +3 -1
  234. package/dist/outbox/outbox.d.ts.map +1 -1
  235. package/dist/outbox/outbox.js.map +1 -1
  236. package/dist/query/column-defaults.js.map +1 -1
  237. package/dist/query/condition-builder.d.ts +7 -1
  238. package/dist/query/condition-builder.d.ts.map +1 -1
  239. package/dist/query/condition-builder.js +5 -1
  240. package/dist/query/condition-builder.js.map +1 -1
  241. package/dist/query/cursor-client.d.ts +105 -0
  242. package/dist/query/cursor-client.d.ts.map +1 -0
  243. package/dist/query/cursor-client.js +165 -0
  244. package/dist/query/cursor-client.js.map +1 -0
  245. package/dist/query/cursor.d.ts.map +1 -1
  246. package/dist/query/cursor.js +7 -1
  247. package/dist/query/cursor.js.map +1 -1
  248. package/dist/query/db-now.d.ts +15 -1
  249. package/dist/query/db-now.d.ts.map +1 -1
  250. package/dist/query/db-now.js +30 -2
  251. package/dist/query/db-now.js.map +1 -1
  252. package/dist/query/orm/orm.js.map +1 -1
  253. package/dist/query/serialize/create-sql-serializer.js +2 -2
  254. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  255. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  256. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  257. package/dist/query/serialize/dialect/sqlite-serializer.js +6 -2
  258. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  259. package/dist/query/simple-query-interface.d.ts +7 -3
  260. package/dist/query/simple-query-interface.d.ts.map +1 -1
  261. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +37 -2
  262. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  263. package/dist/query/unit-of-work/execute-unit-of-work.js +39 -18
  264. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  265. package/dist/query/unit-of-work/unit-of-work.d.ts +42 -16
  266. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  267. package/dist/query/unit-of-work/unit-of-work.js +50 -6
  268. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  269. package/dist/query/value-decoding.js +8 -1
  270. package/dist/query/value-decoding.js.map +1 -1
  271. package/dist/query/value-encoding.js.map +1 -1
  272. package/dist/schema/create.d.ts +69 -25
  273. package/dist/schema/create.d.ts.map +1 -1
  274. package/dist/schema/create.js +91 -16
  275. package/dist/schema/create.js.map +1 -1
  276. package/dist/schema/type-conversion/create-sql-type-mapper.js +1 -1
  277. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  278. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  279. package/dist/schema/validator.d.ts.map +1 -1
  280. package/dist/schema/validator.js.map +1 -1
  281. package/dist/schema-output/drizzle.d.ts.map +1 -1
  282. package/dist/schema-output/drizzle.js +8 -6
  283. package/dist/schema-output/drizzle.js.map +1 -1
  284. package/dist/schema-output/prisma.d.ts.map +1 -1
  285. package/dist/schema-output/prisma.js +21 -10
  286. package/dist/schema-output/prisma.js.map +1 -1
  287. package/dist/sql-driver/dialects/durable-object-dialect.js +3 -9
  288. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -1
  289. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -1
  290. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -1
  291. package/dist/sql-driver/sql-driver-adapter.js.map +1 -1
  292. package/dist/sql-driver/sql.js.map +1 -1
  293. package/dist/sync/commands.d.ts +15 -0
  294. package/dist/sync/commands.d.ts.map +1 -0
  295. package/dist/sync/commands.js +27 -0
  296. package/dist/sync/commands.js.map +1 -0
  297. package/dist/sync/index.d.ts +4 -0
  298. package/dist/sync/index.js +4 -0
  299. package/dist/sync/read-tracking.d.ts +25 -0
  300. package/dist/sync/read-tracking.d.ts.map +1 -0
  301. package/dist/sync/read-tracking.js +148 -0
  302. package/dist/sync/read-tracking.js.map +1 -0
  303. package/dist/sync/submit.js +213 -0
  304. package/dist/sync/submit.js.map +1 -0
  305. package/dist/sync/types.d.ts +63 -0
  306. package/dist/sync/types.d.ts.map +1 -0
  307. package/dist/util/default-database-adapter.js +6 -1
  308. package/dist/util/default-database-adapter.js.map +1 -1
  309. package/dist/with-database.d.ts +3 -6
  310. package/dist/with-database.d.ts.map +1 -1
  311. package/dist/with-database.js +7 -15
  312. package/dist/with-database.js.map +1 -1
  313. package/package.json +33 -41
  314. package/src/adapters/adapters.ts +5 -4
  315. package/src/adapters/drizzle/migrate-drizzle.test.ts +46 -9
  316. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +5 -3
  317. package/src/adapters/drizzle/test-utils.ts +2 -1
  318. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -3
  319. package/src/adapters/generic-sql/generic-sql-adapter.ts +21 -24
  320. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +1 -0
  321. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +81 -15
  322. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +4 -2
  323. package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
  324. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +3 -2
  325. package/src/adapters/generic-sql/migration/dialect/mysql.ts +1 -0
  326. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +5 -4
  327. package/src/adapters/generic-sql/migration/dialect/postgres.ts +2 -1
  328. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +795 -3
  329. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +385 -57
  330. package/src/adapters/generic-sql/migration/executor.test.ts +52 -0
  331. package/src/adapters/generic-sql/migration/executor.ts +47 -4
  332. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +117 -14
  333. package/src/adapters/generic-sql/migration/prepared-migrations.ts +9 -8
  334. package/src/adapters/generic-sql/migration/sql-generator.ts +5 -3
  335. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +3 -3
  336. package/src/adapters/generic-sql/query/cursor-utils.test.ts +3 -2
  337. package/src/adapters/generic-sql/query/cursor-utils.ts +1 -1
  338. package/src/adapters/generic-sql/query/db-now-sql.ts +49 -0
  339. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +144 -8
  340. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +16 -17
  341. package/src/adapters/generic-sql/query/select-builder.test.ts +1 -0
  342. package/src/adapters/generic-sql/query/select-builder.ts +2 -2
  343. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +24 -5
  344. package/src/adapters/generic-sql/query/sql-query-compiler.ts +83 -13
  345. package/src/adapters/generic-sql/query/where-builder.test.ts +7 -5
  346. package/src/adapters/generic-sql/query/where-builder.ts +48 -29
  347. package/src/adapters/generic-sql/sql-adapter-pglite-migrations.test.ts +6 -15
  348. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +52 -7
  349. package/src/adapters/generic-sql/sql-adapter-pglite-queries.test.ts +9 -6
  350. package/src/adapters/generic-sql/sql-adapter-sqlite3-driver.test.ts +273 -5
  351. package/src/adapters/generic-sql/sql-adapter-sqlite3-uow.test.ts +123 -6
  352. package/src/adapters/generic-sql/sql-adapter-sqlocal.test.ts +4 -2
  353. package/src/adapters/generic-sql/uow-decoder.test.ts +4 -3
  354. package/src/adapters/generic-sql/uow-decoder.ts +3 -3
  355. package/src/adapters/generic-sql/uow-encoder.test.ts +4 -2
  356. package/src/adapters/generic-sql/uow-encoder.ts +14 -18
  357. package/src/adapters/in-memory/condition-evaluator.test.ts +2 -1
  358. package/src/adapters/in-memory/condition-evaluator.ts +9 -4
  359. package/src/adapters/in-memory/in-memory-adapter.ts +155 -44
  360. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +50 -2
  361. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +158 -3
  362. package/src/adapters/in-memory/in-memory-uow.ts +402 -26
  363. package/src/adapters/in-memory/options.test.ts +1 -0
  364. package/src/adapters/in-memory/options.ts +5 -1
  365. package/src/adapters/in-memory/outbox.test.ts +361 -0
  366. package/src/adapters/in-memory/reference-resolution.test.ts +3 -2
  367. package/src/adapters/in-memory/reference-resolution.ts +2 -2
  368. package/src/adapters/in-memory/sorted-array-index.test.ts +1 -0
  369. package/src/adapters/in-memory/store.test.ts +1 -0
  370. package/src/adapters/in-memory/store.ts +3 -3
  371. package/src/adapters/in-memory/value-normalization.test.ts +1 -0
  372. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +51 -7
  373. package/src/adapters/shared/from-unit-of-work-compiler.ts +156 -46
  374. package/src/adapters/shared/uow-operation-compiler.ts +3 -3
  375. package/src/browser/mod.ts +64 -0
  376. package/src/client.ts +19 -0
  377. package/src/db-fragment-definition-builder.test.ts +821 -47
  378. package/src/db-fragment-definition-builder.ts +857 -110
  379. package/src/db-fragment-instantiator.test.ts +114 -90
  380. package/src/db-fragment-integration.test.ts +9 -6
  381. package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
  382. package/src/dispatchers/cloudflare-do/index.test.ts +145 -12
  383. package/src/dispatchers/cloudflare-do/index.ts +49 -90
  384. package/src/dispatchers/node/dispatcher.ts +112 -0
  385. package/src/dispatchers/node/index.test.ts +43 -14
  386. package/src/dispatchers/node/index.ts +38 -75
  387. package/src/durable-hooks.test.ts +80 -0
  388. package/src/durable-hooks.ts +67 -0
  389. package/src/fragments/internal-fragment.routes.test.ts +570 -0
  390. package/src/fragments/internal-fragment.routes.ts +297 -5
  391. package/src/fragments/internal-fragment.schema.ts +45 -1
  392. package/src/fragments/internal-fragment.test.ts +223 -251
  393. package/src/fragments/internal-fragment.ts +278 -154
  394. package/src/hooks/durable-hooks-logger.ts +126 -0
  395. package/src/hooks/durable-hooks-processor.pglite.test.ts +87 -0
  396. package/src/hooks/durable-hooks-processor.test.ts +179 -14
  397. package/src/hooks/durable-hooks-processor.ts +120 -14
  398. package/src/hooks/durable-hooks-runtime.test.ts +65 -0
  399. package/src/hooks/durable-hooks-runtime.ts +81 -0
  400. package/src/hooks/hooks.test.ts +314 -53
  401. package/src/hooks/hooks.ts +360 -81
  402. package/src/id.test.ts +34 -0
  403. package/src/id.ts +1 -3
  404. package/src/internal/adapter-registry.test.ts +93 -0
  405. package/src/internal/adapter-registry.ts +239 -0
  406. package/src/internal/outbox-state.ts +43 -0
  407. package/src/migration-engine/auto-from-schema.test.ts +93 -0
  408. package/src/migration-engine/auto-from-schema.ts +360 -42
  409. package/src/migration-engine/create.test.ts +2 -1
  410. package/src/migration-engine/create.ts +1 -1
  411. package/src/migration-engine/generation-engine.test.ts +66 -9
  412. package/src/migration-engine/generation-engine.ts +31 -10
  413. package/src/migration-engine/shared.ts +13 -0
  414. package/src/mod.ts +45 -27
  415. package/src/naming/sql-naming.ts +1 -0
  416. package/src/outbox/outbox-builder.ts +2 -2
  417. package/src/outbox/outbox.test.ts +216 -45
  418. package/src/outbox/outbox.ts +3 -1
  419. package/src/query/column-defaults.ts +1 -1
  420. package/src/query/condition-builder.test.ts +15 -0
  421. package/src/query/condition-builder.ts +7 -0
  422. package/src/query/cursor-client.test.ts +70 -0
  423. package/src/query/cursor-client.ts +263 -0
  424. package/src/query/cursor.test.ts +3 -2
  425. package/src/query/cursor.ts +15 -3
  426. package/src/query/db-now.ts +69 -2
  427. package/src/query/orm/orm.ts +2 -2
  428. package/src/query/query-type.test.ts +2 -1
  429. package/src/query/serialize/create-sql-serializer.ts +3 -3
  430. package/src/query/serialize/dialect/mysql-serializer.ts +1 -1
  431. package/src/query/serialize/dialect/postgres-serializer.ts +1 -1
  432. package/src/query/serialize/dialect/sqlite-serializer.test.ts +39 -2
  433. package/src/query/serialize/dialect/sqlite-serializer.ts +18 -5
  434. package/src/query/simple-query-interface.ts +10 -4
  435. package/src/query/unit-of-work/execute-unit-of-work.test.ts +347 -9
  436. package/src/query/unit-of-work/execute-unit-of-work.ts +63 -20
  437. package/src/query/unit-of-work/retry-policy.test.ts +1 -0
  438. package/src/query/unit-of-work/tx-builder.test.ts +73 -1
  439. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +5 -4
  440. package/src/query/unit-of-work/unit-of-work-types.test.ts +41 -11
  441. package/src/query/unit-of-work/unit-of-work.test.ts +28 -2
  442. package/src/query/unit-of-work/unit-of-work.ts +105 -19
  443. package/src/query/value-decoding.test.ts +50 -2
  444. package/src/query/value-decoding.ts +17 -4
  445. package/src/query/value-encoding.test.ts +1 -0
  446. package/src/query/value-encoding.ts +1 -1
  447. package/src/schema/create.test.ts +164 -5
  448. package/src/schema/create.ts +222 -24
  449. package/src/schema/generate-id.test.ts +1 -0
  450. package/src/schema/serialize.test.ts +4 -3
  451. package/src/schema/type-conversion/create-sql-type-mapper.ts +1 -1
  452. package/src/schema/type-conversion/dialect/sqlite.ts +2 -2
  453. package/src/schema/type-conversion/type-mapping.test.ts +2 -1
  454. package/src/schema/validator.test.ts +4 -2
  455. package/src/schema/validator.ts +1 -0
  456. package/src/schema-output/drizzle.test.ts +72 -19
  457. package/src/schema-output/drizzle.ts +24 -18
  458. package/src/schema-output/prisma.test.ts +172 -14
  459. package/src/schema-output/prisma.ts +34 -14
  460. package/src/sql-driver/better-sqlite3.test.ts +5 -3
  461. package/src/sql-driver/dialects/durable-object-dialect.ts +3 -8
  462. package/src/sql-driver/query-executor/default-query-executor.ts +1 -1
  463. package/src/sql-driver/query-executor/query-executor-base.ts +1 -1
  464. package/src/sql-driver/query-executor/query-executor.ts +1 -1
  465. package/src/sql-driver/sql-driver-adapter.ts +2 -2
  466. package/src/sql-driver/sql.ts +2 -1
  467. package/src/sql-driver/sqlocal.test.ts +4 -2
  468. package/src/sync/commands.test.ts +39 -0
  469. package/src/sync/commands.ts +51 -0
  470. package/src/sync/conflict-checker.test.ts +450 -0
  471. package/src/sync/conflict-checker.ts +248 -0
  472. package/src/sync/index.ts +14 -0
  473. package/src/sync/plan.ts +9 -0
  474. package/src/sync/read-tracking.test.ts +177 -0
  475. package/src/sync/read-tracking.ts +287 -0
  476. package/src/sync/submit.test.ts +205 -0
  477. package/src/sync/submit.ts +328 -0
  478. package/src/sync/types.ts +80 -0
  479. package/src/util/default-database-adapter.ts +15 -2
  480. package/src/with-database.ts +20 -50
  481. package/tsconfig.json +1 -1
  482. package/tsdown.config.ts +38 -26
  483. package/vitest.config.ts +1 -0
  484. package/dist/hooks/durable-hooks-processor.d.ts.map +0 -1
  485. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js +0 -168
  486. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +0 -1
  487. package/dist/packages/fragno/dist/api/bind-services.js +0 -20
  488. package/dist/packages/fragno/dist/api/bind-services.js.map +0 -1
  489. package/dist/packages/fragno/dist/api/error.js +0 -48
  490. package/dist/packages/fragno/dist/api/error.js.map +0 -1
  491. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +0 -321
  492. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
  493. package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -669
  494. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +0 -1
  495. package/dist/packages/fragno/dist/api/fragno-response.js +0 -73
  496. package/dist/packages/fragno/dist/api/fragno-response.js.map +0 -1
  497. package/dist/packages/fragno/dist/api/internal/response-stream.js +0 -81
  498. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +0 -1
  499. package/dist/packages/fragno/dist/api/internal/route.js +0 -10
  500. package/dist/packages/fragno/dist/api/internal/route.js.map +0 -1
  501. package/dist/packages/fragno/dist/api/mutable-request-state.js +0 -97
  502. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +0 -1
  503. package/dist/packages/fragno/dist/api/request-context-storage.js +0 -43
  504. package/dist/packages/fragno/dist/api/request-context-storage.js.map +0 -1
  505. package/dist/packages/fragno/dist/api/request-input-context.js +0 -185
  506. package/dist/packages/fragno/dist/api/request-input-context.js.map +0 -1
  507. package/dist/packages/fragno/dist/api/request-middleware.js +0 -83
  508. package/dist/packages/fragno/dist/api/request-middleware.js.map +0 -1
  509. package/dist/packages/fragno/dist/api/request-output-context.js +0 -119
  510. package/dist/packages/fragno/dist/api/request-output-context.js.map +0 -1
  511. package/dist/packages/fragno/dist/api/route.js +0 -30
  512. package/dist/packages/fragno/dist/api/route.js.map +0 -1
  513. package/dist/packages/fragno/dist/internal/symbols.js +0 -10
  514. package/dist/packages/fragno/dist/internal/symbols.js.map +0 -1
  515. package/dist/packages/fragno/dist/internal/trace-context.js +0 -12
  516. package/dist/packages/fragno/dist/internal/trace-context.js.map +0 -1
@@ -1,6 +1,29 @@
1
- import type { AnySchema, AnyTable } from "../../schema/create";
2
- import { FragnoId, FragnoReference } from "../../schema/create";
3
- import { SQLocalDriverConfig } from "../generic-sql/driver-config";
1
+ import superjson from "superjson";
2
+
3
+ import {
4
+ SETTINGS_NAMESPACE,
5
+ SETTINGS_TABLE_NAME,
6
+ internalSchema,
7
+ } from "../../fragments/internal-fragment";
8
+ import type { NamingResolver } from "../../naming/sql-naming";
9
+ import {
10
+ type OutboxRefLookup,
11
+ type OutboxRefMap,
12
+ encodeVersionstamp,
13
+ versionstampToHex,
14
+ parseOutboxVersionValue,
15
+ } from "../../outbox/outbox";
16
+ import { buildOutboxPlan, finalizeOutboxPayload } from "../../outbox/outbox-builder";
17
+ import { buildCondition } from "../../query/condition-builder";
18
+ import {
19
+ createCursorFromRecord,
20
+ decodeCursor,
21
+ type Cursor,
22
+ type CursorResult,
23
+ } from "../../query/cursor";
24
+ import { getDbNowOffsetMs, isDbNow } from "../../query/db-now";
25
+ import type { CompiledJoin } from "../../query/orm/orm";
26
+ import { createSQLSerializer } from "../../query/serialize/create-sql-serializer";
4
27
  import type {
5
28
  CompiledMutation,
6
29
  MutationOperation,
@@ -10,21 +33,17 @@ import type {
10
33
  UOWDecoder,
11
34
  UOWExecutor,
12
35
  } from "../../query/unit-of-work/unit-of-work";
13
- import { buildCondition } from "../../query/condition-builder";
14
36
  import {
15
37
  encodeValues,
16
38
  encodeValuesWithDbDefaults,
17
39
  ReferenceSubquery,
18
40
  } from "../../query/value-encoding";
19
- import { isDbNow } from "../../query/db-now";
20
- import { createSQLSerializer } from "../../query/serialize/create-sql-serializer";
21
- import type { CompiledJoin } from "../../query/orm/orm";
22
- import {
23
- createCursorFromRecord,
24
- decodeCursor,
25
- type Cursor,
26
- type CursorResult,
27
- } from "../../query/cursor";
41
+ import type { AnySchema, AnyTable } from "../../schema/create";
42
+ import { FragnoId, FragnoReference } from "../../schema/create";
43
+ import { SQLocalDriverConfig } from "../generic-sql/driver-config";
44
+ import { evaluateCondition } from "./condition-evaluator";
45
+ import type { ResolvedInMemoryAdapterOptions } from "./options";
46
+ import { resolveReferenceSubqueries } from "./reference-resolution";
28
47
  import type {
29
48
  InMemoryNamespaceStore,
30
49
  InMemoryRow,
@@ -32,16 +51,15 @@ import type {
32
51
  InMemoryTableStore,
33
52
  } from "./store";
34
53
  import { buildIndexKey, ensureNamespaceStore, normalizeIndexValue } from "./store";
35
- import { evaluateCondition } from "./condition-evaluator";
36
- import { resolveReferenceSubqueries } from "./reference-resolution";
37
- import type { ResolvedInMemoryAdapterOptions } from "./options";
38
54
  import { compareNormalizedValues } from "./value-comparison";
39
- import type { NamingResolver } from "../../naming/sql-naming";
40
55
 
41
56
  type InMemoryCompiledQuery = RetrievalOperation<AnySchema> | MutationOperation<AnySchema>;
42
57
  type InMemoryRawResult = InMemoryRow[] | { count: number }[];
43
58
  type CursorInput = string | Cursor | undefined;
44
59
  type ResolverFactory = (schema: AnySchema, namespace: string | null) => NamingResolver;
60
+ type SchemaNamespaceEntry = { schema: AnySchema; namespace: string | null };
61
+
62
+ const OUTBOX_VERSION_KEY = `${SETTINGS_NAMESPACE}.outbox_version`;
45
63
 
46
64
  const getResolver = (
47
65
  schema: AnySchema,
@@ -255,20 +273,32 @@ const findJoinMatches = (
255
273
  throw new Error(`Column "${right}" not found on table "${targetTable.name}".`);
256
274
  }
257
275
 
258
- const actualRight = rightColumn.role === "external-id" ? "_internalId" : right;
276
+ const actualLeft =
277
+ leftColumn.role === "external-id" && rightColumn.role !== "external-id"
278
+ ? "_internalId"
279
+ : left;
280
+ const actualLeftColumn = parentTable.columns[actualLeft];
281
+ if (!actualLeftColumn) {
282
+ throw new Error(`Column "${actualLeft}" not found on table "${parentTable.name}".`);
283
+ }
284
+
285
+ const actualRight =
286
+ rightColumn.role === "external-id" && leftColumn.role !== "external-id"
287
+ ? "_internalId"
288
+ : right;
259
289
  const actualRightColumn = targetTable.columns[actualRight];
260
290
  if (!actualRightColumn) {
261
291
  throw new Error(`Column "${actualRight}" not found on table "${targetTable.name}".`);
262
292
  }
263
293
 
264
- const leftValue = parentRow[getPhysicalColumnName(parentTable, left, resolver)];
294
+ const leftValue = parentRow[getPhysicalColumnName(parentTable, actualLeft, resolver)];
265
295
  const rightValue = row[getPhysicalColumnName(targetTable, actualRight, resolver)];
266
296
  if (isNullish(leftValue) || isNullish(rightValue)) {
267
297
  matchesJoin = false;
268
298
  break;
269
299
  }
270
300
 
271
- const leftNormalized = normalizeIndexValue(leftValue, leftColumn);
301
+ const leftNormalized = normalizeIndexValue(leftValue, actualLeftColumn);
272
302
  const rightNormalized = normalizeIndexValue(rightValue, actualRightColumn);
273
303
  if (compareNormalizedValues(leftNormalized, rightNormalized) !== 0) {
274
304
  matchesJoin = false;
@@ -433,7 +463,7 @@ const enforceOutgoingForeignKeys = (
433
463
  resolver?: NamingResolver,
434
464
  ): void => {
435
465
  for (const relation of Object.values(table.relations)) {
436
- if (relation.type !== "one") {
466
+ if (relation.type !== "one" || relation.foreignKey === false) {
437
467
  continue;
438
468
  }
439
469
 
@@ -500,7 +530,7 @@ const enforceNoIncomingForeignKeys = (
500
530
  ): void => {
501
531
  for (const sourceTable of Object.values(schema.tables)) {
502
532
  for (const relation of Object.values(sourceTable.relations)) {
503
- if (relation.type !== "one") {
533
+ if (relation.type !== "one" || relation.foreignKey === false) {
504
534
  continue;
505
535
  }
506
536
 
@@ -645,7 +675,9 @@ const findRows = (
645
675
 
646
676
  const scanOptions = {
647
677
  direction,
648
- limit,
678
+ // Apply result limits after where/join filtering. Passing the limit into the
679
+ // raw index scan can drop matching rows that appear later in the index.
680
+ limit: undefined as number | undefined,
649
681
  start: undefined as readonly unknown[] | undefined,
650
682
  startInclusive: true,
651
683
  end: undefined as readonly unknown[] | undefined,
@@ -758,8 +790,14 @@ const countRows = (
758
790
  return count;
759
791
  };
760
792
 
761
- const resolveDbNowValue = (value: unknown, options: ResolvedInMemoryAdapterOptions): unknown =>
762
- isDbNow(value) ? options.clock.now() : value;
793
+ const resolveDbNowValue = (value: unknown, options: ResolvedInMemoryAdapterOptions): unknown => {
794
+ if (!isDbNow(value)) {
795
+ return value;
796
+ }
797
+ const now = options.clock.now();
798
+ const offsetMs = getDbNowOffsetMs(value);
799
+ return offsetMs === 0 ? now : new Date(now.getTime() + offsetMs);
800
+ };
763
801
 
764
802
  const createRow = (
765
803
  op: Extract<MutationOperation<AnySchema>, { type: "create" }>,
@@ -1001,6 +1039,279 @@ const checkRow = (
1001
1039
  }
1002
1040
  };
1003
1041
 
1042
+ const resolveSchemaForLookup = (
1043
+ table: AnyTable,
1044
+ namespace: string | undefined,
1045
+ schemaByNamespace?: Map<string, SchemaNamespaceEntry>,
1046
+ ): SchemaNamespaceEntry | null => {
1047
+ if (!schemaByNamespace) {
1048
+ return null;
1049
+ }
1050
+
1051
+ if (namespace !== undefined) {
1052
+ const entry = schemaByNamespace.get(namespace);
1053
+ if (entry && entry.schema.tables[table.name] === table) {
1054
+ return entry;
1055
+ }
1056
+ return null;
1057
+ }
1058
+
1059
+ for (const entry of schemaByNamespace.values()) {
1060
+ if (entry.schema.tables[table.name] === table) {
1061
+ return entry;
1062
+ }
1063
+ }
1064
+
1065
+ return null;
1066
+ };
1067
+
1068
+ const reserveOutboxVersion = (
1069
+ store: InMemoryStore,
1070
+ options: ResolvedInMemoryAdapterOptions,
1071
+ resolverFactory?: ResolverFactory,
1072
+ ): { version: bigint; rollback: () => void } => {
1073
+ const resolver = getResolver(internalSchema, null, resolverFactory);
1074
+ const namespaceStore = getNamespaceStore(store, internalSchema, null, resolver);
1075
+ const settingsTable = internalSchema.tables[SETTINGS_TABLE_NAME];
1076
+ if (!settingsTable) {
1077
+ throw new Error("Missing internal settings table definition.");
1078
+ }
1079
+ const tableStore = getTableStore(namespaceStore, settingsTable, resolver);
1080
+ const keyColumnName = getPhysicalColumnName(settingsTable, "key", resolver);
1081
+ const valueColumnName = getPhysicalColumnName(settingsTable, "value", resolver);
1082
+ const idColumnName = getPhysicalColumnName(
1083
+ settingsTable,
1084
+ settingsTable.getIdColumn().name,
1085
+ resolver,
1086
+ );
1087
+
1088
+ for (const row of tableStore.rows.values()) {
1089
+ if (row[keyColumnName] !== OUTBOX_VERSION_KEY) {
1090
+ continue;
1091
+ }
1092
+
1093
+ const rawValue = row[valueColumnName];
1094
+ const current = parseOutboxVersionValue(rawValue);
1095
+ const next = current + 1n;
1096
+ const externalId = row[idColumnName];
1097
+ if (typeof externalId !== "string") {
1098
+ throw new Error("Outbox version row is missing external id.");
1099
+ }
1100
+
1101
+ const updateOp: Extract<MutationOperation<AnySchema>, { type: "update" }> = {
1102
+ type: "update",
1103
+ schema: internalSchema,
1104
+ namespace: null,
1105
+ table: settingsTable.name,
1106
+ id: externalId,
1107
+ checkVersion: false,
1108
+ set: { value: next.toString() },
1109
+ };
1110
+ const rollback = updateRow(updateOp, namespaceStore, tableStore, options, resolver);
1111
+ return { version: next, rollback: rollback ?? (() => {}) };
1112
+ }
1113
+
1114
+ const createOp: Extract<MutationOperation<AnySchema>, { type: "create" }> = {
1115
+ type: "create",
1116
+ schema: internalSchema,
1117
+ namespace: null,
1118
+ table: settingsTable.name,
1119
+ values: { key: OUTBOX_VERSION_KEY, value: "0" },
1120
+ generatedExternalId: options.idGenerator(),
1121
+ };
1122
+ const previousInternalId = tableStore.nextInternalId;
1123
+ const internalId = createRow(createOp, namespaceStore, tableStore, options, resolver);
1124
+ const rollback = () => {
1125
+ const existingRow = tableStore.rows.get(internalId);
1126
+ if (existingRow) {
1127
+ for (const indexStore of tableStore.indexes.values()) {
1128
+ const key = buildIndexKey(settingsTable, indexStore.definition, existingRow, resolver);
1129
+ indexStore.index.remove(key, internalId);
1130
+ }
1131
+ tableStore.rows.delete(internalId);
1132
+ }
1133
+ tableStore.nextInternalId = previousInternalId;
1134
+ };
1135
+
1136
+ return { version: 0n, rollback };
1137
+ };
1138
+
1139
+ const resolveOutboxRefMap = (
1140
+ store: InMemoryStore,
1141
+ lookups: OutboxRefLookup[],
1142
+ resolverFactory: ResolverFactory | undefined,
1143
+ schemaByNamespace?: Map<string, SchemaNamespaceEntry>,
1144
+ ): OutboxRefMap | undefined => {
1145
+ if (lookups.length === 0) {
1146
+ return undefined;
1147
+ }
1148
+
1149
+ const refMap: OutboxRefMap = {};
1150
+
1151
+ for (const lookup of lookups) {
1152
+ const schemaEntry = resolveSchemaForLookup(lookup.table, lookup.namespace, schemaByNamespace);
1153
+ if (!schemaEntry) {
1154
+ throw new Error(`Failed to resolve schema for outbox lookup on ${lookup.table.name}.`);
1155
+ }
1156
+
1157
+ const resolver = getResolver(schemaEntry.schema, schemaEntry.namespace, resolverFactory);
1158
+ const namespaceStore = getNamespaceStore(
1159
+ store,
1160
+ schemaEntry.schema,
1161
+ schemaEntry.namespace,
1162
+ resolver,
1163
+ );
1164
+ const tableStore = getTableStore(namespaceStore, lookup.table, resolver);
1165
+ const internalId =
1166
+ typeof lookup.internalId === "number" ? BigInt(lookup.internalId) : lookup.internalId;
1167
+ const row = tableStore.rows.get(internalId);
1168
+
1169
+ if (!row) {
1170
+ const tableName = resolver ? resolver.getTableName(lookup.table.name) : lookup.table.name;
1171
+ const internalColumn = resolver
1172
+ ? resolver.getColumnName(lookup.table.name, lookup.table.getInternalIdColumn().name)
1173
+ : lookup.table.getInternalIdColumn().name;
1174
+ throw new Error(
1175
+ `Failed to resolve outbox reference for ${tableName}.${internalColumn}=${String(lookup.internalId)}`,
1176
+ );
1177
+ }
1178
+
1179
+ const externalColumnName = getPhysicalColumnName(
1180
+ lookup.table,
1181
+ lookup.table.getIdColumn().name,
1182
+ resolver,
1183
+ );
1184
+ const externalId = row[externalColumnName];
1185
+ if (typeof externalId !== "string") {
1186
+ throw new Error("Outbox reference row is missing external id.");
1187
+ }
1188
+
1189
+ refMap[lookup.key] = externalId;
1190
+ }
1191
+
1192
+ return Object.keys(refMap).length > 0 ? refMap : undefined;
1193
+ };
1194
+
1195
+ const insertOutboxRow = (
1196
+ store: InMemoryStore,
1197
+ options: ResolvedInMemoryAdapterOptions,
1198
+ resolverFactory: ResolverFactory | undefined,
1199
+ payload: {
1200
+ versionstamp: string;
1201
+ uowId: string;
1202
+ payload: { json: unknown; meta?: Record<string, unknown> };
1203
+ refMap?: OutboxRefMap;
1204
+ },
1205
+ ): (() => void) => {
1206
+ const resolver = getResolver(internalSchema, null, resolverFactory);
1207
+ const namespaceStore = getNamespaceStore(store, internalSchema, null, resolver);
1208
+ const outboxTable = internalSchema.tables.fragno_db_outbox;
1209
+ if (!outboxTable) {
1210
+ throw new Error("Missing internal outbox table definition.");
1211
+ }
1212
+ const tableStore = getTableStore(namespaceStore, outboxTable, resolver);
1213
+ const createOp: Extract<MutationOperation<AnySchema>, { type: "create" }> = {
1214
+ type: "create",
1215
+ schema: internalSchema,
1216
+ namespace: null,
1217
+ table: outboxTable.name,
1218
+ values: {
1219
+ versionstamp: payload.versionstamp,
1220
+ uowId: payload.uowId,
1221
+ payload: payload.payload,
1222
+ ...(payload.refMap ? { refMap: payload.refMap } : {}),
1223
+ },
1224
+ generatedExternalId: options.idGenerator(),
1225
+ };
1226
+ const previousInternalId = tableStore.nextInternalId;
1227
+ const internalId = createRow(createOp, namespaceStore, tableStore, options, resolver);
1228
+
1229
+ return () => {
1230
+ const existingRow = tableStore.rows.get(internalId);
1231
+ if (existingRow) {
1232
+ for (const indexStore of tableStore.indexes.values()) {
1233
+ const key = buildIndexKey(outboxTable, indexStore.definition, existingRow, resolver);
1234
+ indexStore.index.remove(key, internalId);
1235
+ }
1236
+ tableStore.rows.delete(internalId);
1237
+ }
1238
+ tableStore.nextInternalId = previousInternalId;
1239
+ };
1240
+ };
1241
+
1242
+ const insertOutboxMutationRows = (
1243
+ store: InMemoryStore,
1244
+ options: ResolvedInMemoryAdapterOptions,
1245
+ resolverFactory: ResolverFactory | undefined,
1246
+ payload: {
1247
+ entryVersionstamp: string;
1248
+ uowId: string;
1249
+ mutations: {
1250
+ versionstamp: string;
1251
+ schema: string;
1252
+ table: string;
1253
+ externalId: string;
1254
+ op: string;
1255
+ }[];
1256
+ },
1257
+ ): Array<() => void> => {
1258
+ if (payload.mutations.length === 0) {
1259
+ return [];
1260
+ }
1261
+
1262
+ const resolver = getResolver(internalSchema, null, resolverFactory);
1263
+ const namespaceStore = getNamespaceStore(store, internalSchema, null, resolver);
1264
+ const mutationsTable = internalSchema.tables.fragno_db_outbox_mutations;
1265
+ if (!mutationsTable) {
1266
+ throw new Error("Missing internal outbox mutations table definition.");
1267
+ }
1268
+ const tableStore = getTableStore(namespaceStore, mutationsTable, resolver);
1269
+ const rollbackActions: Array<() => void> = [];
1270
+
1271
+ try {
1272
+ for (const mutation of payload.mutations) {
1273
+ const createOp: Extract<MutationOperation<AnySchema>, { type: "create" }> = {
1274
+ type: "create",
1275
+ schema: internalSchema,
1276
+ namespace: null,
1277
+ table: mutationsTable.name,
1278
+ values: {
1279
+ entryVersionstamp: payload.entryVersionstamp,
1280
+ mutationVersionstamp: mutation.versionstamp,
1281
+ uowId: payload.uowId,
1282
+ schema: mutation.schema,
1283
+ table: mutation.table,
1284
+ externalId: mutation.externalId,
1285
+ op: mutation.op,
1286
+ },
1287
+ generatedExternalId: options.idGenerator(),
1288
+ };
1289
+
1290
+ const previousInternalId = tableStore.nextInternalId;
1291
+ const internalId = createRow(createOp, namespaceStore, tableStore, options, resolver);
1292
+
1293
+ rollbackActions.push(() => {
1294
+ const existingRow = tableStore.rows.get(internalId);
1295
+ if (existingRow) {
1296
+ for (const indexStore of tableStore.indexes.values()) {
1297
+ const key = buildIndexKey(mutationsTable, indexStore.definition, existingRow, resolver);
1298
+ indexStore.index.remove(key, internalId);
1299
+ }
1300
+ tableStore.rows.delete(internalId);
1301
+ }
1302
+ tableStore.nextInternalId = previousInternalId;
1303
+ });
1304
+ }
1305
+ } catch (error) {
1306
+ for (const rollback of rollbackActions.reverse()) {
1307
+ rollback();
1308
+ }
1309
+ throw error;
1310
+ }
1311
+
1312
+ return rollbackActions;
1313
+ };
1314
+
1004
1315
  export const createInMemoryUowCompiler = (): UOWCompiler<InMemoryCompiledQuery> => ({
1005
1316
  compileRetrievalOperation(op: RetrievalOperation<AnySchema>): InMemoryCompiledQuery | null {
1006
1317
  return op;
@@ -1022,6 +1333,7 @@ export const createInMemoryUowExecutor = (
1022
1333
  store: InMemoryStore,
1023
1334
  options: ResolvedInMemoryAdapterOptions,
1024
1335
  resolverFactory?: ResolverFactory,
1336
+ schemaByNamespace?: Map<string, SchemaNamespaceEntry>,
1025
1337
  ): UOWExecutor<InMemoryCompiledQuery, InMemoryRawResult> => ({
1026
1338
  async executeRetrievalPhase(
1027
1339
  retrievalBatch: InMemoryCompiledQuery[],
@@ -1060,8 +1372,31 @@ export const createInMemoryUowExecutor = (
1060
1372
  ): Promise<MutationResult> {
1061
1373
  const createdInternalIds: (bigint | null)[] = [];
1062
1374
  const rollbackActions: Array<() => void> = [];
1375
+ const outboxEnabled = options.outbox?.enabled ?? false;
1376
+ const shouldInclude = options.outbox?.shouldInclude;
1377
+ const outboxOperations = outboxEnabled
1378
+ ? mutationBatch.flatMap((mutation) => {
1379
+ const operation = mutation.operation;
1380
+ if (!operation) {
1381
+ return [];
1382
+ }
1383
+ if (shouldInclude && !shouldInclude(operation)) {
1384
+ return [];
1385
+ }
1386
+ return [operation];
1387
+ })
1388
+ : [];
1389
+ const outboxPlan = outboxOperations.length > 0 ? buildOutboxPlan(outboxOperations) : null;
1390
+ const shouldWriteOutbox = outboxEnabled && outboxPlan !== null && outboxPlan.drafts.length > 0;
1391
+ let outboxVersion: bigint | null = null;
1063
1392
 
1064
1393
  try {
1394
+ if (shouldWriteOutbox) {
1395
+ const reservation = reserveOutboxVersion(store, options, resolverFactory);
1396
+ outboxVersion = reservation.version;
1397
+ rollbackActions.push(reservation.rollback);
1398
+ }
1399
+
1065
1400
  for (const compiled of mutationBatch) {
1066
1401
  const operation = compiled.query;
1067
1402
 
@@ -1161,6 +1496,37 @@ export const createInMemoryUowExecutor = (
1161
1496
 
1162
1497
  throw new Error(`Unsupported in-memory mutation "${operation.type}".`);
1163
1498
  }
1499
+
1500
+ if (shouldWriteOutbox && outboxPlan && outboxVersion !== null) {
1501
+ const uowId = mutationBatch[0]?.uowId;
1502
+ if (!uowId) {
1503
+ throw new Error("Outbox mutation batch is missing uowId.");
1504
+ }
1505
+
1506
+ const refMap = resolveOutboxRefMap(
1507
+ store,
1508
+ outboxPlan.lookups,
1509
+ resolverFactory,
1510
+ schemaByNamespace,
1511
+ );
1512
+ const payload = finalizeOutboxPayload(outboxPlan, outboxVersion);
1513
+ const payloadSerialized = superjson.serialize(payload);
1514
+ const versionstamp = versionstampToHex(encodeVersionstamp(outboxVersion, 0));
1515
+ rollbackActions.push(
1516
+ ...insertOutboxMutationRows(store, options, resolverFactory, {
1517
+ entryVersionstamp: versionstamp,
1518
+ uowId,
1519
+ mutations: payload.mutations,
1520
+ }),
1521
+ );
1522
+ const rollback = insertOutboxRow(store, options, resolverFactory, {
1523
+ versionstamp,
1524
+ uowId,
1525
+ payload: payloadSerialized,
1526
+ refMap,
1527
+ });
1528
+ rollbackActions.push(rollback);
1529
+ }
1164
1530
  } catch (error) {
1165
1531
  for (const rollback of rollbackActions.reverse()) {
1166
1532
  rollback();
@@ -1262,7 +1628,17 @@ export class InMemoryUowDecoder implements UOWDecoder<InMemoryRawResult> {
1262
1628
  if (!relation) {
1263
1629
  continue;
1264
1630
  }
1265
- output[relationName] = this.decodeRow(relationData[relationName], relation.table, resolver);
1631
+ const relationRow = relationData[relationName];
1632
+ const internalIdKey = relation.table.getInternalIdColumn().name;
1633
+ if (
1634
+ Object.prototype.hasOwnProperty.call(relationRow, internalIdKey) &&
1635
+ isNullish(relationRow[internalIdKey])
1636
+ ) {
1637
+ output[relationName] = relation.type === "many" ? [] : null;
1638
+ continue;
1639
+ }
1640
+
1641
+ output[relationName] = this.decodeRow(relationRow, relation.table, resolver);
1266
1642
  }
1267
1643
 
1268
1644
  for (const key in columnValues) {
@@ -1,4 +1,5 @@
1
1
  import { afterEach, describe, expect, it, vi } from "vitest";
2
+
2
3
  import { resolveInMemoryAdapterOptions } from "./options";
3
4
 
4
5
  describe("resolveInMemoryAdapterOptions", () => {
@@ -1,5 +1,7 @@
1
- import { createId, init } from "@paralleldrive/cuid2";
1
+ import { createId, init } from "@fragno-dev/core";
2
+
2
3
  import type { SqlNamingStrategy } from "../../naming/sql-naming";
4
+ import type { OutboxConfig } from "../../outbox/outbox";
3
5
 
4
6
  export type InMemoryAdapterOptions = {
5
7
  clock?: { now: () => Date };
@@ -19,6 +21,7 @@ export type ResolvedInMemoryAdapterOptions = {
19
21
  internalIdGeneratorProvided: boolean;
20
22
  enforceConstraints: boolean;
21
23
  btreeOrder: number;
24
+ outbox?: OutboxConfig;
22
25
  };
23
26
 
24
27
  const defaultClock = {
@@ -83,5 +86,6 @@ export const resolveInMemoryAdapterOptions = (
83
86
  internalIdGeneratorProvided,
84
87
  enforceConstraints: options.enforceConstraints ?? defaultEnforceConstraints,
85
88
  btreeOrder: options.btreeOrder ?? defaultBtreeOrder,
89
+ outbox: undefined,
86
90
  };
87
91
  };