@fragno-dev/db 0.2.2 → 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 (587) hide show
  1. package/.turbo/turbo-build.log +404 -175
  2. package/CHANGELOG.md +109 -0
  3. package/README.md +54 -9
  4. package/dist/adapters/adapters.d.ts +23 -21
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/generic-sql/driver-config.d.ts +16 -1
  8. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/driver-config.js +23 -1
  10. package/dist/adapters/generic-sql/driver-config.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +24 -9
  12. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  13. package/dist/adapters/generic-sql/generic-sql-adapter.js +60 -22
  14. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  15. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +169 -3
  16. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  17. package/dist/adapters/generic-sql/migration/cold-kysely.js.map +1 -1
  18. package/dist/adapters/generic-sql/migration/dialect/mysql.js +25 -6
  19. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  20. package/dist/adapters/generic-sql/migration/dialect/postgres.js +7 -6
  21. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  22. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +193 -16
  23. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  24. package/dist/adapters/generic-sql/migration/executor.d.ts.map +1 -1
  25. package/dist/adapters/generic-sql/migration/executor.js +30 -3
  26. package/dist/adapters/generic-sql/migration/executor.js.map +1 -1
  27. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  28. package/dist/adapters/generic-sql/migration/prepared-migrations.js +9 -9
  29. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  30. package/dist/adapters/generic-sql/migration/sql-generator.js +75 -52
  31. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  32. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +7 -6
  33. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  34. package/dist/adapters/generic-sql/query/cursor-utils.js +42 -4
  35. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/db-now-sql.js +27 -0
  37. package/dist/adapters/generic-sql/query/db-now-sql.js.map +1 -0
  38. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +32 -21
  39. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  40. package/dist/adapters/generic-sql/query/select-builder.js +5 -3
  41. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  42. package/dist/adapters/generic-sql/query/sql-query-compiler.js +49 -18
  43. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  44. package/dist/adapters/generic-sql/query/where-builder.js +43 -29
  45. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  46. package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
  47. package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  48. package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
  49. package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
  50. package/dist/adapters/generic-sql/uow-decoder.js +6 -2
  51. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  52. package/dist/adapters/generic-sql/uow-encoder.js +27 -8
  53. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  54. package/dist/adapters/in-memory/condition-evaluator.js +135 -0
  55. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
  56. package/dist/adapters/in-memory/errors.d.ts +13 -0
  57. package/dist/adapters/in-memory/errors.d.ts.map +1 -0
  58. package/dist/adapters/in-memory/errors.js +23 -0
  59. package/dist/adapters/in-memory/errors.js.map +1 -0
  60. package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
  61. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
  62. package/dist/adapters/in-memory/in-memory-adapter.js +196 -0
  63. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
  64. package/dist/adapters/in-memory/in-memory-uow.js +871 -0
  65. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
  66. package/dist/adapters/in-memory/index.d.ts +4 -0
  67. package/dist/adapters/in-memory/index.js +4 -0
  68. package/dist/adapters/in-memory/options.d.ts +30 -0
  69. package/dist/adapters/in-memory/options.d.ts.map +1 -0
  70. package/dist/adapters/in-memory/options.js +62 -0
  71. package/dist/adapters/in-memory/options.js.map +1 -0
  72. package/dist/adapters/in-memory/reference-resolution.js +26 -0
  73. package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
  74. package/dist/adapters/in-memory/sorted-array-index.js +129 -0
  75. package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
  76. package/dist/adapters/in-memory/store.js +71 -0
  77. package/dist/adapters/in-memory/store.js.map +1 -0
  78. package/dist/adapters/in-memory/value-comparison.js +28 -0
  79. package/dist/adapters/in-memory/value-comparison.js.map +1 -0
  80. package/dist/adapters/shared/from-unit-of-work-compiler.js +51 -24
  81. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  82. package/dist/adapters/shared/uow-operation-compiler.js +11 -11
  83. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  84. package/dist/adapters/sql/index.d.ts +5 -0
  85. package/dist/adapters/sql/index.js +4 -0
  86. package/dist/browser/adapters/adapters.d.ts +61 -0
  87. package/dist/browser/adapters/adapters.d.ts.map +1 -0
  88. package/dist/browser/adapters/generic-sql/migration/executor.d.ts +15 -0
  89. package/dist/browser/adapters/generic-sql/migration/executor.d.ts.map +1 -0
  90. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts +66 -0
  91. package/dist/browser/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -0
  92. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts +11 -0
  93. package/dist/browser/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  94. package/dist/browser/adapters/in-memory/in-memory-adapter.d.ts +5 -0
  95. package/dist/browser/adapters/in-memory/index.d.ts +2 -0
  96. package/dist/browser/adapters/in-memory/options.d.ts +1 -0
  97. package/dist/browser/db-fragment-definition-builder.d.ts +237 -0
  98. package/dist/browser/db-fragment-definition-builder.d.ts.map +1 -0
  99. package/dist/browser/durable-hooks.d.ts +3 -0
  100. package/dist/browser/fragments/internal-fragment.d.ts +317 -0
  101. package/dist/browser/fragments/internal-fragment.d.ts.map +1 -0
  102. package/dist/browser/fragments/internal-fragment.schema.d.ts +1 -0
  103. package/dist/browser/hooks/durable-hooks-logger.d.ts +10 -0
  104. package/dist/browser/hooks/durable-hooks-logger.d.ts.map +1 -0
  105. package/dist/browser/hooks/hooks.d.ts +146 -0
  106. package/dist/browser/hooks/hooks.d.ts.map +1 -0
  107. package/dist/browser/id.js +1 -0
  108. package/dist/browser/internal/adapter-registry.d.ts +4 -0
  109. package/dist/browser/internal/outbox-state.d.ts +2 -0
  110. package/dist/browser/mod.d.ts +15 -0
  111. package/dist/browser/mod.d.ts.map +1 -0
  112. package/dist/browser/mod.js +17 -0
  113. package/dist/browser/mod.js.map +1 -0
  114. package/dist/browser/mod2.d.ts +48 -0
  115. package/dist/browser/mod2.d.ts.map +1 -0
  116. package/dist/browser/naming/sql-naming.d.ts +19 -0
  117. package/dist/browser/naming/sql-naming.d.ts.map +1 -0
  118. package/dist/browser/outbox/outbox.d.ts +21 -0
  119. package/dist/browser/outbox/outbox.d.ts.map +1 -0
  120. package/dist/browser/query/column-defaults.js +1 -0
  121. package/dist/browser/query/condition-builder.d.ts +44 -0
  122. package/dist/browser/query/condition-builder.d.ts.map +1 -0
  123. package/dist/browser/query/condition-builder.js +97 -0
  124. package/dist/browser/query/condition-builder.js.map +1 -0
  125. package/dist/browser/query/cursor.d.ts +105 -0
  126. package/dist/browser/query/cursor.d.ts.map +1 -0
  127. package/dist/browser/query/cursor.js +150 -0
  128. package/dist/browser/query/cursor.js.map +1 -0
  129. package/dist/browser/query/db-now.d.ts +22 -0
  130. package/dist/browser/query/db-now.d.ts.map +1 -0
  131. package/dist/browser/query/db-now.js +33 -0
  132. package/dist/browser/query/db-now.js.map +1 -0
  133. package/dist/browser/query/orm/orm.d.ts +18 -0
  134. package/dist/browser/query/orm/orm.d.ts.map +1 -0
  135. package/dist/browser/query/simple-query-interface.d.ts +108 -0
  136. package/dist/browser/query/simple-query-interface.d.ts.map +1 -0
  137. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts +423 -0
  138. package/dist/browser/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -0
  139. package/dist/browser/query/unit-of-work/execute-unit-of-work.js +507 -0
  140. package/dist/browser/query/unit-of-work/execute-unit-of-work.js.map +1 -0
  141. package/dist/browser/query/unit-of-work/retry-policy.d.ts +23 -0
  142. package/dist/browser/query/unit-of-work/retry-policy.d.ts.map +1 -0
  143. package/dist/browser/query/unit-of-work/retry-policy.js +40 -0
  144. package/dist/browser/query/unit-of-work/retry-policy.js.map +1 -0
  145. package/dist/browser/query/unit-of-work/unit-of-work.d.ts +703 -0
  146. package/dist/browser/query/unit-of-work/unit-of-work.d.ts.map +1 -0
  147. package/dist/browser/query/unit-of-work/unit-of-work.js +1206 -0
  148. package/dist/browser/query/unit-of-work/unit-of-work.js.map +1 -0
  149. package/dist/browser/query/value-encoding.js +38 -0
  150. package/dist/browser/query/value-encoding.js.map +1 -0
  151. package/dist/browser/schema/create.d.ts +326 -0
  152. package/dist/browser/schema/create.d.ts.map +1 -0
  153. package/dist/browser/schema/create.js +89 -0
  154. package/dist/browser/schema/create.js.map +1 -0
  155. package/dist/browser/schema/generate-id.js +28 -0
  156. package/dist/browser/schema/generate-id.js.map +1 -0
  157. package/dist/browser/shared/providers.d.ts +6 -0
  158. package/dist/browser/shared/providers.d.ts.map +1 -0
  159. package/dist/browser/sql-driver/connection/connection-provider.d.ts +13 -0
  160. package/dist/browser/sql-driver/connection/connection-provider.d.ts.map +1 -0
  161. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts +7 -0
  162. package/dist/browser/sql-driver/dialect-adapter/dialect-adapter.d.ts.map +1 -0
  163. package/dist/browser/sql-driver/driver/runtime-driver.d.ts +23 -0
  164. package/dist/browser/sql-driver/driver/runtime-driver.d.ts.map +1 -0
  165. package/dist/browser/sql-driver/query-executor/plugin.d.ts +17 -0
  166. package/dist/browser/sql-driver/query-executor/plugin.d.ts.map +1 -0
  167. package/dist/browser/sql-driver/query-executor/query-executor.d.ts +36 -0
  168. package/dist/browser/sql-driver/query-executor/query-executor.d.ts.map +1 -0
  169. package/dist/browser/sql-driver/sql-driver-adapter.d.ts +29 -0
  170. package/dist/browser/sql-driver/sql-driver-adapter.d.ts.map +1 -0
  171. package/dist/browser/sql-driver/sql-driver.d.ts +38 -0
  172. package/dist/browser/sql-driver/sql-driver.d.ts.map +1 -0
  173. package/dist/browser/sync/commands.d.ts +15 -0
  174. package/dist/browser/sync/commands.d.ts.map +1 -0
  175. package/dist/browser/sync/commands.js +27 -0
  176. package/dist/browser/sync/commands.js.map +1 -0
  177. package/dist/browser/sync/types.d.ts +63 -0
  178. package/dist/browser/sync/types.d.ts.map +1 -0
  179. package/dist/browser/util/types.d.ts +8 -0
  180. package/dist/browser/util/types.d.ts.map +1 -0
  181. package/dist/browser/with-database.d.ts +29 -0
  182. package/dist/browser/with-database.d.ts.map +1 -0
  183. package/dist/client.d.ts +4 -0
  184. package/dist/client.js +5 -0
  185. package/dist/db-fragment-definition-builder.d.ts +101 -33
  186. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  187. package/dist/db-fragment-definition-builder.js +450 -60
  188. package/dist/db-fragment-definition-builder.js.map +1 -1
  189. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts +20 -0
  190. package/dist/dispatchers/cloudflare-do/dispatcher.d.ts.map +1 -0
  191. package/dist/dispatchers/cloudflare-do/dispatcher.js +147 -0
  192. package/dist/dispatchers/cloudflare-do/dispatcher.js.map +1 -0
  193. package/dist/dispatchers/cloudflare-do/index.d.ts +11 -0
  194. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
  195. package/dist/dispatchers/cloudflare-do/index.js +31 -0
  196. package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
  197. package/dist/dispatchers/node/dispatcher.d.ts +14 -0
  198. package/dist/dispatchers/node/dispatcher.d.ts.map +1 -0
  199. package/dist/dispatchers/node/dispatcher.js +80 -0
  200. package/dist/dispatchers/node/dispatcher.js.map +1 -0
  201. package/dist/dispatchers/node/index.d.ts +12 -0
  202. package/dist/dispatchers/node/index.d.ts.map +1 -0
  203. package/dist/dispatchers/node/index.js +27 -0
  204. package/dist/dispatchers/node/index.js.map +1 -0
  205. package/dist/durable-hooks.d.ts +31 -0
  206. package/dist/durable-hooks.d.ts.map +1 -0
  207. package/dist/durable-hooks.js +23 -0
  208. package/dist/durable-hooks.js.map +1 -0
  209. package/dist/fragments/internal-fragment.d.ts +186 -8
  210. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  211. package/dist/fragments/internal-fragment.js +203 -38
  212. package/dist/fragments/internal-fragment.js.map +1 -1
  213. package/dist/fragments/internal-fragment.routes.js +164 -0
  214. package/dist/fragments/internal-fragment.routes.js.map +1 -0
  215. package/dist/fragments/internal-fragment.schema.d.ts +15 -0
  216. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
  217. package/dist/fragments/internal-fragment.schema.js +39 -0
  218. package/dist/fragments/internal-fragment.schema.js.map +1 -0
  219. package/dist/hooks/durable-hooks-logger.d.ts +10 -0
  220. package/dist/hooks/durable-hooks-logger.d.ts.map +1 -0
  221. package/dist/hooks/durable-hooks-logger.js +75 -0
  222. package/dist/hooks/durable-hooks-logger.js.map +1 -0
  223. package/dist/hooks/durable-hooks-processor.d.ts +1 -0
  224. package/dist/hooks/durable-hooks-processor.js +80 -0
  225. package/dist/hooks/durable-hooks-processor.js.map +1 -0
  226. package/dist/hooks/durable-hooks-runtime.js +44 -0
  227. package/dist/hooks/durable-hooks-runtime.js.map +1 -0
  228. package/dist/hooks/hooks.d.ts +100 -1
  229. package/dist/hooks/hooks.d.ts.map +1 -1
  230. package/dist/hooks/hooks.js +254 -27
  231. package/dist/hooks/hooks.js.map +1 -1
  232. package/dist/id.d.ts +2 -2
  233. package/dist/id.js +2 -2
  234. package/dist/internal/adapter-registry.d.ts +11 -0
  235. package/dist/internal/adapter-registry.d.ts.map +1 -0
  236. package/dist/internal/adapter-registry.js +135 -0
  237. package/dist/internal/adapter-registry.js.map +1 -0
  238. package/dist/internal/outbox-state.d.ts +2 -0
  239. package/dist/internal/outbox-state.js +26 -0
  240. package/dist/internal/outbox-state.js.map +1 -0
  241. package/dist/migration-engine/auto-from-schema.d.ts +33 -0
  242. package/dist/migration-engine/auto-from-schema.d.ts.map +1 -0
  243. package/dist/migration-engine/auto-from-schema.js +223 -37
  244. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  245. package/dist/migration-engine/generation-engine.d.ts +16 -10
  246. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  247. package/dist/migration-engine/generation-engine.js +86 -35
  248. package/dist/migration-engine/generation-engine.js.map +1 -1
  249. package/dist/migration-engine/shared.d.ts +113 -0
  250. package/dist/migration-engine/shared.d.ts.map +1 -0
  251. package/dist/migration-engine/shared.js.map +1 -1
  252. package/dist/mod.d.ts +20 -12
  253. package/dist/mod.d.ts.map +1 -1
  254. package/dist/mod.js +18 -12
  255. package/dist/mod.js.map +1 -1
  256. package/dist/naming/sql-naming.d.ts +19 -0
  257. package/dist/naming/sql-naming.d.ts.map +1 -0
  258. package/dist/naming/sql-naming.js +116 -0
  259. package/dist/naming/sql-naming.js.map +1 -0
  260. package/dist/outbox/outbox-builder.js +156 -0
  261. package/dist/outbox/outbox-builder.js.map +1 -0
  262. package/dist/outbox/outbox.d.ts +54 -0
  263. package/dist/outbox/outbox.d.ts.map +1 -0
  264. package/dist/outbox/outbox.js +37 -0
  265. package/dist/outbox/outbox.js.map +1 -0
  266. package/dist/query/column-defaults.js +20 -4
  267. package/dist/query/column-defaults.js.map +1 -1
  268. package/dist/query/condition-builder.d.ts +7 -1
  269. package/dist/query/condition-builder.d.ts.map +1 -1
  270. package/dist/query/condition-builder.js +5 -1
  271. package/dist/query/condition-builder.js.map +1 -1
  272. package/dist/query/cursor-client.d.ts +105 -0
  273. package/dist/query/cursor-client.d.ts.map +1 -0
  274. package/dist/query/cursor-client.js +165 -0
  275. package/dist/query/cursor-client.js.map +1 -0
  276. package/dist/query/cursor.d.ts +3 -1
  277. package/dist/query/cursor.d.ts.map +1 -1
  278. package/dist/query/cursor.js +51 -14
  279. package/dist/query/cursor.js.map +1 -1
  280. package/dist/query/db-now.d.ts +22 -0
  281. package/dist/query/db-now.d.ts.map +1 -0
  282. package/dist/query/db-now.js +35 -0
  283. package/dist/query/db-now.js.map +1 -0
  284. package/dist/query/orm/orm.js.map +1 -1
  285. package/dist/query/serialize/create-sql-serializer.js +5 -4
  286. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  287. package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
  288. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  289. package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
  290. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  291. package/dist/query/serialize/dialect/sqlite-serializer.js +60 -12
  292. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  293. package/dist/query/serialize/sql-serializer.js +2 -2
  294. package/dist/query/serialize/sql-serializer.js.map +1 -1
  295. package/dist/query/simple-query-interface.d.ts +13 -4
  296. package/dist/query/simple-query-interface.d.ts.map +1 -1
  297. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +37 -2
  298. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  299. package/dist/query/unit-of-work/execute-unit-of-work.js +50 -24
  300. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  301. package/dist/query/unit-of-work/unit-of-work.d.ts +92 -30
  302. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  303. package/dist/query/unit-of-work/unit-of-work.js +136 -11
  304. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  305. package/dist/query/value-decoding.js +16 -6
  306. package/dist/query/value-decoding.js.map +1 -1
  307. package/dist/query/value-encoding.js +29 -9
  308. package/dist/query/value-encoding.js.map +1 -1
  309. package/dist/schema/create.d.ts +103 -35
  310. package/dist/schema/create.d.ts.map +1 -1
  311. package/dist/schema/create.js +172 -58
  312. package/dist/schema/create.js.map +1 -1
  313. package/dist/schema/generate-id.js +2 -2
  314. package/dist/schema/generate-id.js.map +1 -1
  315. package/dist/schema/type-conversion/create-sql-type-mapper.js +4 -3
  316. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  317. package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
  318. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  319. package/dist/schema/validator.d.ts +10 -0
  320. package/dist/schema/validator.d.ts.map +1 -0
  321. package/dist/schema/validator.js +123 -0
  322. package/dist/schema/validator.js.map +1 -0
  323. package/dist/schema-output/drizzle.d.ts +30 -0
  324. package/dist/schema-output/drizzle.d.ts.map +1 -0
  325. package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +88 -60
  326. package/dist/schema-output/drizzle.js.map +1 -0
  327. package/dist/schema-output/prisma.d.ts +17 -0
  328. package/dist/schema-output/prisma.d.ts.map +1 -0
  329. package/dist/schema-output/prisma.js +307 -0
  330. package/dist/schema-output/prisma.js.map +1 -0
  331. package/dist/sql-driver/dialects/durable-object-dialect.js +3 -9
  332. package/dist/sql-driver/dialects/durable-object-dialect.js.map +1 -1
  333. package/dist/sql-driver/query-executor/default-query-executor.js.map +1 -1
  334. package/dist/sql-driver/query-executor/query-executor-base.js.map +1 -1
  335. package/dist/sql-driver/sql-driver-adapter.js.map +1 -1
  336. package/dist/sql-driver/sql.js.map +1 -1
  337. package/dist/sync/commands.d.ts +15 -0
  338. package/dist/sync/commands.d.ts.map +1 -0
  339. package/dist/sync/commands.js +27 -0
  340. package/dist/sync/commands.js.map +1 -0
  341. package/dist/sync/index.d.ts +4 -0
  342. package/dist/sync/index.js +4 -0
  343. package/dist/sync/read-tracking.d.ts +25 -0
  344. package/dist/sync/read-tracking.d.ts.map +1 -0
  345. package/dist/sync/read-tracking.js +148 -0
  346. package/dist/sync/read-tracking.js.map +1 -0
  347. package/dist/sync/submit.js +213 -0
  348. package/dist/sync/submit.js.map +1 -0
  349. package/dist/sync/types.d.ts +63 -0
  350. package/dist/sync/types.d.ts.map +1 -0
  351. package/dist/util/default-database-adapter.js +66 -0
  352. package/dist/util/default-database-adapter.js.map +1 -0
  353. package/dist/with-database.d.ts +3 -6
  354. package/dist/with-database.d.ts.map +1 -1
  355. package/dist/with-database.js +8 -7
  356. package/dist/with-database.js.map +1 -1
  357. package/package.json +62 -55
  358. package/src/adapters/adapters.ts +33 -26
  359. package/src/adapters/drizzle/migrate-drizzle.test.ts +99 -41
  360. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +601 -0
  361. package/src/adapters/drizzle/test-utils.ts +13 -8
  362. package/src/adapters/generic-sql/driver-config.ts +38 -0
  363. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +10 -8
  364. package/src/adapters/generic-sql/generic-sql-adapter.ts +117 -34
  365. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +55 -0
  366. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +297 -3
  367. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +120 -0
  368. package/src/adapters/generic-sql/migration/cold-kysely.ts +1 -0
  369. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +27 -8
  370. package/src/adapters/generic-sql/migration/dialect/mysql.ts +47 -8
  371. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +28 -9
  372. package/src/adapters/generic-sql/migration/dialect/postgres.ts +9 -4
  373. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +839 -8
  374. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +396 -53
  375. package/src/adapters/generic-sql/migration/executor.test.ts +52 -0
  376. package/src/adapters/generic-sql/migration/executor.ts +47 -4
  377. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +238 -46
  378. package/src/adapters/generic-sql/migration/prepared-migrations.ts +21 -13
  379. package/src/adapters/generic-sql/migration/sql-generator.ts +145 -66
  380. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +11 -8
  381. package/src/adapters/generic-sql/query/cursor-utils.test.ts +272 -0
  382. package/src/adapters/generic-sql/query/cursor-utils.ts +42 -7
  383. package/src/adapters/generic-sql/query/db-now-sql.ts +49 -0
  384. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +171 -35
  385. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +53 -40
  386. package/src/adapters/generic-sql/query/select-builder.test.ts +16 -11
  387. package/src/adapters/generic-sql/query/select-builder.ts +7 -3
  388. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +75 -6
  389. package/src/adapters/generic-sql/query/sql-query-compiler.ts +129 -24
  390. package/src/adapters/generic-sql/query/where-builder.test.ts +96 -20
  391. package/src/adapters/generic-sql/query/where-builder.ts +112 -41
  392. package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +11 -20
  393. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +851 -0
  394. package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +18 -15
  395. package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +282 -14
  396. package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +129 -12
  397. package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +9 -7
  398. package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
  399. package/src/adapters/generic-sql/uow-decoder.test.ts +5 -4
  400. package/src/adapters/generic-sql/uow-decoder.ts +23 -5
  401. package/src/adapters/generic-sql/uow-encoder.test.ts +36 -3
  402. package/src/adapters/generic-sql/uow-encoder.ts +48 -13
  403. package/src/adapters/in-memory/condition-evaluator.test.ts +194 -0
  404. package/src/adapters/in-memory/condition-evaluator.ts +280 -0
  405. package/src/adapters/in-memory/errors.ts +20 -0
  406. package/src/adapters/in-memory/in-memory-adapter.ts +388 -0
  407. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +344 -0
  408. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +255 -0
  409. package/src/adapters/in-memory/in-memory-uow.ts +1724 -0
  410. package/src/adapters/in-memory/index.ts +3 -0
  411. package/src/adapters/in-memory/options.test.ts +42 -0
  412. package/src/adapters/in-memory/options.ts +91 -0
  413. package/src/adapters/in-memory/outbox.test.ts +361 -0
  414. package/src/adapters/in-memory/reference-resolution.test.ts +51 -0
  415. package/src/adapters/in-memory/reference-resolution.ts +67 -0
  416. package/src/adapters/in-memory/sorted-array-index.test.ts +124 -0
  417. package/src/adapters/in-memory/sorted-array-index.ts +228 -0
  418. package/src/adapters/in-memory/store.test.ts +69 -0
  419. package/src/adapters/in-memory/store.ts +145 -0
  420. package/src/adapters/in-memory/value-comparison.ts +53 -0
  421. package/src/adapters/in-memory/value-normalization.test.ts +58 -0
  422. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1207 -0
  423. package/src/adapters/shared/from-unit-of-work-compiler.ts +159 -47
  424. package/src/adapters/shared/uow-operation-compiler.ts +28 -18
  425. package/src/adapters/sql/index.ts +12 -0
  426. package/src/browser/mod.ts +64 -0
  427. package/src/client.ts +19 -0
  428. package/src/db-fragment-definition-builder.test.ts +845 -53
  429. package/src/db-fragment-definition-builder.ts +911 -95
  430. package/src/db-fragment-instantiator.test.ts +210 -94
  431. package/src/db-fragment-integration.test.ts +17 -12
  432. package/src/dispatchers/cloudflare-do/dispatcher.ts +204 -0
  433. package/src/dispatchers/cloudflare-do/index.test.ts +206 -0
  434. package/src/dispatchers/cloudflare-do/index.ts +63 -0
  435. package/src/dispatchers/node/dispatcher.ts +112 -0
  436. package/src/dispatchers/node/index.test.ts +120 -0
  437. package/src/dispatchers/node/index.ts +50 -0
  438. package/src/durable-hooks.test.ts +80 -0
  439. package/src/durable-hooks.ts +67 -0
  440. package/src/fragments/internal-fragment.routes.test.ts +570 -0
  441. package/src/fragments/internal-fragment.routes.ts +334 -0
  442. package/src/fragments/internal-fragment.schema.ts +95 -0
  443. package/src/fragments/internal-fragment.test.ts +505 -83
  444. package/src/fragments/internal-fragment.ts +453 -70
  445. package/src/hooks/durable-hooks-logger.ts +126 -0
  446. package/src/hooks/durable-hooks-processor.pglite.test.ts +87 -0
  447. package/src/hooks/durable-hooks-processor.test.ts +282 -0
  448. package/src/hooks/durable-hooks-processor.ts +173 -0
  449. package/src/hooks/durable-hooks-runtime.test.ts +65 -0
  450. package/src/hooks/durable-hooks-runtime.ts +81 -0
  451. package/src/hooks/hooks.test.ts +455 -34
  452. package/src/hooks/hooks.ts +501 -34
  453. package/src/id.test.ts +34 -0
  454. package/src/id.ts +1 -3
  455. package/src/internal/adapter-registry.test.ts +93 -0
  456. package/src/internal/adapter-registry.ts +239 -0
  457. package/src/internal/outbox-state.ts +43 -0
  458. package/src/migration-engine/auto-from-schema.test.ts +107 -14
  459. package/src/migration-engine/auto-from-schema.ts +365 -44
  460. package/src/migration-engine/create.test.ts +4 -3
  461. package/src/migration-engine/create.ts +1 -1
  462. package/src/migration-engine/generation-engine.test.ts +292 -110
  463. package/src/migration-engine/generation-engine.ts +117 -66
  464. package/src/migration-engine/shared.ts +14 -0
  465. package/src/mod.ts +95 -39
  466. package/src/naming/sql-naming.ts +181 -0
  467. package/src/outbox/outbox-builder.ts +241 -0
  468. package/src/outbox/outbox.test.ts +424 -0
  469. package/src/outbox/outbox.ts +139 -0
  470. package/src/query/column-defaults.ts +42 -4
  471. package/src/query/condition-builder.test.ts +18 -3
  472. package/src/query/condition-builder.ts +7 -0
  473. package/src/query/cursor-client.test.ts +70 -0
  474. package/src/query/cursor-client.ts +263 -0
  475. package/src/query/cursor.test.ts +119 -20
  476. package/src/query/cursor.ts +88 -27
  477. package/src/query/db-now.ts +73 -0
  478. package/src/query/orm/orm.ts +2 -2
  479. package/src/query/query-type.test.ts +4 -3
  480. package/src/query/serialize/create-sql-serializer.ts +10 -5
  481. package/src/query/serialize/dialect/mysql-serializer.ts +13 -5
  482. package/src/query/serialize/dialect/postgres-serializer.ts +35 -5
  483. package/src/query/serialize/dialect/sqlite-serializer.test.ts +90 -3
  484. package/src/query/serialize/dialect/sqlite-serializer.ts +108 -12
  485. package/src/query/serialize/sql-serializer.ts +4 -4
  486. package/src/query/simple-query-interface.ts +15 -4
  487. package/src/query/unit-of-work/execute-unit-of-work.test.ts +372 -10
  488. package/src/query/unit-of-work/execute-unit-of-work.ts +87 -27
  489. package/src/query/unit-of-work/retry-policy.test.ts +1 -0
  490. package/src/query/unit-of-work/tx-builder.test.ts +73 -1
  491. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +17 -16
  492. package/src/query/unit-of-work/unit-of-work-types.test.ts +42 -12
  493. package/src/query/unit-of-work/unit-of-work.test.ts +196 -39
  494. package/src/query/unit-of-work/unit-of-work.ts +309 -38
  495. package/src/query/value-decoding.test.ts +63 -4
  496. package/src/query/value-decoding.ts +32 -6
  497. package/src/query/value-encoding.test.ts +86 -2
  498. package/src/query/value-encoding.ts +56 -6
  499. package/src/schema/create.test.ts +293 -47
  500. package/src/schema/create.ts +406 -70
  501. package/src/schema/generate-id.test.ts +3 -2
  502. package/src/schema/generate-id.ts +2 -2
  503. package/src/schema/serialize.test.ts +18 -5
  504. package/src/schema/type-conversion/create-sql-type-mapper.ts +8 -3
  505. package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
  506. package/src/schema/type-conversion/type-mapping.test.ts +26 -1
  507. package/src/schema/validator.test.ts +199 -0
  508. package/src/schema/validator.ts +232 -0
  509. package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +232 -129
  510. package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +155 -99
  511. package/src/schema-output/prisma.test.ts +694 -0
  512. package/src/schema-output/prisma.ts +593 -0
  513. package/src/sql-driver/better-sqlite3.test.ts +5 -3
  514. package/src/sql-driver/dialects/durable-object-dialect.ts +3 -8
  515. package/src/sql-driver/query-executor/default-query-executor.ts +1 -1
  516. package/src/sql-driver/query-executor/query-executor-base.ts +1 -1
  517. package/src/sql-driver/query-executor/query-executor.ts +1 -1
  518. package/src/sql-driver/sql-driver-adapter.ts +2 -2
  519. package/src/sql-driver/sql.ts +2 -1
  520. package/src/sql-driver/sqlocal.test.ts +4 -2
  521. package/src/sync/commands.test.ts +39 -0
  522. package/src/sync/commands.ts +51 -0
  523. package/src/sync/conflict-checker.test.ts +450 -0
  524. package/src/sync/conflict-checker.ts +248 -0
  525. package/src/sync/index.ts +14 -0
  526. package/src/sync/plan.ts +9 -0
  527. package/src/sync/read-tracking.test.ts +177 -0
  528. package/src/sync/read-tracking.ts +287 -0
  529. package/src/sync/submit.test.ts +205 -0
  530. package/src/sync/submit.ts +328 -0
  531. package/src/sync/types.ts +80 -0
  532. package/src/util/default-database-adapter.ts +119 -0
  533. package/src/with-database.ts +20 -31
  534. package/tsconfig.json +1 -1
  535. package/tsdown.config.ts +38 -24
  536. package/vitest.config.ts +1 -0
  537. package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
  538. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
  539. package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
  540. package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
  541. package/dist/adapters/drizzle/generate.d.ts +0 -30
  542. package/dist/adapters/drizzle/generate.d.ts.map +0 -1
  543. package/dist/adapters/drizzle/generate.js.map +0 -1
  544. package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
  545. package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
  546. package/dist/adapters/kysely/kysely-adapter.js +0 -17
  547. package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
  548. package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
  549. package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
  550. package/dist/adapters/shared/table-name-mapper.js +0 -43
  551. package/dist/adapters/shared/table-name-mapper.js.map +0 -1
  552. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js +0 -165
  553. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
  554. package/dist/packages/fragno/dist/api/bind-services.js +0 -20
  555. package/dist/packages/fragno/dist/api/bind-services.js.map +0 -1
  556. package/dist/packages/fragno/dist/api/error.js +0 -48
  557. package/dist/packages/fragno/dist/api/error.js.map +0 -1
  558. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +0 -320
  559. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +0 -1
  560. package/dist/packages/fragno/dist/api/fragment-instantiator.js +0 -525
  561. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +0 -1
  562. package/dist/packages/fragno/dist/api/fragno-response.js +0 -73
  563. package/dist/packages/fragno/dist/api/fragno-response.js.map +0 -1
  564. package/dist/packages/fragno/dist/api/internal/response-stream.js +0 -81
  565. package/dist/packages/fragno/dist/api/internal/response-stream.js.map +0 -1
  566. package/dist/packages/fragno/dist/api/internal/route.js +0 -10
  567. package/dist/packages/fragno/dist/api/internal/route.js.map +0 -1
  568. package/dist/packages/fragno/dist/api/mutable-request-state.js +0 -97
  569. package/dist/packages/fragno/dist/api/mutable-request-state.js.map +0 -1
  570. package/dist/packages/fragno/dist/api/request-context-storage.js +0 -43
  571. package/dist/packages/fragno/dist/api/request-context-storage.js.map +0 -1
  572. package/dist/packages/fragno/dist/api/request-input-context.js +0 -118
  573. package/dist/packages/fragno/dist/api/request-input-context.js.map +0 -1
  574. package/dist/packages/fragno/dist/api/request-middleware.js +0 -83
  575. package/dist/packages/fragno/dist/api/request-middleware.js.map +0 -1
  576. package/dist/packages/fragno/dist/api/request-output-context.js +0 -119
  577. package/dist/packages/fragno/dist/api/request-output-context.js.map +0 -1
  578. package/dist/packages/fragno/dist/api/route.js +0 -17
  579. package/dist/packages/fragno/dist/api/route.js.map +0 -1
  580. package/dist/packages/fragno/dist/internal/symbols.js +0 -10
  581. package/dist/packages/fragno/dist/internal/symbols.js.map +0 -1
  582. package/dist/schema-generator/schema-generator.d.ts +0 -15
  583. package/dist/schema-generator/schema-generator.d.ts.map +0 -1
  584. package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
  585. package/src/adapters/kysely/kysely-adapter.ts +0 -27
  586. package/src/adapters/shared/table-name-mapper.ts +0 -50
  587. package/src/schema-generator/schema-generator.ts +0 -12
@@ -1,7 +1,8 @@
1
+ import type { DriverConfig } from "../adapters/generic-sql/driver-config";
2
+ import type { SQLiteStorageMode } from "../adapters/generic-sql/sqlite-storage";
1
3
  import type { AnyColumn } from "../schema/create";
2
4
  import { createSQLSerializer } from "./serialize/create-sql-serializer";
3
5
  import { resolveFragnoIdValue } from "./value-encoding";
4
- import type { DriverConfig } from "../adapters/generic-sql/driver-config";
5
6
 
6
7
  /**
7
8
  * Cursor object containing all information needed for pagination
@@ -56,6 +57,7 @@ export class Cursor {
56
57
  * Encode cursor to an opaque base64 string (safe to send to client)
57
58
  */
58
59
  encode(): string {
60
+ assertSerializableIndexValues(this.#indexValues);
59
61
  const data: CursorData = {
60
62
  v: 1,
61
63
  indexName: this.#indexName,
@@ -100,7 +102,12 @@ export interface CursorData {
100
102
  * Encode cursor data to a base64 string (internal)
101
103
  */
102
104
  function encodeCursorData(data: CursorData): string {
103
- const json = JSON.stringify(data);
105
+ let json: string;
106
+ try {
107
+ json = JSON.stringify(data);
108
+ } catch (error) {
109
+ throw new Error(`Invalid cursor: ${error instanceof Error ? error.message : "malformed data"}`);
110
+ }
104
111
  // Use Buffer in Node.js or btoa in browsers
105
112
  if (typeof Buffer !== "undefined") {
106
113
  return Buffer.from(json, "utf-8").toString("base64");
@@ -129,32 +136,38 @@ export function decodeCursor(cursor: string): Cursor {
129
136
  json = atob(cursor);
130
137
  }
131
138
  const data = JSON.parse(json);
139
+ const record = data as Record<string, unknown>;
132
140
 
133
141
  // Validate structure
134
142
  if (
135
- !data ||
136
- typeof data !== "object" ||
137
- !data.indexValues ||
138
- typeof data.indexValues !== "object" ||
139
- typeof data.pageSize !== "number" ||
140
- !data.indexName ||
141
- !data.orderDirection ||
142
- (data.orderDirection !== "asc" && data.orderDirection !== "desc")
143
+ !isPlainObject(data) ||
144
+ !isPlainObject(record["indexValues"]) ||
145
+ typeof record["indexName"] !== "string" ||
146
+ record["indexName"].length === 0 ||
147
+ typeof record["orderDirection"] !== "string" ||
148
+ (record["orderDirection"] !== "asc" && record["orderDirection"] !== "desc") ||
149
+ typeof record["pageSize"] !== "number" ||
150
+ !Number.isFinite(record["pageSize"]) ||
151
+ !Number.isInteger(record["pageSize"]) ||
152
+ record["pageSize"] <= 0
143
153
  ) {
144
154
  throw new Error("Invalid cursor structure");
145
155
  }
146
156
 
147
157
  // Only support v1
148
- const version = typeof data.v === "number" ? data.v : 0;
158
+ if (typeof record["v"] !== "number") {
159
+ throw new Error("Unsupported cursor version: missing. Only v1 is supported.");
160
+ }
161
+ const version = record["v"];
149
162
  if (version !== 1) {
150
163
  throw new Error(`Unsupported cursor version: ${version}. Only v1 is supported.`);
151
164
  }
152
165
 
153
166
  return new Cursor({
154
- indexName: data.indexName,
155
- orderDirection: data.orderDirection,
156
- pageSize: data.pageSize,
157
- indexValues: data.indexValues,
167
+ indexName: record["indexName"],
168
+ orderDirection: record["orderDirection"],
169
+ pageSize: record["pageSize"],
170
+ indexValues: record["indexValues"],
158
171
  });
159
172
  } catch (error) {
160
173
  throw new Error(`Invalid cursor: ${error instanceof Error ? error.message : "malformed data"}`);
@@ -194,7 +207,14 @@ export function createCursorFromRecord(
194
207
  const indexValues: Record<string, unknown> = {};
195
208
 
196
209
  for (const col of indexColumns) {
197
- indexValues[col.ormName] = record[col.ormName];
210
+ const value = record[col.name];
211
+ if (value === undefined) {
212
+ throw new Error(`Record is missing value for index column "${col.name}".`);
213
+ }
214
+ // Resolve FragnoId/FragnoReference to primitive values for cursor serialization.
215
+ const resolved = resolveFragnoIdValue(value, col);
216
+ // BigInt values are not JSON-serializable, so store them as strings.
217
+ indexValues[col.name] = typeof resolved === "bigint" ? resolved.toString() : resolved;
198
218
  }
199
219
 
200
220
  return new Cursor({
@@ -218,6 +238,7 @@ export function createCursorFromRecord(
218
238
  * @param cursor - The cursor object
219
239
  * @param indexColumns - The columns that make up the index
220
240
  * @param driverConfig - The driver configuration
241
+ * @param sqliteStorageMode - Optional SQLite storage mode override
221
242
  * @returns Serialized values ready for database queries
222
243
  *
223
244
  * @example
@@ -233,23 +254,63 @@ export function serializeCursorValues(
233
254
  cursor: Cursor,
234
255
  indexColumns: AnyColumn[],
235
256
  driverConfig: DriverConfig,
257
+ sqliteStorageMode?: SQLiteStorageMode,
236
258
  ): Record<string, unknown> {
237
- const serializer = createSQLSerializer(driverConfig);
259
+ const serializer = createSQLSerializer(driverConfig, sqliteStorageMode);
238
260
  const serialized: Record<string, unknown> = {};
261
+ const missingColumns: string[] = [];
239
262
 
240
263
  for (const col of indexColumns) {
241
- const value = cursor.indexValues[col.ormName];
242
- if (value !== undefined) {
243
- // First deserialize from JSON format to application format
244
- // (e.g., "2025-11-07T09:36:57.959Z" string → Date object)
245
- const deserialized = serializer.deserialize(value, col);
246
- // Resolve FragnoId/FragnoReference to primitive values (if present)
247
- const resolved = resolveFragnoIdValue(deserialized, col);
248
- // Then serialize to database format
249
- // (e.g., Date database driver format)
250
- serialized[col.ormName] = serializer.serialize(resolved, col);
264
+ const value = cursor.indexValues[col.name];
265
+ if (value === undefined) {
266
+ missingColumns.push(col.name);
267
+ continue;
268
+ }
269
+
270
+ // If the cursor value is already a FragnoId/FragnoReference, resolve it directly
271
+ // to avoid deserializing non-JSON objects.
272
+ const resolvedDirect = resolveFragnoIdValue(value, col);
273
+ if (resolvedDirect !== value) {
274
+ serialized[col.name] = serializer.serialize(resolvedDirect, col);
275
+ continue;
251
276
  }
277
+
278
+ // First deserialize from JSON format to application format
279
+ // (e.g., "2025-11-07T09:36:57.959Z" string → Date object)
280
+ const deserialized = serializer.deserialize(value, col);
281
+ // Resolve FragnoId/FragnoReference to primitive values (if present)
282
+ const resolved = resolveFragnoIdValue(deserialized, col);
283
+ // Then serialize to database format
284
+ // (e.g., Date → database driver format)
285
+ serialized[col.name] = serializer.serialize(resolved, col);
286
+ }
287
+
288
+ if (missingColumns.length > 0) {
289
+ const suffix = cursor.indexName ? ` for index "${cursor.indexName}"` : "";
290
+ const columns = missingColumns.map((name) => `"${name}"`).join(", ");
291
+ const plural = missingColumns.length === 1 ? "" : "s";
292
+ throw new Error(`Cursor is missing values for index column${plural} ${columns}${suffix}.`);
252
293
  }
253
294
 
254
295
  return serialized;
255
296
  }
297
+
298
+ const isPlainObject = (value: unknown): value is Record<string, unknown> =>
299
+ typeof value === "object" && value !== null && !Array.isArray(value);
300
+
301
+ const assertSerializableIndexValues = (values: Record<string, unknown>): void => {
302
+ for (const [key, value] of Object.entries(values)) {
303
+ if (value === undefined) {
304
+ throw new Error(`Cursor index value "${key}" is undefined.`);
305
+ }
306
+ if (typeof value === "number" && !Number.isFinite(value)) {
307
+ throw new Error(`Cursor index value "${key}" must be a finite number.`);
308
+ }
309
+ if (typeof value === "bigint") {
310
+ throw new Error(`Cursor index value "${key}" must not be a BigInt.`);
311
+ }
312
+ if (typeof value === "function" || typeof value === "symbol") {
313
+ throw new Error(`Cursor index value "${key}" is not JSON-serializable.`);
314
+ }
315
+ }
316
+ };
@@ -0,0 +1,73 @@
1
+ export type DbInterval = { tag: "db-interval"; ms: number };
2
+
3
+ export type DbIntervalInput =
4
+ | number
5
+ | {
6
+ ms?: number;
7
+ seconds?: number;
8
+ minutes?: number;
9
+ hours?: number;
10
+ days?: number;
11
+ };
12
+
13
+ export type DbNow = {
14
+ tag: "db-now";
15
+ offsetMs?: number;
16
+ plus: (interval: DbInterval | DbIntervalInput) => DbNow;
17
+ };
18
+
19
+ const toIntervalMs = (input: DbInterval | DbIntervalInput): number => {
20
+ if (typeof input === "number") {
21
+ if (!Number.isFinite(input)) {
22
+ throw new Error("DB_INTERVAL_INVALID");
23
+ }
24
+ return input;
25
+ }
26
+
27
+ if (typeof input === "object" && input !== null && "tag" in input) {
28
+ const tagged = input as DbInterval;
29
+ if (tagged.tag === "db-interval") {
30
+ if (!Number.isFinite(tagged.ms)) {
31
+ throw new Error("DB_INTERVAL_INVALID");
32
+ }
33
+ return tagged.ms;
34
+ }
35
+ throw new Error("DB_INTERVAL_INVALID");
36
+ }
37
+
38
+ const interval = input as Exclude<DbIntervalInput, number>;
39
+ const totalMs =
40
+ (interval.ms ?? 0) +
41
+ (interval.seconds ?? 0) * 1000 +
42
+ (interval.minutes ?? 0) * 60_000 +
43
+ (interval.hours ?? 0) * 3_600_000 +
44
+ (interval.days ?? 0) * 86_400_000;
45
+
46
+ if (!Number.isFinite(totalMs)) {
47
+ throw new Error("DB_INTERVAL_INVALID");
48
+ }
49
+
50
+ return totalMs;
51
+ };
52
+
53
+ const createDbNow = (offsetMs = 0): DbNow => ({
54
+ tag: "db-now",
55
+ offsetMs,
56
+ plus: (interval) => createDbNow(offsetMs + toIntervalMs(interval)),
57
+ });
58
+
59
+ export const dbNow = (): DbNow => createDbNow(0);
60
+
61
+ export const isDbNow = (value: unknown): value is DbNow =>
62
+ typeof value === "object" && value !== null && (value as { tag?: string }).tag === "db-now";
63
+
64
+ export const getDbNowOffsetMs = (value: DbNow): number =>
65
+ typeof value.offsetMs === "number" ? value.offsetMs : 0;
66
+
67
+ export const dbInterval = (input: DbIntervalInput): DbInterval => ({
68
+ tag: "db-interval",
69
+ ms: toIntervalMs(input),
70
+ });
71
+
72
+ export const isDbInterval = (value: unknown): value is DbInterval =>
73
+ typeof value === "object" && value !== null && (value as { tag?: string }).tag === "db-interval";
@@ -1,3 +1,5 @@
1
+ import type { AnyColumn, AnyRelation, AnyTable } from "../../schema/create";
2
+ import { buildCondition, type Condition } from "../condition-builder";
1
3
  import type {
2
4
  AnySelectClause,
3
5
  FindFirstOptions,
@@ -5,8 +7,6 @@ import type {
5
7
  JoinBuilder,
6
8
  OrderBy,
7
9
  } from "../simple-query-interface";
8
- import { buildCondition, type Condition } from "../condition-builder";
9
- import type { AnyColumn, AnyRelation, AnyTable } from "../../schema/create";
10
10
 
11
11
  export interface CompiledJoin {
12
12
  relation: AnyRelation;
@@ -1,5 +1,7 @@
1
1
  import { describe, expectTypeOf, it } from "vitest";
2
+
2
3
  import { column, FragnoId, idColumn, referenceColumn, schema } from "../schema/create";
4
+ import type { ConditionBuilder } from "./condition-builder";
3
5
  import type {
4
6
  SimpleQueryInterface,
5
7
  FindFirstOptions,
@@ -9,11 +11,10 @@ import type {
9
11
  SelectClause,
10
12
  TableToInsertValues,
11
13
  } from "./simple-query-interface";
12
- import type { ConditionBuilder } from "./condition-builder";
13
14
 
14
15
  describe("query type tests", () => {
15
16
  // Create test schema
16
- const _testSchema = schema((s) => {
17
+ const _testSchema = schema("_test", (s) => {
17
18
  return s
18
19
  .addTable("users", (t) => {
19
20
  return t
@@ -337,7 +338,7 @@ describe("query type tests", () => {
337
338
  });
338
339
 
339
340
  describe("join", () => {
340
- const userSchema = schema((s) => {
341
+ const userSchema = schema("user", (s) => {
341
342
  return s
342
343
  .addTable("users", (t) => {
343
344
  return t.addColumn("id", idColumn()).addColumn("name", column("string"));
@@ -1,8 +1,9 @@
1
1
  import type { DriverConfig } from "../../adapters/generic-sql/driver-config";
2
- import { SQLSerializer } from "./sql-serializer";
3
- import { SQLiteSerializer } from "./dialect/sqlite-serializer";
4
- import { PostgreSQLSerializer } from "./dialect/postgres-serializer";
2
+ import type { SQLiteStorageMode } from "../../adapters/generic-sql/sqlite-storage";
5
3
  import { MySQLSerializer } from "./dialect/mysql-serializer";
4
+ import { PostgreSQLSerializer } from "./dialect/postgres-serializer";
5
+ import { SQLiteSerializer } from "./dialect/sqlite-serializer";
6
+ import { SQLSerializer } from "./sql-serializer";
6
7
 
7
8
  // Re-export SQLSerializer for convenience
8
9
  export { SQLSerializer } from "./sql-serializer";
@@ -14,9 +15,13 @@ export { SQLSerializer } from "./sql-serializer";
14
15
  * (PostgreSQL, MySQL, or SQLite).
15
16
  *
16
17
  * @param driverConfig - The driver configuration
18
+ * @param sqliteStorageMode - Optional SQLite storage mode override
17
19
  * @returns Dialect-specific SQLSerializer instance
18
20
  */
19
- export function createSQLSerializer(driverConfig: DriverConfig): SQLSerializer {
21
+ export function createSQLSerializer(
22
+ driverConfig: DriverConfig,
23
+ sqliteStorageMode?: SQLiteStorageMode,
24
+ ): SQLSerializer {
20
25
  // TODO: The serializers are pretty lenient in what they accept (lost of typeof checks), it may
21
26
  // be beneficial to implement serializers per DriverConfig, and be less lenient.
22
27
  switch (driverConfig.databaseType) {
@@ -25,7 +30,7 @@ export function createSQLSerializer(driverConfig: DriverConfig): SQLSerializer {
25
30
  case "mysql":
26
31
  return new MySQLSerializer(driverConfig);
27
32
  case "sqlite":
28
- return new SQLiteSerializer(driverConfig);
33
+ return new SQLiteSerializer(driverConfig, sqliteStorageMode);
29
34
  default: {
30
35
  const exhaustiveCheck: never = driverConfig.databaseType;
31
36
  throw new Error(`Unsupported database type: ${exhaustiveCheck}`);
@@ -1,6 +1,6 @@
1
+ import type { DriverConfig } from "../../../adapters/generic-sql/driver-config";
1
2
  import type { AnyColumn } from "../../../schema/create";
2
3
  import { SQLSerializer } from "../sql-serializer";
3
- import type { DriverConfig } from "../../../adapters/generic-sql/driver-config";
4
4
 
5
5
  /**
6
6
  * MySQL-specific serializer.
@@ -19,7 +19,8 @@ export class MySQLSerializer extends SQLSerializer {
19
19
  super(driverConfig);
20
20
  }
21
21
 
22
- protected serializeDate(value: Date): Date {
22
+ protected serializeDate(value: Date, _col: AnyColumn): Date {
23
+ void _col;
23
24
  // MySQL handles Date objects natively
24
25
  return value;
25
26
  }
@@ -34,7 +35,8 @@ export class MySQLSerializer extends SQLSerializer {
34
35
  return value;
35
36
  }
36
37
 
37
- protected deserializeDate(value: unknown): Date {
38
+ protected deserializeDate(value: unknown, _col: AnyColumn): Date {
39
+ void _col;
38
40
  if (value instanceof Date) {
39
41
  return value;
40
42
  }
@@ -96,12 +98,15 @@ export class MySQLSerializer extends SQLSerializer {
96
98
 
97
99
  protected deserializeInteger(value: unknown): number {
98
100
  if (typeof value === "number") {
101
+ if (Number.isNaN(value) || !Number.isFinite(value)) {
102
+ throw new Error(`Cannot deserialize integer from invalid number: ${value}`);
103
+ }
99
104
  return value;
100
105
  }
101
106
  // MySQL may return integers as strings
102
107
  if (typeof value === "string") {
103
108
  const num = Number(value);
104
- if (isNaN(num)) {
109
+ if (Number.isNaN(num) || !Number.isFinite(num)) {
105
110
  throw new Error(`Cannot deserialize integer from invalid string: ${value}`);
106
111
  }
107
112
  return num;
@@ -121,11 +126,14 @@ export class MySQLSerializer extends SQLSerializer {
121
126
  protected deserializeDecimal(value: unknown): number {
122
127
  // MySQL can return decimals as numbers or strings
123
128
  if (typeof value === "number") {
129
+ if (Number.isNaN(value) || !Number.isFinite(value)) {
130
+ throw new Error(`Cannot deserialize decimal from invalid number: ${value}`);
131
+ }
124
132
  return value;
125
133
  }
126
134
  if (typeof value === "string") {
127
135
  const num = parseFloat(value);
128
- if (isNaN(num)) {
136
+ if (Number.isNaN(num) || !Number.isFinite(num)) {
129
137
  throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);
130
138
  }
131
139
  return num;
@@ -1,6 +1,6 @@
1
+ import type { DriverConfig } from "../../../adapters/generic-sql/driver-config";
1
2
  import type { AnyColumn } from "../../../schema/create";
2
3
  import { SQLSerializer } from "../sql-serializer";
3
- import type { DriverConfig } from "../../../adapters/generic-sql/driver-config";
4
4
 
5
5
  /**
6
6
  * PostgreSQL-specific serializer.
@@ -18,7 +18,8 @@ export class PostgreSQLSerializer extends SQLSerializer {
18
18
  super(driverConfig);
19
19
  }
20
20
 
21
- protected serializeDate(value: Date): Date {
21
+ protected serializeDate(value: Date, _col: AnyColumn): Date {
22
+ void _col;
22
23
  // PostgreSQL handles Date objects natively
23
24
  return value;
24
25
  }
@@ -33,13 +34,18 @@ export class PostgreSQLSerializer extends SQLSerializer {
33
34
  return value;
34
35
  }
35
36
 
36
- protected deserializeDate(value: unknown): Date {
37
+ protected deserializeDate(value: unknown, _col: AnyColumn): Date {
38
+ void _col;
37
39
  if (value instanceof Date) {
40
+ if (this.driverConfig.driverType === "pglite") {
41
+ return new Date(value.getTime() - value.getTimezoneOffset() * 60_000);
42
+ }
38
43
  return value;
39
44
  }
40
45
  // PostgreSQL returns timestamps/dates as strings
41
46
  if (typeof value === "string") {
42
- return new Date(value);
47
+ // Normalize timezone-less timestamps to UTC to avoid local offset drift.
48
+ return new Date(normalizeTimestampString(value));
43
49
  }
44
50
  throw new Error(`Cannot deserialize date from value: ${value}`);
45
51
  }
@@ -91,6 +97,9 @@ export class PostgreSQLSerializer extends SQLSerializer {
91
97
 
92
98
  protected deserializeInteger(value: unknown): number {
93
99
  if (typeof value === "number") {
100
+ if (Number.isNaN(value) || !Number.isFinite(value)) {
101
+ throw new Error(`Cannot deserialize integer from invalid number: ${value}`);
102
+ }
94
103
  return value;
95
104
  }
96
105
  // PostgreSQL may return bigint for large integers
@@ -108,11 +117,14 @@ export class PostgreSQLSerializer extends SQLSerializer {
108
117
  protected deserializeDecimal(value: unknown): number {
109
118
  // PostgreSQL can return decimals as numbers or strings depending on precision
110
119
  if (typeof value === "number") {
120
+ if (Number.isNaN(value) || !Number.isFinite(value)) {
121
+ throw new Error(`Cannot deserialize decimal from invalid number: ${value}`);
122
+ }
111
123
  return value;
112
124
  }
113
125
  if (typeof value === "string") {
114
126
  const num = parseFloat(value);
115
- if (isNaN(num)) {
127
+ if (Number.isNaN(num) || !Number.isFinite(num)) {
116
128
  throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);
117
129
  }
118
130
  return num;
@@ -127,3 +139,21 @@ export class PostgreSQLSerializer extends SQLSerializer {
127
139
  throw new Error(`Cannot deserialize string from value: ${typeof value}`);
128
140
  }
129
141
  }
142
+
143
+ const normalizeTimestampString = (value: string) => {
144
+ if (!hasTimeComponent(value) || !isTimestampWithoutTimezone(value)) {
145
+ return value;
146
+ }
147
+ const withTimeSeparator = value.includes(" ") ? value.replace(" ", "T") : value;
148
+ return `${withTimeSeparator}Z`;
149
+ };
150
+
151
+ const hasTimeComponent = (value: string) => /\d{2}:\d{2}:\d{2}/.test(value);
152
+
153
+ const isTimestampWithoutTimezone = (value: string) => {
154
+ // Detect RFC3339-like timezone indicators: Z or +/-HH(:MM)?
155
+ if (value.endsWith("Z")) {
156
+ return false;
157
+ }
158
+ return !/[+-]\d{2}(:?\d{2})?$/.test(value);
159
+ };
@@ -1,11 +1,20 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import { SQLiteSerializer } from "./sqlite-serializer";
3
- import type { AnyColumn } from "../../../schema/create";
2
+
4
3
  import { BetterSQLite3DriverConfig } from "../../../adapters/generic-sql/driver-config";
4
+ import { sqliteStoragePrisma } from "../../../adapters/generic-sql/sqlite-storage";
5
+ import type { AnyColumn } from "../../../schema/create";
6
+ import { SQLiteSerializer } from "./sqlite-serializer";
5
7
 
6
8
  describe("SQLiteSerializer", () => {
7
9
  const mockDriverConfig = new BetterSQLite3DriverConfig();
8
10
  const serializer = new SQLiteSerializer(mockDriverConfig);
11
+ const prismaSerializer = new SQLiteSerializer(mockDriverConfig, sqliteStoragePrisma);
12
+ const timestampColumn: AnyColumn = {
13
+ name: "createdAt",
14
+ type: "timestamp",
15
+ role: "regular",
16
+ isNullable: false,
17
+ } as AnyColumn;
9
18
 
10
19
  describe("serializeBigInt", () => {
11
20
  describe("for internal-id and reference columns", () => {
@@ -110,6 +119,19 @@ describe("SQLiteSerializer", () => {
110
119
  expect((result as Buffer).length).toBe(8);
111
120
  });
112
121
 
122
+ it("should keep bigint for regular column in prisma storage", () => {
123
+ const col: AnyColumn = {
124
+ name: "largeNumber",
125
+ type: "bigint",
126
+ role: "regular",
127
+ isNullable: false,
128
+ } as AnyColumn;
129
+
130
+ const result = prismaSerializer["serializeBigInt"](BigInt(789), col);
131
+ expect(result).toBe(BigInt(789));
132
+ expect(typeof result).toBe("bigint");
133
+ });
134
+
113
135
  it("should handle large values outside safe integer range as Buffer", () => {
114
136
  const col: AnyColumn = {
115
137
  name: "largeNumber",
@@ -132,11 +154,18 @@ describe("SQLiteSerializer", () => {
132
154
  describe("other serialization methods", () => {
133
155
  it("should serialize Date to timestamp number", () => {
134
156
  const date = new Date("2024-01-01T00:00:00Z");
135
- const result = serializer["serializeDate"](date);
157
+ const result = serializer["serializeDate"](date, timestampColumn);
136
158
  expect(result).toBe(date.getTime());
137
159
  expect(typeof result).toBe("number");
138
160
  });
139
161
 
162
+ it("should serialize Date to ISO string for prisma storage", () => {
163
+ const date = new Date("2024-01-01T00:00:00Z");
164
+ const result = prismaSerializer["serializeDate"](date, timestampColumn);
165
+ expect(result).toBe(date.toISOString());
166
+ expect(typeof result).toBe("string");
167
+ });
168
+
140
169
  it("should serialize boolean to 0/1", () => {
141
170
  expect(serializer["serializeBoolean"](true)).toBe(1);
142
171
  expect(serializer["serializeBoolean"](false)).toBe(0);
@@ -181,6 +210,23 @@ describe("SQLiteSerializer", () => {
181
210
  });
182
211
  });
183
212
 
213
+ describe("deserializeDate", () => {
214
+ it("should parse CURRENT_TIMESTAMP format as UTC", () => {
215
+ const date = prismaSerializer["deserializeDate"]("2024-03-10 12:34:56", timestampColumn);
216
+ expect(date.toISOString()).toBe("2024-03-10T12:34:56.000Z");
217
+ });
218
+
219
+ it("should parse CURRENT_TIMESTAMP format with milliseconds as UTC", () => {
220
+ const date = prismaSerializer["deserializeDate"]("2024-03-10 12:34:56.789", timestampColumn);
221
+ expect(date.toISOString()).toBe("2024-03-10T12:34:56.789Z");
222
+ });
223
+
224
+ it("should parse numeric timestamp strings with decimals", () => {
225
+ const date = serializer["deserializeDate"]("1772709276409.0", timestampColumn);
226
+ expect(date.getTime()).toBe(1772709276409);
227
+ });
228
+ });
229
+
184
230
  describe("deserializeInteger", () => {
185
231
  it("should deserialize number directly", () => {
186
232
  expect(serializer["deserializeInteger"](42)).toBe(42);
@@ -248,4 +294,45 @@ describe("SQLiteSerializer", () => {
248
294
  );
249
295
  });
250
296
  });
297
+
298
+ describe("deserializeBigInt", () => {
299
+ it("should throw when prisma storage receives unsafe bigint number", () => {
300
+ const unsafeNumber = Number.MAX_SAFE_INTEGER + 10;
301
+ expect(() => prismaSerializer["deserializeBigInt"](unsafeNumber)).toThrow(RangeError);
302
+ expect(() => prismaSerializer["deserializeBigInt"](unsafeNumber)).toThrow(
303
+ /exceeds Number\.MAX_SAFE_INTEGER/,
304
+ );
305
+ });
306
+
307
+ it("should deserialize bigint from ArrayBuffer blob values", () => {
308
+ const expected = BigInt("9007199254740993");
309
+ const buffer = Buffer.alloc(8);
310
+ buffer.writeBigInt64BE(expected);
311
+ const arrayBuffer = buffer.buffer.slice(
312
+ buffer.byteOffset,
313
+ buffer.byteOffset + buffer.byteLength,
314
+ );
315
+
316
+ expect(serializer["deserializeBigInt"](arrayBuffer)).toBe(expected);
317
+ });
318
+
319
+ it("should deserialize bigint from Uint8Array blob values", () => {
320
+ const expected = BigInt("123456789012345678");
321
+ const buffer = Buffer.alloc(8);
322
+ buffer.writeBigInt64BE(expected);
323
+ const value = new Uint8Array(buffer);
324
+
325
+ expect(serializer["deserializeBigInt"](value)).toBe(expected);
326
+ });
327
+
328
+ it.each([
329
+ ["Buffer", Buffer.alloc(9)],
330
+ ["ArrayBuffer", new ArrayBuffer(9)],
331
+ ["Uint8Array", new Uint8Array(9)],
332
+ ])("should reject %s blob values when byte length is not exactly 8", (_, value) => {
333
+ expect(() => serializer["deserializeBigInt"](value)).toThrow(
334
+ /Cannot deserialize bigint from 9 bytes; expected 8\./,
335
+ );
336
+ });
337
+ });
251
338
  });