@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,5 +1,10 @@
1
1
  import { describe, it, expect } from "vitest";
2
+
3
+ import { BetterSQLite3DriverConfig } from "../../adapters/generic-sql/driver-config";
4
+ import { GenericSQLUOWOperationCompiler } from "../../adapters/generic-sql/query/generic-sql-uow-operation-compiler";
5
+ import { createUOWCompilerFromOperationCompiler } from "../../adapters/shared/uow-operation-compiler";
2
6
  import { schema, idColumn, type FragnoId, referenceColumn } from "../../schema/create";
7
+ import type { CompiledQuery } from "../../sql-driver/sql-driver";
3
8
  import {
4
9
  type UOWCompiler,
5
10
  type UOWDecoder,
@@ -7,10 +12,6 @@ import {
7
12
  type CompiledMutation,
8
13
  type UOWExecutor,
9
14
  } from "./unit-of-work";
10
- import { GenericSQLUOWOperationCompiler } from "../../adapters/generic-sql/query/generic-sql-uow-operation-compiler";
11
- import { BetterSQLite3DriverConfig } from "../../adapters/generic-sql/driver-config";
12
- import { createUOWCompilerFromOperationCompiler } from "../../adapters/shared/uow-operation-compiler";
13
- import type { CompiledQuery } from "../../sql-driver/sql-driver";
14
15
 
15
16
  // Create compiler using actual implementation
16
17
  function createCompiler(): UOWCompiler<CompiledQuery> {
@@ -1,7 +1,8 @@
1
1
  import { describe, expectTypeOf, it } from "vitest";
2
+
2
3
  import { column, idColumn, referenceColumn, schema } from "../../schema/create";
3
- import { JoinFindBuilder, UnitOfWork } from "./unit-of-work";
4
4
  import type { FragnoId, FragnoReference } from "../../schema/create";
5
+ import { JoinFindBuilder, UnitOfWork } from "./unit-of-work";
5
6
 
6
7
  type Prettify<T> = {
7
8
  [K in keyof T]: T[K];
@@ -138,7 +139,6 @@ describe("UnitOfWork type tests", () => {
138
139
  const [_userResult] = await uow1.executeRetrieve();
139
140
  type UserResult = RecursivePrettify<(typeof _userResult)[number]>;
140
141
 
141
- // @ts-expect-error assert type
142
142
  expectTypeOf<UserResult>().toEqualTypeOf<{
143
143
  id: FragnoId;
144
144
  name: string;
@@ -174,13 +174,8 @@ describe("UnitOfWork type tests", () => {
174
174
  type _JoinOutInviter = Prettify<_JoinOut["inviter"]>;
175
175
  // ^?
176
176
 
177
- // FIXME: There should not be a `{}` in the type
178
177
  expectTypeOf<_JoinOutInviter>().toEqualTypeOf<{
179
- id: FragnoId;
180
178
  name: string;
181
- email: string;
182
- age: number | null;
183
- invitedBy: FragnoReference | null;
184
179
  } | null>();
185
180
  });
186
181
 
@@ -194,14 +189,49 @@ describe("UnitOfWork type tests", () => {
194
189
  type _JoinOutPosts = Prettify<_JoinOut["posts"]>;
195
190
  // ^?
196
191
 
197
- // FIXME: There should not be a `{}` in the array
198
192
  expectTypeOf<_JoinOutPosts>().toEqualTypeOf<
199
193
  {
200
- id: FragnoId;
201
194
  title: string;
202
- content: string;
203
- userId: FragnoReference;
204
195
  }[]
205
196
  >();
206
197
  });
198
+
199
+ it("preserves nested select narrowing in join builder", () => {
200
+ const builder = new JoinFindBuilder("users", testSchema.tables.users);
201
+
202
+ const _builderOut = builder.join((jb) =>
203
+ jb.posts((pb) => pb.select(["title"]).join((jb2) => jb2.author((ab) => ab.select(["name"])))),
204
+ );
205
+
206
+ type JoinOut = InferJoinOutPrettify<typeof _builderOut>;
207
+ type Post = Prettify<JoinOut["posts"][number]>;
208
+ type PostTitle = Post["title"];
209
+ type Author = Prettify<NonNullable<Post["author"]>>;
210
+
211
+ expectTypeOf<PostTitle>().toEqualTypeOf<string>();
212
+ expectTypeOf<Author>().toEqualTypeOf<{ name: string }>();
213
+ });
214
+
215
+ it("preserves nested select narrowing via UOW find", async () => {
216
+ const uow = createTestUOW();
217
+
218
+ const uow1 = uow.find("users", (b) =>
219
+ b
220
+ .whereIndex("primary")
221
+ .join((jb) =>
222
+ jb.posts((pb) =>
223
+ pb.select(["title"]).join((jb2) => jb2.author((ab) => ab.select(["name"]))),
224
+ ),
225
+ ),
226
+ );
227
+
228
+ const [_userResult] = await uow1.executeRetrieve();
229
+ type User = RecursivePrettify<(typeof _userResult)[number]>;
230
+ type Post = Prettify<User["posts"][number]>;
231
+ type PostTitle = Post["title"];
232
+ type Author = Prettify<NonNullable<Post["author"]>>;
233
+
234
+ expectTypeOf<PostTitle>().toEqualTypeOf<string>();
235
+ expectTypeOf<Author>().toEqualTypeOf<{ name: string }>();
236
+ });
207
237
  });
@@ -1,5 +1,8 @@
1
1
  import { describe, it, expect, assert, expectTypeOf } from "vitest";
2
+
2
3
  import { column, schema, idColumn, FragnoId } from "../../schema/create";
4
+ import { createIndexedBuilder } from "../condition-builder";
5
+ import type { SimpleQueryInterface } from "../simple-query-interface";
3
6
  import {
4
7
  type UOWCompiler,
5
8
  type UOWDecoder,
@@ -8,8 +11,6 @@ import {
8
11
  type InferIdColumnName,
9
12
  type IndexColumns,
10
13
  } from "./unit-of-work";
11
- import { createIndexedBuilder } from "../condition-builder";
12
- import type { SimpleQueryInterface } from "../simple-query-interface";
13
14
 
14
15
  // Mock compiler and executor for testing
15
16
  function createMockCompiler(): UOWCompiler<unknown> {
@@ -1909,3 +1910,28 @@ describe("findFirst convenience method", () => {
1909
1910
  expect(ops[0]?.indexName).toBe("_primary");
1910
1911
  });
1911
1912
  });
1913
+
1914
+ describe("triggerHook namespace resolution", () => {
1915
+ it("should fall back to schema name when namespace is null", () => {
1916
+ const hooksSchema = schema("hooks_test", (s) =>
1917
+ s.addTable("events", (t) => t.addColumn("id", idColumn())),
1918
+ );
1919
+ const uow = createUnitOfWork(createMockCompiler(), createMockExecutor(), createMockDecoder());
1920
+ uow.registerSchema(hooksSchema, null);
1921
+
1922
+ const hooks = {
1923
+ onTest: (_payload: { value: string }) => {},
1924
+ };
1925
+
1926
+ const typedUow = uow.forSchema(hooksSchema, hooks);
1927
+ typedUow.triggerHook("onTest", { value: "ok" });
1928
+
1929
+ const triggeredHooks = uow.getTriggeredHooks();
1930
+ expect(triggeredHooks).toHaveLength(1);
1931
+ expect(triggeredHooks[0]).toMatchObject({
1932
+ namespace: hooksSchema.name,
1933
+ hookName: "onTest",
1934
+ payload: { value: "ok" },
1935
+ });
1936
+ });
1937
+ });
@@ -1,3 +1,4 @@
1
+ import type { TriggeredHook, TriggerHookOptions, HooksMap, HookPayload } from "../../hooks/hooks";
1
2
  import type {
2
3
  AnySchema,
3
4
  AnyTable,
@@ -8,7 +9,13 @@ import type {
8
9
  } from "../../schema/create";
9
10
  import { FragnoId } from "../../schema/create";
10
11
  import { generateId } from "../../schema/generate-id";
12
+ import type { Prettify } from "../../util/types";
11
13
  import type { Condition, ConditionBuilder } from "../condition-builder";
14
+ import { buildCondition } from "../condition-builder";
15
+ import type { CursorResult } from "../cursor";
16
+ import { Cursor } from "../cursor";
17
+ import { dbInterval, dbNow, type DbInterval, type DbIntervalInput, type DbNow } from "../db-now";
18
+ import type { CompiledJoin } from "../orm/orm";
12
19
  import type {
13
20
  SelectClause,
14
21
  TableToInsertValues,
@@ -17,12 +24,6 @@ import type {
17
24
  ExtractSelect,
18
25
  ExtractJoinOut,
19
26
  } from "../simple-query-interface";
20
- import { buildCondition } from "../condition-builder";
21
- import type { CompiledJoin } from "../orm/orm";
22
- import type { CursorResult } from "../cursor";
23
- import { Cursor } from "../cursor";
24
- import type { Prettify } from "../../util/types";
25
- import type { TriggeredHook, TriggerHookOptions, HooksMap, HookPayload } from "../../hooks/hooks";
26
27
 
27
28
  /**
28
29
  * Builder for updateMany operations that supports both whereIndex and set chaining
@@ -33,6 +34,8 @@ export interface UpdateManyBuilder<TTable extends AnyTable> {
33
34
  condition?: (eb: IndexSpecificConditionBuilder<TTable, TIndexName>) => Condition | boolean,
34
35
  ): this;
35
36
  set(values: TableToUpdateValues<TTable>): this;
37
+ now(): DbNow;
38
+ interval(input: DbIntervalInput): DbInterval;
36
39
  }
37
40
 
38
41
  /**
@@ -42,6 +45,12 @@ export type IndexColumns<TIndex extends Index> = TIndex["columnNames"][number];
42
45
 
43
46
  type RemoveEmptyObject<T> = T extends object ? (keyof T extends never ? never : T) : never;
44
47
 
48
+ type ExtractJoinBuilderSelect<T> =
49
+ T extends JoinFindBuilder<infer _Table, infer TSelect, infer _JoinOut> ? TSelect : true;
50
+
51
+ type ExtractJoinBuilderOut<T> =
52
+ T extends JoinFindBuilder<infer _Table, infer _Select, infer TJoinOut> ? TJoinOut : {};
53
+
45
54
  /**
46
55
  * Extract all indexed column names from a table's indexes
47
56
  */
@@ -167,6 +176,7 @@ export type RetrievalOperation<
167
176
  options: FindOptions<TTable, SelectClause<TTable>>;
168
177
  withCursor?: boolean;
169
178
  withSingleResult?: boolean;
179
+ readTracking?: boolean;
170
180
  }
171
181
  | {
172
182
  type: "count";
@@ -366,6 +376,7 @@ export class FindBuilder<
366
376
  `Use either select() or selectCount(), not both.`,
367
377
  );
368
378
  }
379
+ // prettier-ignore
369
380
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
370
381
  (this as any).#selectClause = columns;
371
382
  return this as unknown as FindBuilder<TTable, TNewSelect, TJoinOut>;
@@ -575,6 +586,17 @@ export class UpdateBuilder<TTable extends AnyTable> {
575
586
  return this;
576
587
  }
577
588
 
589
+ /**
590
+ * Database timestamp helper for mutation values.
591
+ */
592
+ now(): DbNow {
593
+ return dbNow();
594
+ }
595
+
596
+ interval(input: DbIntervalInput): DbInterval {
597
+ return dbInterval(input);
598
+ }
599
+
578
600
  /**
579
601
  * Enable version checking for optimistic concurrency control
580
602
  * @throws Error if the ID is just a string (no version available)
@@ -711,6 +733,7 @@ export class JoinFindBuilder<
711
733
  select<const TNewSelect extends SelectClause<TTable>>(
712
734
  columns: TNewSelect,
713
735
  ): JoinFindBuilder<TTable, TNewSelect, TJoinOut> {
736
+ // prettier-ignore
714
737
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
715
738
  (this as any).#selectClause = columns;
716
739
  return this as unknown as JoinFindBuilder<TTable, TNewSelect, TJoinOut>;
@@ -809,15 +832,22 @@ export type IndexedJoinBuilder<TTable extends AnyTable, TJoinOut> = {
809
832
  infer TRelationType,
810
833
  infer TTargetTable
811
834
  >
812
- ? <TSelect extends SelectClause<TTable["relations"][K]["table"]> = true, TNestedJoinOut = {}>(
813
- builderFn?: (
814
- builder: JoinFindBuilder<TTable["relations"][K]["table"]>,
815
- ) => JoinFindBuilder<TTable["relations"][K]["table"], TSelect, TNestedJoinOut>,
835
+ ? <
836
+ TBuilderFn extends (builder: JoinFindBuilder<TTable["relations"][K]["table"]>) => unknown =
837
+ (
838
+ builder: JoinFindBuilder<TTable["relations"][K]["table"]>,
839
+ ) => JoinFindBuilder<TTable["relations"][K]["table"]>,
840
+ >(
841
+ builderFn?: TBuilderFn,
816
842
  ) => IndexedJoinBuilder<
817
843
  TTable,
818
844
  TJoinOut & {
819
845
  [P in K]: MapRelationType<
820
- SelectResult<TTargetTable, TNestedJoinOut, TSelect>
846
+ SelectResult<
847
+ TTargetTable,
848
+ ExtractJoinBuilderOut<ReturnType<TBuilderFn>>,
849
+ ExtractJoinBuilderSelect<ReturnType<TBuilderFn>>
850
+ >
821
851
  >[TRelationType];
822
852
  }
823
853
  >
@@ -943,8 +973,14 @@ export interface IUnitOfWork {
943
973
  // Schema registration (for cross-fragment operations like hooks)
944
974
  registerSchema(schema: AnySchema, namespace: string | null): void;
945
975
 
946
- // Hook triggering (schema-agnostic, string-based hook names)
947
- triggerHook(hookName: string, payload: unknown, options?: TriggerHookOptions): void;
976
+ // Hook triggering (schema-agnostic, string-based hook names).
977
+ // Namespace identifies which fragment/dispatcher owns this hook.
978
+ triggerHook(
979
+ namespace: string,
980
+ hookName: string,
981
+ payload: unknown,
982
+ options?: TriggerHookOptions,
983
+ ): void;
948
984
 
949
985
  getTriggeredHooks(): readonly TriggeredHook[];
950
986
  }
@@ -956,8 +992,10 @@ export interface IUnitOfWork {
956
992
  *
957
993
  * Note: This is just a marker interface. Restriction is enforced by the UnitOfWork class itself.
958
994
  */
959
- export interface IUnitOfWorkRestricted
960
- extends Omit<IUnitOfWork, "executeRetrieve" | "executeMutations"> {}
995
+ export interface IUnitOfWorkRestricted extends Omit<
996
+ IUnitOfWork,
997
+ "executeRetrieve" | "executeMutations"
998
+ > {}
961
999
 
962
1000
  export type UOWInstrumentationPhase =
963
1001
  | "beforeRetrieve"
@@ -1268,6 +1306,7 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
1268
1306
 
1269
1307
  #retrievalResults?: unknown[];
1270
1308
  #createdInternalIds: (bigint | null)[] = [];
1309
+ #readTrackingEnabled = false;
1271
1310
 
1272
1311
  // Phase coordination promises
1273
1312
  #retrievalPhaseDeferred = new DeferredPromise<unknown[]>();
@@ -1411,6 +1450,7 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
1411
1450
  child.#mutationOps = this.#mutationOps;
1412
1451
  child.#retrievalResults = this.#retrievalResults;
1413
1452
  child.#createdInternalIds = this.#createdInternalIds;
1453
+ child.#readTrackingEnabled = this.#readTrackingEnabled;
1414
1454
  child.#retrievalPhaseDeferred = this.#retrievalPhaseDeferred;
1415
1455
  child.#mutationPhaseDeferred = this.#mutationPhaseDeferred;
1416
1456
  child.#retrievalError = this.#retrievalError;
@@ -1460,6 +1500,7 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
1460
1500
  this.#mutationOps = [];
1461
1501
  this.#retrievalResults = undefined;
1462
1502
  this.#createdInternalIds = [];
1503
+ this.#readTrackingEnabled = false;
1463
1504
 
1464
1505
  // Reset state
1465
1506
  this.#state = "building-retrieval";
@@ -1480,8 +1521,14 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
1480
1521
  /**
1481
1522
  * Trigger a hook to be executed after the transaction commits.
1482
1523
  */
1483
- triggerHook(hookName: string, payload: unknown, options?: TriggerHookOptions): void {
1524
+ triggerHook(
1525
+ namespace: string,
1526
+ hookName: string,
1527
+ payload: unknown,
1528
+ options?: TriggerHookOptions,
1529
+ ): void {
1484
1530
  this.#triggeredHooks.push({
1531
+ namespace,
1485
1532
  hookName,
1486
1533
  payload,
1487
1534
  options,
@@ -1499,6 +1546,14 @@ export class UnitOfWork<const TRawInput = unknown> implements IUnitOfWork {
1499
1546
  return this.#coordinator.parent?.state ?? this.#state;
1500
1547
  }
1501
1548
 
1549
+ enableReadTracking(): void {
1550
+ this.#readTrackingEnabled = true;
1551
+ }
1552
+
1553
+ get readTrackingEnabled(): boolean {
1554
+ return this.#readTrackingEnabled;
1555
+ }
1556
+
1502
1557
  get name(): string | undefined {
1503
1558
  return this.#name;
1504
1559
  }
@@ -1830,8 +1885,7 @@ export class TypedUnitOfWork<
1830
1885
  const TRetrievalResults extends unknown[] = [],
1831
1886
  const TRawInput = unknown,
1832
1887
  const THooks extends HooksMap = {},
1833
- > implements IUnitOfWork
1834
- {
1888
+ > {
1835
1889
  #schema: TSchema;
1836
1890
  #namespace?: string | null;
1837
1891
  #uow: UnitOfWork<TRawInput>;
@@ -1844,6 +1898,9 @@ export class TypedUnitOfWork<
1844
1898
  this.#uow = uow;
1845
1899
  }
1846
1900
 
1901
+ /**
1902
+ * Type-only access to retrieval results for this typed UOW.
1903
+ */
1847
1904
  get $results(): Prettify<TRetrievalResults> {
1848
1905
  throw new Error("type only");
1849
1906
  }
@@ -1931,6 +1988,20 @@ export class TypedUnitOfWork<
1931
1988
  return this.#uow.forSchema<TOtherSchema, TOtherHooks>(schema, hooks);
1932
1989
  }
1933
1990
 
1991
+ /**
1992
+ * Database timestamp helper for inserts.
1993
+ */
1994
+ now(): DbNow {
1995
+ return dbNow();
1996
+ }
1997
+
1998
+ /**
1999
+ * Build a database interval for use with now().plus(...).
2000
+ */
2001
+ interval(input: DbIntervalInput): DbInterval {
2002
+ return dbInterval(input);
2003
+ }
2004
+
1934
2005
  registerSchema(schema: AnySchema, namespace: string | null): void {
1935
2006
  this.#uow.registerSchema(schema, namespace);
1936
2007
  }
@@ -2008,6 +2079,7 @@ export class TypedUnitOfWork<
2008
2079
  indexName,
2009
2080
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2010
2081
  options: options as any,
2082
+ readTracking: this.#uow.readTrackingEnabled,
2011
2083
  });
2012
2084
 
2013
2085
  // Track which operation index belongs to this view
@@ -2086,6 +2158,7 @@ export class TypedUnitOfWork<
2086
2158
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2087
2159
  options: options as any,
2088
2160
  withSingleResult: true,
2161
+ readTracking: this.#uow.readTrackingEnabled,
2089
2162
  });
2090
2163
 
2091
2164
  // Track which operation index belongs to this view
@@ -2134,6 +2207,7 @@ export class TypedUnitOfWork<
2134
2207
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2135
2208
  options: options as any,
2136
2209
  withCursor: true,
2210
+ readTracking: this.#uow.readTrackingEnabled,
2137
2211
  });
2138
2212
 
2139
2213
  // Track which operation index belongs to this view
@@ -2290,15 +2364,27 @@ export class TypedUnitOfWork<
2290
2364
  throw new Error("type only");
2291
2365
  }
2292
2366
 
2367
+ get namespace(): string | null | undefined {
2368
+ return this.#namespace;
2369
+ }
2370
+
2293
2371
  /**
2294
2372
  * Trigger a hook to be executed after the transaction commits.
2373
+ * The namespace is automatically injected from this typed view's schema registration.
2295
2374
  */
2296
2375
  triggerHook<K extends keyof THooks & string>(
2297
2376
  hookName: K,
2298
2377
  payload: HookPayload<THooks[K]>,
2299
2378
  options?: TriggerHookOptions,
2300
2379
  ): void {
2301
- this.#uow.triggerHook(hookName, payload, options);
2380
+ if (this.#namespace === undefined) {
2381
+ throw new Error(
2382
+ "Cannot trigger hook: schema has no registered namespace. " +
2383
+ "Ensure the schema is registered with a namespace via registerSchema().",
2384
+ );
2385
+ }
2386
+ const hookNamespace = this.#namespace ?? this.#schema.name;
2387
+ this.#uow.triggerHook(hookNamespace, hookName, payload, options);
2302
2388
  }
2303
2389
 
2304
2390
  getTriggeredHooks(): ReadonlyArray<TriggeredHook> {
@@ -1,12 +1,13 @@
1
1
  import { assert, describe, expect, it } from "vitest";
2
- import { column, idColumn, referenceColumn, schema, FragnoId } from "../schema/create";
3
- import { decodeResult } from "./value-decoding";
2
+
4
3
  import {
5
4
  SQLocalDriverConfig,
6
5
  NodePostgresDriverConfig,
7
6
  PGLiteDriverConfig,
8
7
  MySQL2DriverConfig,
9
8
  } from "../adapters/generic-sql/driver-config";
9
+ import { column, idColumn, referenceColumn, schema, FragnoId } from "../schema/create";
10
+ import { decodeResult } from "./value-decoding";
10
11
 
11
12
  describe("decodeResult", () => {
12
13
  const testSchema = schema("test", (s) => {
@@ -33,6 +34,11 @@ describe("decodeResult", () => {
33
34
  type: "one",
34
35
  from: { table: "posts", column: "userId" },
35
36
  to: { table: "users", column: "id" },
37
+ })
38
+ .addReference("posts", {
39
+ type: "many",
40
+ from: { table: "users", column: "id" },
41
+ to: { table: "posts", column: "userId" },
36
42
  });
37
43
  });
38
44
 
@@ -300,6 +306,48 @@ describe("decodeResult", () => {
300
306
  expect(author["id"].internalId).toBe(BigInt(200));
301
307
  expect(author["name"]).toBe("Alice");
302
308
  });
309
+
310
+ it("should return null for missing one relations when internal id is null", () => {
311
+ const result = decodeResult(
312
+ {
313
+ id: "post1",
314
+ title: "My Post",
315
+ "author:id": null,
316
+ "author:_internalId": null,
317
+ "author:_version": null,
318
+ "author:name": null,
319
+ },
320
+ postsTable,
321
+ sqliteConfig,
322
+ );
323
+
324
+ expect(result).toEqual({
325
+ id: "post1",
326
+ title: "My Post",
327
+ author: null,
328
+ });
329
+ });
330
+
331
+ it("should return empty array for missing many relations when internal id is null", () => {
332
+ const result = decodeResult(
333
+ {
334
+ id: "user1",
335
+ name: "Alice",
336
+ "posts:id": null,
337
+ "posts:_internalId": null,
338
+ "posts:_version": null,
339
+ "posts:title": null,
340
+ },
341
+ usersTable,
342
+ sqliteConfig,
343
+ );
344
+
345
+ expect(result).toEqual({
346
+ id: "user1",
347
+ name: "Alice",
348
+ posts: [],
349
+ });
350
+ });
303
351
  });
304
352
 
305
353
  describe("complete record decoding", () => {
@@ -1,9 +1,12 @@
1
- import type { AnyTable } from "../schema/create";
2
- import { createSQLSerializer } from "./serialize/create-sql-serializer";
3
- import { FragnoId, FragnoReference } from "../schema/create";
4
1
  import type { DriverConfig } from "../adapters/generic-sql/driver-config";
5
2
  import type { SQLiteStorageMode } from "../adapters/generic-sql/sqlite-storage";
6
3
  import type { NamingResolver } from "../naming/sql-naming";
4
+ import type { AnyTable } from "../schema/create";
5
+ import { FragnoId, FragnoReference } from "../schema/create";
6
+ import { createSQLSerializer } from "./serialize/create-sql-serializer";
7
+
8
+ const isNullish = (value: unknown): value is null | undefined =>
9
+ value === null || value === undefined;
7
10
 
8
11
  /**
9
12
  * Decodes a database result record to application format.
@@ -84,9 +87,19 @@ export function decodeResult(
84
87
  continue;
85
88
  }
86
89
 
90
+ const relationRow = relationData[relationName];
91
+ const internalIdKey = relation.table.getInternalIdColumn().name;
92
+ if (
93
+ Object.prototype.hasOwnProperty.call(relationRow, internalIdKey) &&
94
+ isNullish(relationRow[internalIdKey])
95
+ ) {
96
+ output[relationName] = relation.type === "many" ? [] : null;
97
+ continue;
98
+ }
99
+
87
100
  // Recursively decode the relation data
88
101
  output[relationName] = decodeResult(
89
- relationData[relationName],
102
+ relationRow,
90
103
  relation.table,
91
104
  driverConfig,
92
105
  sqliteStorageMode,
@@ -1,4 +1,5 @@
1
1
  import { describe, expect, it } from "vitest";
2
+
2
3
  import {
3
4
  column,
4
5
  FragnoId,
@@ -1,3 +1,4 @@
1
+ import type { NamingResolver } from "../naming/sql-naming";
1
2
  import type { AnyTable, AnyColumn } from "../schema/create";
2
3
  import { FragnoId, FragnoReference } from "../schema/create";
3
4
  import {
@@ -5,7 +6,6 @@ import {
5
6
  generateRuntimeDefault,
6
7
  type RuntimeDefaultContext,
7
8
  } from "./column-defaults";
8
- import type { NamingResolver } from "../naming/sql-naming";
9
9
 
10
10
  /**
11
11
  * Marker class for reference column values that need subquery resolution.