@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
@@ -0,0 +1,328 @@
1
+ import type { OutboxEntry } from "../outbox/outbox";
2
+ import { ConcurrencyConflictError } from "../query/unit-of-work/execute-unit-of-work";
3
+ import type { SubmitResponse, SubmitConflictReason, SyncCommandDefinition } from "./types";
4
+
5
+ export const DEFAULT_MAX_COMMANDS_PER_SUBMIT = 100;
6
+ export const DEFAULT_MAX_UNSEEN_MUTATIONS = 10_000;
7
+
8
+ export type SyncRequestRecord = {
9
+ requestId: string;
10
+ status: "applied" | "conflict";
11
+ confirmedCommandIds: string[];
12
+ conflictCommandId?: string;
13
+ baseVersionstamp?: string;
14
+ lastVersionstamp?: string;
15
+ };
16
+
17
+ export type SyncCommandResolution = {
18
+ command: SyncCommandDefinition;
19
+ namespace: string | null;
20
+ };
21
+
22
+ export type SyncSubmitRuntime = {
23
+ getAdapterIdentity: () => Promise<string>;
24
+ listOutboxEntries: (afterVersionstamp?: string) => Promise<OutboxEntry[]>;
25
+ countOutboxMutations: (afterVersionstamp?: string) => Promise<number>;
26
+ getSyncRequest: (requestId: string) => Promise<SyncRequestRecord | undefined>;
27
+ storeSyncRequest: (record: SyncRequestRecord) => Promise<void>;
28
+ resolveCommand: (
29
+ fragment: string,
30
+ schema: string,
31
+ name: string,
32
+ ) => SyncCommandResolution | undefined;
33
+ createCommandContext: (command: SyncCommandDefinition) => unknown;
34
+ executeCommand: (command: SyncCommandDefinition, input: unknown, ctx: unknown) => Promise<void>;
35
+ maxCommandsPerSubmit?: number;
36
+ maxUnseenMutations?: number;
37
+ };
38
+
39
+ export type SyncSubmitError = {
40
+ status: "error";
41
+ statusCode: number;
42
+ body: {
43
+ error: {
44
+ code: string;
45
+ message: string;
46
+ detail?: string;
47
+ };
48
+ };
49
+ };
50
+
51
+ export type SyncSubmitResult =
52
+ | {
53
+ status: "ok";
54
+ response: SubmitResponse;
55
+ }
56
+ | SyncSubmitError;
57
+
58
+ const VALID_CONFLICT_RESOLUTION = new Set(["server", "disabled"] as const);
59
+ const VERSIONSTAMP_REGEX = /^[0-9a-f]{24}$/i;
60
+
61
+ const isObject = (value: unknown): value is Record<string, unknown> =>
62
+ value !== null && typeof value === "object";
63
+
64
+ const isNonEmptyString = (value: unknown): value is string =>
65
+ typeof value === "string" && value.trim().length > 0;
66
+
67
+ const normalizeVersionstamp = (value: string | undefined): string | undefined =>
68
+ value ? value.toLowerCase() : undefined;
69
+
70
+ const isValidVersionstamp = (value: string): boolean => VERSIONSTAMP_REGEX.test(value);
71
+
72
+ const buildError = (code: string, message: string, statusCode = 400): SyncSubmitError => ({
73
+ status: "error",
74
+ statusCode,
75
+ body: {
76
+ error: {
77
+ code,
78
+ message,
79
+ },
80
+ },
81
+ });
82
+
83
+ const withEntries = async (
84
+ runtime: SyncSubmitRuntime,
85
+ baseVersionstamp: string | undefined,
86
+ ): Promise<{ entries: OutboxEntry[]; lastVersionstamp?: string }> => {
87
+ const entries = await runtime.listOutboxEntries(baseVersionstamp);
88
+ const lastVersionstamp =
89
+ entries.length > 0 ? entries[entries.length - 1]?.versionstamp : undefined;
90
+ return { entries, lastVersionstamp };
91
+ };
92
+
93
+ export const submitSyncRequest = async (
94
+ raw: unknown,
95
+ runtime: SyncSubmitRuntime,
96
+ ): Promise<SyncSubmitResult> => {
97
+ if (!isObject(raw)) {
98
+ return buildError("INVALID_REQUEST", "Request body must be an object.");
99
+ }
100
+
101
+ const requestId = raw["requestId"];
102
+ if (!isNonEmptyString(requestId)) {
103
+ return buildError("INVALID_REQUEST", "requestId is required.");
104
+ }
105
+
106
+ const adapterIdentity = raw["adapterIdentity"];
107
+ if (!isNonEmptyString(adapterIdentity)) {
108
+ return buildError("INVALID_REQUEST", "adapterIdentity is required.");
109
+ }
110
+
111
+ const conflictResolutionStrategy = raw["conflictResolutionStrategy"];
112
+ if (
113
+ !isNonEmptyString(conflictResolutionStrategy) ||
114
+ !VALID_CONFLICT_RESOLUTION.has(conflictResolutionStrategy as "server" | "disabled")
115
+ ) {
116
+ return buildError(
117
+ "INVALID_REQUEST",
118
+ 'conflictResolutionStrategy must be "server" or "disabled".',
119
+ );
120
+ }
121
+
122
+ const baseVersionstamp = raw["baseVersionstamp"];
123
+ if (baseVersionstamp !== undefined && !isNonEmptyString(baseVersionstamp)) {
124
+ return buildError("INVALID_REQUEST", "baseVersionstamp must be a non-empty string.");
125
+ }
126
+
127
+ const normalizedBaseVersionstamp =
128
+ baseVersionstamp !== undefined ? normalizeVersionstamp(baseVersionstamp) : undefined;
129
+ if (normalizedBaseVersionstamp && !isValidVersionstamp(normalizedBaseVersionstamp)) {
130
+ return buildError("INVALID_VERSIONSTAMP", "baseVersionstamp must be 24 hex characters.");
131
+ }
132
+
133
+ const commands = raw["commands"];
134
+ if (!Array.isArray(commands)) {
135
+ return buildError("INVALID_REQUEST", "commands must be an array.");
136
+ }
137
+
138
+ const expectedAdapterIdentity = await runtime.getAdapterIdentity();
139
+ if (expectedAdapterIdentity !== adapterIdentity) {
140
+ return buildError(
141
+ "ADAPTER_IDENTITY_MISMATCH",
142
+ "adapterIdentity does not match this adapter.",
143
+ 409,
144
+ );
145
+ }
146
+
147
+ const existing = await runtime.getSyncRequest(requestId);
148
+ if (existing) {
149
+ const { entries, lastVersionstamp } = await withEntries(runtime, normalizedBaseVersionstamp);
150
+ const response: SubmitResponse = {
151
+ status: "conflict",
152
+ requestId,
153
+ confirmedCommandIds: existing.confirmedCommandIds ?? [],
154
+ conflictCommandId: existing.conflictCommandId ?? undefined,
155
+ lastVersionstamp: lastVersionstamp ?? existing.lastVersionstamp ?? undefined,
156
+ entries,
157
+ reason: "already_handled",
158
+ };
159
+ return { status: "ok", response };
160
+ }
161
+
162
+ const maxCommands = runtime.maxCommandsPerSubmit ?? DEFAULT_MAX_COMMANDS_PER_SUBMIT;
163
+ const maxUnseen = runtime.maxUnseenMutations ?? DEFAULT_MAX_UNSEEN_MUTATIONS;
164
+
165
+ if (commands.length === 0) {
166
+ const { entries, lastVersionstamp } = await withEntries(runtime, normalizedBaseVersionstamp);
167
+ const response: SubmitResponse = {
168
+ status: "conflict",
169
+ requestId,
170
+ confirmedCommandIds: [],
171
+ entries,
172
+ lastVersionstamp,
173
+ reason: "no_commands",
174
+ };
175
+ await runtime.storeSyncRequest({
176
+ requestId,
177
+ status: "conflict",
178
+ confirmedCommandIds: [],
179
+ baseVersionstamp: normalizedBaseVersionstamp,
180
+ lastVersionstamp,
181
+ });
182
+ return { status: "ok", response };
183
+ }
184
+
185
+ if (commands.length > maxCommands) {
186
+ const { entries, lastVersionstamp } = await withEntries(runtime, normalizedBaseVersionstamp);
187
+ const response: SubmitResponse = {
188
+ status: "conflict",
189
+ requestId,
190
+ confirmedCommandIds: [],
191
+ entries,
192
+ lastVersionstamp,
193
+ reason: "limit_exceeded",
194
+ };
195
+ await runtime.storeSyncRequest({
196
+ requestId,
197
+ status: "conflict",
198
+ confirmedCommandIds: [],
199
+ baseVersionstamp: normalizedBaseVersionstamp,
200
+ lastVersionstamp,
201
+ });
202
+ return { status: "ok", response };
203
+ }
204
+
205
+ const unseenCount = await runtime.countOutboxMutations(normalizedBaseVersionstamp);
206
+ if (unseenCount > maxUnseen) {
207
+ const { entries, lastVersionstamp } = await withEntries(runtime, normalizedBaseVersionstamp);
208
+ const response: SubmitResponse = {
209
+ status: "conflict",
210
+ requestId,
211
+ confirmedCommandIds: [],
212
+ entries,
213
+ lastVersionstamp,
214
+ reason: "client_far_behind",
215
+ };
216
+ await runtime.storeSyncRequest({
217
+ requestId,
218
+ status: "conflict",
219
+ confirmedCommandIds: [],
220
+ baseVersionstamp: normalizedBaseVersionstamp,
221
+ lastVersionstamp,
222
+ });
223
+ return { status: "ok", response };
224
+ }
225
+
226
+ const confirmedCommandIds: string[] = [];
227
+ let conflictCommandId: string | undefined;
228
+ let conflictReason: SubmitConflictReason | undefined;
229
+
230
+ for (const command of commands) {
231
+ if (!isObject(command)) {
232
+ return buildError("INVALID_COMMAND", "Command entries must be objects.");
233
+ }
234
+
235
+ const commandId = command["id"];
236
+ const commandName = command["name"];
237
+ const target = command["target"];
238
+
239
+ if (!isNonEmptyString(commandId) || !isNonEmptyString(commandName) || !isObject(target)) {
240
+ return buildError("INVALID_COMMAND", "Command entries must include id, name, and target.");
241
+ }
242
+
243
+ const fragmentName = target["fragment"];
244
+ const schemaName = target["schema"];
245
+
246
+ if (!isNonEmptyString(fragmentName) || !isNonEmptyString(schemaName)) {
247
+ return buildError("INVALID_COMMAND", "Command target must include fragment and schema.");
248
+ }
249
+
250
+ const resolved = runtime.resolveCommand(fragmentName, schemaName, commandName);
251
+ if (!resolved) {
252
+ return buildError("UNKNOWN_COMMAND", "Command target or name was not recognized.");
253
+ }
254
+
255
+ const ctx = runtime.createCommandContext(resolved.command);
256
+
257
+ try {
258
+ await runtime.executeCommand(resolved.command, command["input"], ctx);
259
+ confirmedCommandIds.push(commandId);
260
+ } catch (error) {
261
+ if (error instanceof ConcurrencyConflictError) {
262
+ conflictCommandId = commandId;
263
+ conflictReason = "write_congestion";
264
+ break;
265
+ }
266
+ await runtime.storeSyncRequest({
267
+ requestId,
268
+ status: "conflict",
269
+ confirmedCommandIds,
270
+ conflictCommandId: commandId,
271
+ baseVersionstamp: normalizedBaseVersionstamp,
272
+ });
273
+ return {
274
+ status: "error",
275
+ statusCode: 500,
276
+ body: {
277
+ error: {
278
+ code: "SYNC_COMMAND_FAILED",
279
+ message: error instanceof Error ? error.message : "Sync command failed.",
280
+ },
281
+ },
282
+ };
283
+ }
284
+ }
285
+
286
+ const { entries, lastVersionstamp } = await withEntries(runtime, normalizedBaseVersionstamp);
287
+
288
+ if (conflictReason) {
289
+ const response: SubmitResponse = {
290
+ status: "conflict",
291
+ requestId,
292
+ confirmedCommandIds,
293
+ conflictCommandId,
294
+ entries,
295
+ lastVersionstamp,
296
+ reason: conflictReason,
297
+ };
298
+
299
+ await runtime.storeSyncRequest({
300
+ requestId,
301
+ status: "conflict",
302
+ confirmedCommandIds,
303
+ conflictCommandId,
304
+ baseVersionstamp: normalizedBaseVersionstamp,
305
+ lastVersionstamp,
306
+ });
307
+
308
+ return { status: "ok", response };
309
+ }
310
+
311
+ const response: SubmitResponse = {
312
+ status: "applied",
313
+ requestId,
314
+ confirmedCommandIds,
315
+ entries,
316
+ lastVersionstamp,
317
+ };
318
+
319
+ await runtime.storeSyncRequest({
320
+ requestId,
321
+ status: "applied",
322
+ confirmedCommandIds,
323
+ baseVersionstamp: normalizedBaseVersionstamp,
324
+ lastVersionstamp,
325
+ });
326
+
327
+ return { status: "ok", response };
328
+ };
@@ -0,0 +1,80 @@
1
+ import type { RequestThisContext } from "@fragno-dev/core";
2
+
3
+ import type { OutboxEntry } from "../outbox/outbox";
4
+ import type {
5
+ ExecuteTxOptions,
6
+ HandlerTxBuilder,
7
+ } from "../query/unit-of-work/execute-unit-of-work";
8
+
9
+ export type SubmitRequest = {
10
+ baseVersionstamp?: string;
11
+ requestId: string;
12
+ conflictResolutionStrategy: "server" | "disabled";
13
+ adapterIdentity: string;
14
+ commands: Array<{
15
+ id: string;
16
+ name: string;
17
+ target: {
18
+ fragment: string;
19
+ schema: string;
20
+ };
21
+ input: unknown;
22
+ }>;
23
+ };
24
+
25
+ export type SubmitConflictReason =
26
+ | "conflict"
27
+ | "write_congestion"
28
+ | "client_far_behind"
29
+ | "no_commands"
30
+ | "already_handled"
31
+ | "limit_exceeded";
32
+
33
+ export type SubmitAppliedResponse = {
34
+ status: "applied";
35
+ requestId: string;
36
+ confirmedCommandIds: string[];
37
+ lastVersionstamp?: string;
38
+ entries: OutboxEntry[];
39
+ };
40
+
41
+ export type SubmitConflictResponse = {
42
+ status: "conflict";
43
+ requestId: string;
44
+ confirmedCommandIds: string[];
45
+ conflictCommandId?: string;
46
+ lastVersionstamp?: string;
47
+ entries: OutboxEntry[];
48
+ reason: SubmitConflictReason;
49
+ };
50
+
51
+ export type SubmitResponse = SubmitAppliedResponse | SubmitConflictResponse;
52
+
53
+ export type SyncCommandTxFactory = (
54
+ options?: Omit<ExecuteTxOptions, "createUnitOfWork">,
55
+ ) => HandlerTxBuilder<readonly [], [], [], unknown, unknown, false, false, false, false, {}>;
56
+
57
+ export type SyncCommandHandler<TInput = unknown, TContext = unknown> = (args: {
58
+ input: TInput;
59
+ tx: SyncCommandTxFactory;
60
+ ctx: TContext;
61
+ }) => Promise<unknown>;
62
+
63
+ export type SyncCommandDefinition<TInput = unknown, TContext = unknown> = {
64
+ name: string;
65
+ handler: SyncCommandHandler<TInput, TContext>;
66
+ createServerContext?: (requestContext: RequestThisContext) => TContext;
67
+ };
68
+
69
+ export type SyncCommandRegistry = {
70
+ schemaName: string;
71
+ commands: Map<string, SyncCommandDefinition>;
72
+ getCommand: (name: string) => SyncCommandDefinition | undefined;
73
+ };
74
+
75
+ export type SyncCommandTargetRegistration = {
76
+ fragmentName: string;
77
+ schemaName: string;
78
+ namespace: string | null;
79
+ commands: Map<string, SyncCommandDefinition>;
80
+ };
@@ -1,10 +1,12 @@
1
1
  import fs from "node:fs";
2
2
  import { createRequire } from "node:module";
3
3
  import path from "node:path";
4
+
4
5
  import { SqliteDialect } from "kysely";
5
- import { SqlAdapter } from "../adapters/generic-sql/generic-sql-adapter";
6
- import { BetterSQLite3DriverConfig } from "../adapters/generic-sql/driver-config";
6
+
7
7
  import type { DatabaseAdapter } from "../adapters/adapters";
8
+ import { BetterSQLite3DriverConfig } from "../adapters/generic-sql/driver-config";
9
+ import { SqlAdapter } from "../adapters/generic-sql/generic-sql-adapter";
8
10
  import type { AnySchema } from "../schema/create";
9
11
  type DatabaseAdapterConfig = {
10
12
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -14,6 +16,14 @@ type DatabaseAdapterConfig = {
14
16
 
15
17
  type BetterSqlite3Constructor = typeof import("better-sqlite3");
16
18
 
19
+ const isCloudflareWorkers = (): boolean => {
20
+ if (typeof globalThis === "undefined") {
21
+ return false;
22
+ }
23
+ const navigatorRef = (globalThis as { navigator?: { userAgent?: string } }).navigator;
24
+ return navigatorRef?.userAgent === "Cloudflare-Workers";
25
+ };
26
+
17
27
  const createNodeRequire = (): NodeRequire | null => {
18
28
  try {
19
29
  const metaUrl = typeof import.meta !== "undefined" ? import.meta.url : undefined;
@@ -27,6 +37,9 @@ const createNodeRequire = (): NodeRequire | null => {
27
37
  };
28
38
 
29
39
  const loadBetterSqlite3 = (): BetterSqlite3Constructor | null => {
40
+ if (isCloudflareWorkers()) {
41
+ return null;
42
+ }
30
43
  const requireFn = createNodeRequire();
31
44
  if (!requireFn) {
32
45
  return null;
@@ -1,10 +1,6 @@
1
- import type { AnySchema } from "./schema/create";
2
- import type {
3
- RequestThisContext,
4
- FragnoPublicConfig,
5
- AnyFragnoInstantiatedFragment,
6
- } from "@fragno-dev/core";
7
- import { FragmentDefinitionBuilder, instantiate } from "@fragno-dev/core";
1
+ import type { RequestThisContext, FragnoPublicConfig, AnyRouteOrFactory } from "@fragno-dev/core";
2
+ import { FragmentDefinitionBuilder } from "@fragno-dev/core";
3
+
8
4
  import {
9
5
  DatabaseFragmentDefinitionBuilder,
10
6
  type DatabaseServiceContext,
@@ -13,22 +9,13 @@ import {
13
9
  type FragnoPublicConfigWithDatabase,
14
10
  type DatabaseRequestStorage,
15
11
  } from "./db-fragment-definition-builder";
16
- import { internalFragmentDef, type InternalFragmentInstance } from "./fragments/internal-fragment";
17
- import { internalFragmentRoutes } from "./fragments/internal-fragment.routes";
18
12
  import type { HooksMap } from "./hooks/hooks";
19
- import { resolveDatabaseAdapter } from "./util/default-database-adapter";
20
-
21
- function shouldExposeOutboxRoutes(
22
- options: FragnoPublicConfigWithDatabase,
23
- schema: AnySchema,
24
- ): boolean {
25
- const adapter = resolveDatabaseAdapter(options, schema) as { outbox?: { enabled?: boolean } };
26
- return adapter.outbox?.enabled ?? false;
27
- }
13
+ import { getInternalFragment, getRegistryForAdapterSync } from "./internal/adapter-registry";
14
+ import type { AnySchema } from "./schema/create";
28
15
 
29
16
  /**
30
17
  * Helper to add database support to a fragment builder.
31
- * Automatically links the internal fragment and adds ImplicitDatabaseDependencies to the TDeps type.
18
+ * Registers the schema with the adapter registry and adds ImplicitDatabaseDependencies to the TDeps type.
32
19
  *
33
20
  * @example
34
21
  * ```typescript
@@ -56,7 +43,7 @@ export function withDatabase<TSchema extends AnySchema>(
56
43
  TServiceThisContext extends RequestThisContext,
57
44
  THandlerThisContext extends RequestThisContext,
58
45
  TRequestStorage,
59
- TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment>,
46
+ TInternalRoutes extends readonly AnyRouteOrFactory[],
60
47
  >(
61
48
  builder: FragmentDefinitionBuilder<
62
49
  TConfig,
@@ -69,7 +56,7 @@ export function withDatabase<TSchema extends AnySchema>(
69
56
  TServiceThisContext,
70
57
  THandlerThisContext,
71
58
  TRequestStorage,
72
- TLinkedFragments
59
+ TInternalRoutes
73
60
  >,
74
61
  ) => DatabaseFragmentDefinitionBuilder<
75
62
  TSchema,
@@ -82,7 +69,7 @@ export function withDatabase<TSchema extends AnySchema>(
82
69
  HooksMap,
83
70
  DatabaseServiceContext<HooksMap>,
84
71
  DatabaseHandlerContext,
85
- TLinkedFragments & { _fragno_internal: InternalFragmentInstance }
72
+ TInternalRoutes
86
73
  > {
87
74
  return <
88
75
  TConfig,
@@ -94,7 +81,7 @@ export function withDatabase<TSchema extends AnySchema>(
94
81
  TServiceThisContext extends RequestThisContext,
95
82
  THandlerThisContext extends RequestThisContext,
96
83
  TRequestStorage,
97
- TLinkedFragments extends Record<string, AnyFragnoInstantiatedFragment>,
84
+ TInternalRoutes extends readonly AnyRouteOrFactory[],
98
85
  >(
99
86
  builder: FragmentDefinitionBuilder<
100
87
  TConfig,
@@ -107,32 +94,9 @@ export function withDatabase<TSchema extends AnySchema>(
107
94
  TServiceThisContext,
108
95
  THandlerThisContext,
109
96
  TRequestStorage,
110
- TLinkedFragments
97
+ TInternalRoutes
111
98
  >,
112
99
  ) => {
113
- const builderWithInternal = builder.withLinkedFragment(
114
- "_fragno_internal",
115
- ({ config, options }) => {
116
- const internalRoutes = shouldExposeOutboxRoutes(
117
- options as FragnoPublicConfigWithDatabase,
118
- schema,
119
- )
120
- ? [internalFragmentRoutes]
121
- : [];
122
-
123
- // Cast is safe: by the time this callback is invoked during fragment instantiation,
124
- // the options will be FragnoPublicConfigWithDatabase (enforced by DatabaseFragmentDefinitionBuilder)
125
- return instantiate(internalFragmentDef)
126
- .withConfig(config as {})
127
- .withOptions({
128
- ...(options as FragnoPublicConfigWithDatabase),
129
- databaseNamespace: null,
130
- })
131
- .withRoutes(internalRoutes)
132
- .build();
133
- },
134
- );
135
-
136
100
  // Cast is safe: we're creating a DatabaseFragmentDefinitionBuilder which internally uses
137
101
  // FragnoPublicConfigWithDatabase, but the input builder uses FragnoPublicConfig.
138
102
  // The database builder's build() method will enforce FragnoPublicConfigWithDatabase at the end.
@@ -150,9 +114,9 @@ export function withDatabase<TSchema extends AnySchema>(
150
114
  {}, // Start with empty hooks, provideHooks() will update this
151
115
  DatabaseServiceContext<{}>,
152
116
  DatabaseHandlerContext,
153
- TLinkedFragments & { _fragno_internal: InternalFragmentInstance }
117
+ TInternalRoutes
154
118
  >(
155
- builderWithInternal as unknown as FragmentDefinitionBuilder<
119
+ builder as unknown as FragmentDefinitionBuilder<
156
120
  TConfig,
157
121
  FragnoPublicConfigWithDatabase,
158
122
  TDeps & ImplicitDatabaseDependencies<TSchema>,
@@ -163,9 +127,15 @@ export function withDatabase<TSchema extends AnySchema>(
163
127
  DatabaseServiceContext<{}>,
164
128
  DatabaseHandlerContext,
165
129
  DatabaseRequestStorage,
166
- TLinkedFragments & { _fragno_internal: InternalFragmentInstance }
130
+ TInternalRoutes
167
131
  >,
168
132
  schema,
133
+ undefined,
134
+ undefined,
135
+ {
136
+ getRegistryForAdapterSync,
137
+ getInternalFragment,
138
+ },
169
139
  );
170
140
  };
171
141
  }
package/tsconfig.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "extends": "@fragno-private/typescript-config/tsconfig.base.json",
2
+ "extends": "@fragno-private/typescript-config/tsconfig.node.json",
3
3
  "compilerOptions": {
4
4
  "outDir": "./dist",
5
5
  "rootDir": ".",
package/tsdown.config.ts CHANGED
@@ -1,28 +1,40 @@
1
1
  import { defineConfig } from "tsdown";
2
2
 
3
- export default defineConfig({
4
- entry: [
5
- "./src/mod.ts",
6
- "./src/id.ts",
7
- "./src/schema/create.ts",
8
- "./src/query/simple-query-interface.ts",
9
- "./src/adapters/adapters.ts",
10
- "./src/adapters/in-memory/index.ts",
11
- "./src/adapters/sql/index.ts",
12
- "./src/adapters/generic-sql/driver-config.ts",
13
- "./src/schema-output/drizzle.ts",
14
- "./src/schema-output/prisma.ts",
15
- "./src/sql-driver/sql-driver.ts",
16
- "./src/sql-driver/dialects/dialects.ts",
17
- "./src/sql-driver/dialects/durable-object-dialect.ts",
18
- "./src/query/unit-of-work/unit-of-work.ts",
19
- "./src/query/cursor.ts",
20
- "./src/fragment.ts",
21
- "./src/db-fragment-definition-builder.ts",
22
- "./src/dispatchers/node/index.ts",
23
- "./src/dispatchers/cloudflare-do/index.ts",
24
- "./src/migration-engine/generation-engine.ts",
25
- ],
26
- dts: true,
27
- unbundle: true,
28
- });
3
+ export default defineConfig([
4
+ {
5
+ entry: [
6
+ "./src/mod.ts",
7
+ "./src/durable-hooks.ts",
8
+ "./src/id.ts",
9
+ "./src/schema/create.ts",
10
+ "./src/query/simple-query-interface.ts",
11
+ "./src/adapters/adapters.ts",
12
+ "./src/adapters/in-memory/index.ts",
13
+ "./src/adapters/sql/index.ts",
14
+ "./src/adapters/generic-sql/driver-config.ts",
15
+ "./src/schema-output/drizzle.ts",
16
+ "./src/schema-output/prisma.ts",
17
+ "./src/client.ts",
18
+ "./src/sync/index.ts",
19
+ "./src/sql-driver/sql-driver.ts",
20
+ "./src/sql-driver/dialects/dialects.ts",
21
+ "./src/sql-driver/dialects/durable-object-dialect.ts",
22
+ "./src/query/unit-of-work/unit-of-work.ts",
23
+ "./src/query/cursor.ts",
24
+ "./src/fragment.ts",
25
+ "./src/db-fragment-definition-builder.ts",
26
+ "./src/dispatchers/node/index.ts",
27
+ "./src/dispatchers/cloudflare-do/index.ts",
28
+ "./src/migration-engine/generation-engine.ts",
29
+ ],
30
+ dts: true,
31
+ unbundle: true,
32
+ },
33
+ {
34
+ entry: ["./src/browser/mod.ts"],
35
+ platform: "browser",
36
+ outDir: "./dist/browser",
37
+ dts: true,
38
+ unbundle: true,
39
+ },
40
+ ]);
package/vitest.config.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { defineConfig } from "vitest/config";
2
+
2
3
  import { baseConfig } from "@fragno-private/vitest-config";
3
4
 
4
5
  export default defineConfig({
@@ -1 +0,0 @@
1
- {"version":3,"file":"durable-hooks-processor.d.ts","names":[],"sources":["../../src/hooks/durable-hooks-processor.ts"],"sourcesContent":[],"mappings":";;;;KAIY,qBAAA;iBACK;EADL,aAAA,EAAA,GAAA,GAEW,OAFU,CAEF,IAFE,GAAA,IAAA,CAAA;EAChB,KAAA,EAAA,GAAA,GAEF,OAFE,CAAA,IAAA,CAAA;EACc,SAAA,EAAA,MAAA;CAAR;AACR,iBAoBC,2BApBD,CAAA,gBAoB6C,SApB7C,CAAA,CAAA,QAAA,EAqBH,qCArBG,CAqBmC,OArBnC,CAAA,CAAA,EAsBZ,qBAtBY,GAAA,IAAA"}