@fragno-dev/db 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) hide show
  1. package/.turbo/turbo-build.log +206 -140
  2. package/CHANGELOG.md +67 -0
  3. package/README.md +30 -9
  4. package/dist/adapters/adapters.d.ts +23 -21
  5. package/dist/adapters/adapters.d.ts.map +1 -1
  6. package/dist/adapters/adapters.js.map +1 -1
  7. package/dist/adapters/generic-sql/driver-config.d.ts +16 -1
  8. package/dist/adapters/generic-sql/driver-config.d.ts.map +1 -1
  9. package/dist/adapters/generic-sql/driver-config.js +23 -1
  10. package/dist/adapters/generic-sql/driver-config.js.map +1 -1
  11. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts +27 -9
  12. package/dist/adapters/generic-sql/generic-sql-adapter.d.ts.map +1 -1
  13. package/dist/adapters/generic-sql/generic-sql-adapter.js +55 -16
  14. package/dist/adapters/generic-sql/generic-sql-adapter.js.map +1 -1
  15. package/dist/adapters/generic-sql/generic-sql-uow-executor.js +129 -3
  16. package/dist/adapters/generic-sql/generic-sql-uow-executor.js.map +1 -1
  17. package/dist/adapters/generic-sql/migration/dialect/mysql.js +24 -5
  18. package/dist/adapters/generic-sql/migration/dialect/mysql.js.map +1 -1
  19. package/dist/adapters/generic-sql/migration/dialect/postgres.js +6 -5
  20. package/dist/adapters/generic-sql/migration/dialect/postgres.js.map +1 -1
  21. package/dist/adapters/generic-sql/migration/dialect/sqlite.js +21 -10
  22. package/dist/adapters/generic-sql/migration/dialect/sqlite.js.map +1 -1
  23. package/dist/adapters/generic-sql/migration/prepared-migrations.d.ts.map +1 -1
  24. package/dist/adapters/generic-sql/migration/prepared-migrations.js +8 -8
  25. package/dist/adapters/generic-sql/migration/prepared-migrations.js.map +1 -1
  26. package/dist/adapters/generic-sql/migration/sql-generator.js +74 -51
  27. package/dist/adapters/generic-sql/migration/sql-generator.js.map +1 -1
  28. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js +6 -5
  29. package/dist/adapters/generic-sql/query/create-sql-query-compiler.js.map +1 -1
  30. package/dist/adapters/generic-sql/query/cursor-utils.js +42 -4
  31. package/dist/adapters/generic-sql/query/cursor-utils.js.map +1 -1
  32. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js +25 -17
  33. package/dist/adapters/generic-sql/query/generic-sql-uow-operation-compiler.js.map +1 -1
  34. package/dist/adapters/generic-sql/query/select-builder.js +5 -3
  35. package/dist/adapters/generic-sql/query/select-builder.js.map +1 -1
  36. package/dist/adapters/generic-sql/query/sql-query-compiler.js +15 -12
  37. package/dist/adapters/generic-sql/query/sql-query-compiler.js.map +1 -1
  38. package/dist/adapters/generic-sql/query/where-builder.js +38 -28
  39. package/dist/adapters/generic-sql/query/where-builder.js.map +1 -1
  40. package/dist/adapters/generic-sql/sqlite-storage.d.ts +13 -0
  41. package/dist/adapters/generic-sql/sqlite-storage.d.ts.map +1 -0
  42. package/dist/adapters/generic-sql/sqlite-storage.js +15 -0
  43. package/dist/adapters/generic-sql/sqlite-storage.js.map +1 -0
  44. package/dist/adapters/generic-sql/uow-decoder.js +7 -3
  45. package/dist/adapters/generic-sql/uow-decoder.js.map +1 -1
  46. package/dist/adapters/generic-sql/uow-encoder.js +28 -8
  47. package/dist/adapters/generic-sql/uow-encoder.js.map +1 -1
  48. package/dist/adapters/in-memory/condition-evaluator.js +131 -0
  49. package/dist/adapters/in-memory/condition-evaluator.js.map +1 -0
  50. package/dist/adapters/in-memory/errors.d.ts +13 -0
  51. package/dist/adapters/in-memory/errors.d.ts.map +1 -0
  52. package/dist/adapters/in-memory/errors.js +23 -0
  53. package/dist/adapters/in-memory/errors.js.map +1 -0
  54. package/dist/adapters/in-memory/in-memory-adapter.d.ts +27 -0
  55. package/dist/adapters/in-memory/in-memory-adapter.d.ts.map +1 -0
  56. package/dist/adapters/in-memory/in-memory-adapter.js +176 -0
  57. package/dist/adapters/in-memory/in-memory-adapter.js.map +1 -0
  58. package/dist/adapters/in-memory/in-memory-uow.js +648 -0
  59. package/dist/adapters/in-memory/in-memory-uow.js.map +1 -0
  60. package/dist/adapters/in-memory/index.d.ts +4 -0
  61. package/dist/adapters/in-memory/index.js +4 -0
  62. package/dist/adapters/in-memory/options.d.ts +28 -0
  63. package/dist/adapters/in-memory/options.d.ts.map +1 -0
  64. package/dist/adapters/in-memory/options.js +61 -0
  65. package/dist/adapters/in-memory/options.js.map +1 -0
  66. package/dist/adapters/in-memory/reference-resolution.js +26 -0
  67. package/dist/adapters/in-memory/reference-resolution.js.map +1 -0
  68. package/dist/adapters/in-memory/sorted-array-index.js +129 -0
  69. package/dist/adapters/in-memory/sorted-array-index.js.map +1 -0
  70. package/dist/adapters/in-memory/store.js +71 -0
  71. package/dist/adapters/in-memory/store.js.map +1 -0
  72. package/dist/adapters/in-memory/value-comparison.js +28 -0
  73. package/dist/adapters/in-memory/value-comparison.js.map +1 -0
  74. package/dist/adapters/shared/from-unit-of-work-compiler.js.map +1 -1
  75. package/dist/adapters/shared/uow-operation-compiler.js +11 -11
  76. package/dist/adapters/shared/uow-operation-compiler.js.map +1 -1
  77. package/dist/adapters/sql/index.d.ts +5 -0
  78. package/dist/adapters/sql/index.js +4 -0
  79. package/dist/db-fragment-definition-builder.d.ts +45 -96
  80. package/dist/db-fragment-definition-builder.d.ts.map +1 -1
  81. package/dist/db-fragment-definition-builder.js +121 -99
  82. package/dist/db-fragment-definition-builder.js.map +1 -1
  83. package/dist/dispatchers/cloudflare-do/index.d.ts +26 -0
  84. package/dist/dispatchers/cloudflare-do/index.d.ts.map +1 -0
  85. package/dist/dispatchers/cloudflare-do/index.js +63 -0
  86. package/dist/dispatchers/cloudflare-do/index.js.map +1 -0
  87. package/dist/dispatchers/node/index.d.ts +17 -0
  88. package/dist/dispatchers/node/index.d.ts.map +1 -0
  89. package/dist/dispatchers/node/index.js +59 -0
  90. package/dist/dispatchers/node/index.js.map +1 -0
  91. package/dist/fragments/internal-fragment.d.ts +172 -9
  92. package/dist/fragments/internal-fragment.d.ts.map +1 -1
  93. package/dist/fragments/internal-fragment.js +193 -74
  94. package/dist/fragments/internal-fragment.js.map +1 -1
  95. package/dist/fragments/internal-fragment.routes.js +29 -0
  96. package/dist/fragments/internal-fragment.routes.js.map +1 -0
  97. package/dist/fragments/internal-fragment.schema.d.ts +9 -0
  98. package/dist/fragments/internal-fragment.schema.d.ts.map +1 -0
  99. package/dist/fragments/internal-fragment.schema.js +22 -0
  100. package/dist/fragments/internal-fragment.schema.js.map +1 -0
  101. package/dist/hooks/durable-hooks-processor.d.ts +14 -0
  102. package/dist/hooks/durable-hooks-processor.d.ts.map +1 -0
  103. package/dist/hooks/durable-hooks-processor.js +32 -0
  104. package/dist/hooks/durable-hooks-processor.js.map +1 -0
  105. package/dist/hooks/hooks.d.ts +47 -4
  106. package/dist/hooks/hooks.d.ts.map +1 -1
  107. package/dist/hooks/hooks.js +106 -39
  108. package/dist/hooks/hooks.js.map +1 -1
  109. package/dist/migration-engine/auto-from-schema.js +14 -11
  110. package/dist/migration-engine/auto-from-schema.js.map +1 -1
  111. package/dist/migration-engine/generation-engine.d.ts +16 -10
  112. package/dist/migration-engine/generation-engine.d.ts.map +1 -1
  113. package/dist/migration-engine/generation-engine.js +72 -33
  114. package/dist/migration-engine/generation-engine.js.map +1 -1
  115. package/dist/migration-engine/shared.js.map +1 -1
  116. package/dist/mod.d.ts +17 -10
  117. package/dist/mod.d.ts.map +1 -1
  118. package/dist/mod.js +14 -8
  119. package/dist/mod.js.map +1 -1
  120. package/dist/naming/sql-naming.d.ts +19 -0
  121. package/dist/naming/sql-naming.d.ts.map +1 -0
  122. package/dist/naming/sql-naming.js +116 -0
  123. package/dist/naming/sql-naming.js.map +1 -0
  124. package/dist/node_modules/.pnpm/{rou3@0.7.10 → rou3@0.7.12}/node_modules/rou3/dist/index.js +8 -5
  125. package/dist/node_modules/.pnpm/rou3@0.7.12/node_modules/rou3/dist/index.js.map +1 -0
  126. package/dist/outbox/outbox-builder.js +156 -0
  127. package/dist/outbox/outbox-builder.js.map +1 -0
  128. package/dist/outbox/outbox.d.ts +52 -0
  129. package/dist/outbox/outbox.d.ts.map +1 -0
  130. package/dist/outbox/outbox.js +37 -0
  131. package/dist/outbox/outbox.js.map +1 -0
  132. package/dist/packages/fragno/dist/api/fragment-definition-builder.js +3 -2
  133. package/dist/packages/fragno/dist/api/fragment-definition-builder.js.map +1 -1
  134. package/dist/packages/fragno/dist/api/fragment-instantiator.js +164 -20
  135. package/dist/packages/fragno/dist/api/fragment-instantiator.js.map +1 -1
  136. package/dist/packages/fragno/dist/api/request-input-context.js +67 -0
  137. package/dist/packages/fragno/dist/api/request-input-context.js.map +1 -1
  138. package/dist/packages/fragno/dist/api/route.js +14 -1
  139. package/dist/packages/fragno/dist/api/route.js.map +1 -1
  140. package/dist/packages/fragno/dist/internal/trace-context.js +12 -0
  141. package/dist/packages/fragno/dist/internal/trace-context.js.map +1 -0
  142. package/dist/query/column-defaults.js +20 -4
  143. package/dist/query/column-defaults.js.map +1 -1
  144. package/dist/query/cursor.d.ts +3 -1
  145. package/dist/query/cursor.d.ts.map +1 -1
  146. package/dist/query/cursor.js +45 -14
  147. package/dist/query/cursor.js.map +1 -1
  148. package/dist/query/db-now.d.ts +8 -0
  149. package/dist/query/db-now.d.ts.map +1 -0
  150. package/dist/query/db-now.js +7 -0
  151. package/dist/query/db-now.js.map +1 -0
  152. package/dist/query/serialize/create-sql-serializer.js +3 -2
  153. package/dist/query/serialize/create-sql-serializer.js.map +1 -1
  154. package/dist/query/serialize/dialect/mysql-serializer.js +12 -6
  155. package/dist/query/serialize/dialect/mysql-serializer.js.map +1 -1
  156. package/dist/query/serialize/dialect/postgres-serializer.js +25 -7
  157. package/dist/query/serialize/dialect/postgres-serializer.js.map +1 -1
  158. package/dist/query/serialize/dialect/sqlite-serializer.js +55 -11
  159. package/dist/query/serialize/dialect/sqlite-serializer.js.map +1 -1
  160. package/dist/query/serialize/sql-serializer.js +2 -2
  161. package/dist/query/serialize/sql-serializer.js.map +1 -1
  162. package/dist/query/simple-query-interface.d.ts +6 -1
  163. package/dist/query/simple-query-interface.d.ts.map +1 -1
  164. package/dist/query/unit-of-work/execute-unit-of-work.d.ts +351 -100
  165. package/dist/query/unit-of-work/execute-unit-of-work.d.ts.map +1 -1
  166. package/dist/query/unit-of-work/execute-unit-of-work.js +440 -267
  167. package/dist/query/unit-of-work/execute-unit-of-work.js.map +1 -1
  168. package/dist/query/unit-of-work/unit-of-work.d.ts +67 -22
  169. package/dist/query/unit-of-work/unit-of-work.d.ts.map +1 -1
  170. package/dist/query/unit-of-work/unit-of-work.js +110 -13
  171. package/dist/query/unit-of-work/unit-of-work.js.map +1 -1
  172. package/dist/query/value-decoding.js +8 -5
  173. package/dist/query/value-decoding.js.map +1 -1
  174. package/dist/query/value-encoding.js +29 -9
  175. package/dist/query/value-encoding.js.map +1 -1
  176. package/dist/schema/create.d.ts +40 -14
  177. package/dist/schema/create.d.ts.map +1 -1
  178. package/dist/schema/create.js +82 -42
  179. package/dist/schema/create.js.map +1 -1
  180. package/dist/schema/generate-id.d.ts +20 -0
  181. package/dist/schema/generate-id.d.ts.map +1 -0
  182. package/dist/schema/generate-id.js +28 -0
  183. package/dist/schema/generate-id.js.map +1 -0
  184. package/dist/schema/type-conversion/create-sql-type-mapper.js +3 -2
  185. package/dist/schema/type-conversion/create-sql-type-mapper.js.map +1 -1
  186. package/dist/schema/type-conversion/dialect/sqlite.js +9 -0
  187. package/dist/schema/type-conversion/dialect/sqlite.js.map +1 -1
  188. package/dist/schema/validator.d.ts +10 -0
  189. package/dist/schema/validator.d.ts.map +1 -0
  190. package/dist/schema/validator.js +123 -0
  191. package/dist/schema/validator.js.map +1 -0
  192. package/dist/schema-output/drizzle.d.ts +30 -0
  193. package/dist/schema-output/drizzle.d.ts.map +1 -0
  194. package/dist/{adapters/drizzle/generate.js → schema-output/drizzle.js} +82 -56
  195. package/dist/schema-output/drizzle.js.map +1 -0
  196. package/dist/schema-output/prisma.d.ts +17 -0
  197. package/dist/schema-output/prisma.d.ts.map +1 -0
  198. package/dist/schema-output/prisma.js +296 -0
  199. package/dist/schema-output/prisma.js.map +1 -0
  200. package/dist/util/default-database-adapter.js +61 -0
  201. package/dist/util/default-database-adapter.js.map +1 -0
  202. package/dist/with-database.d.ts +1 -1
  203. package/dist/with-database.d.ts.map +1 -1
  204. package/dist/with-database.js +12 -3
  205. package/dist/with-database.js.map +1 -1
  206. package/package.json +43 -28
  207. package/src/adapters/adapters.ts +30 -24
  208. package/src/adapters/drizzle/migrate-drizzle.test.ts +54 -33
  209. package/src/adapters/drizzle/migration-parity-drizzle-kit.test.ts +599 -0
  210. package/src/adapters/drizzle/test-utils.ts +12 -8
  211. package/src/adapters/generic-sql/driver-config.ts +38 -0
  212. package/src/adapters/generic-sql/generic-sql-adapter.test.ts +5 -5
  213. package/src/adapters/generic-sql/generic-sql-adapter.ts +110 -24
  214. package/src/adapters/generic-sql/generic-sql-uow-executor.test.ts +54 -0
  215. package/src/adapters/generic-sql/generic-sql-uow-executor.ts +231 -3
  216. package/src/adapters/generic-sql/migration/adapter-migration-parity.test.ts +118 -0
  217. package/src/adapters/generic-sql/migration/dialect/mysql.test.ts +26 -8
  218. package/src/adapters/generic-sql/migration/dialect/mysql.ts +46 -8
  219. package/src/adapters/generic-sql/migration/dialect/postgres.test.ts +25 -7
  220. package/src/adapters/generic-sql/migration/dialect/postgres.ts +8 -4
  221. package/src/adapters/generic-sql/migration/dialect/sqlite.test.ts +47 -8
  222. package/src/adapters/generic-sql/migration/dialect/sqlite.ts +27 -12
  223. package/src/adapters/generic-sql/migration/prepared-migrations.test.ts +128 -39
  224. package/src/adapters/generic-sql/migration/prepared-migrations.ts +15 -8
  225. package/src/adapters/generic-sql/migration/sql-generator.ts +142 -65
  226. package/src/adapters/generic-sql/query/create-sql-query-compiler.ts +9 -6
  227. package/src/adapters/generic-sql/query/cursor-utils.test.ts +271 -0
  228. package/src/adapters/generic-sql/query/cursor-utils.ts +41 -6
  229. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.test.ts +27 -27
  230. package/src/adapters/generic-sql/query/generic-sql-uow-operation-compiler.ts +38 -24
  231. package/src/adapters/generic-sql/query/select-builder.test.ts +15 -11
  232. package/src/adapters/generic-sql/query/select-builder.ts +6 -2
  233. package/src/adapters/generic-sql/query/sql-query-compiler.test.ts +52 -2
  234. package/src/adapters/generic-sql/query/sql-query-compiler.ts +50 -15
  235. package/src/adapters/generic-sql/query/where-builder.test.ts +91 -17
  236. package/src/adapters/generic-sql/query/where-builder.ts +90 -38
  237. package/src/adapters/{kysely/kysely-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-migrations.test.ts} +6 -6
  238. package/src/adapters/generic-sql/sql-adapter-pglite-pagination.test.ts +806 -0
  239. package/src/adapters/{drizzle/drizzle-adapter-pglite.test.ts → generic-sql/sql-adapter-pglite-queries.test.ts} +11 -11
  240. package/src/adapters/generic-sql/{test/generic-drizzle-adapter-sqlite3.test.ts → sql-adapter-sqlite3-driver.test.ts} +49 -35
  241. package/src/adapters/{drizzle/drizzle-adapter-sqlite3.test.ts → generic-sql/sql-adapter-sqlite3-uow.test.ts} +48 -32
  242. package/src/adapters/{kysely/kysely-adapter-sqlocal.test.ts → generic-sql/sql-adapter-sqlocal.test.ts} +6 -6
  243. package/src/adapters/generic-sql/sqlite-storage.ts +20 -0
  244. package/src/adapters/generic-sql/uow-decoder.test.ts +1 -1
  245. package/src/adapters/generic-sql/uow-decoder.ts +21 -3
  246. package/src/adapters/generic-sql/uow-encoder.test.ts +33 -2
  247. package/src/adapters/generic-sql/uow-encoder.ts +50 -11
  248. package/src/adapters/in-memory/condition-evaluator.test.ts +193 -0
  249. package/src/adapters/in-memory/condition-evaluator.ts +275 -0
  250. package/src/adapters/in-memory/errors.ts +20 -0
  251. package/src/adapters/in-memory/in-memory-adapter.ts +277 -0
  252. package/src/adapters/in-memory/in-memory-uow.mutations.test.ts +296 -0
  253. package/src/adapters/in-memory/in-memory-uow.retrieval.test.ts +100 -0
  254. package/src/adapters/in-memory/in-memory-uow.ts +1348 -0
  255. package/src/adapters/in-memory/index.ts +3 -0
  256. package/src/adapters/in-memory/options.test.ts +41 -0
  257. package/src/adapters/in-memory/options.ts +87 -0
  258. package/src/adapters/in-memory/reference-resolution.test.ts +50 -0
  259. package/src/adapters/in-memory/reference-resolution.ts +67 -0
  260. package/src/adapters/in-memory/sorted-array-index.test.ts +123 -0
  261. package/src/adapters/in-memory/sorted-array-index.ts +228 -0
  262. package/src/adapters/in-memory/store.test.ts +68 -0
  263. package/src/adapters/in-memory/store.ts +145 -0
  264. package/src/adapters/in-memory/value-comparison.ts +53 -0
  265. package/src/adapters/in-memory/value-normalization.test.ts +57 -0
  266. package/src/adapters/prisma/prisma-adapter-sqlite3.test.ts +1163 -0
  267. package/src/adapters/shared/from-unit-of-work-compiler.ts +3 -1
  268. package/src/adapters/shared/uow-operation-compiler.ts +26 -16
  269. package/src/adapters/sql/index.ts +12 -0
  270. package/src/db-fragment-definition-builder.test.ts +88 -54
  271. package/src/db-fragment-definition-builder.ts +201 -322
  272. package/src/db-fragment-instantiator.test.ts +169 -101
  273. package/src/db-fragment-integration.test.ts +301 -149
  274. package/src/dispatchers/cloudflare-do/index.test.ts +73 -0
  275. package/src/dispatchers/cloudflare-do/index.ts +104 -0
  276. package/src/dispatchers/node/index.test.ts +91 -0
  277. package/src/dispatchers/node/index.ts +87 -0
  278. package/src/fragments/internal-fragment.routes.ts +42 -0
  279. package/src/fragments/internal-fragment.schema.ts +51 -0
  280. package/src/fragments/internal-fragment.test.ts +730 -274
  281. package/src/fragments/internal-fragment.ts +447 -154
  282. package/src/hooks/durable-hooks-processor.test.ts +117 -0
  283. package/src/hooks/durable-hooks-processor.ts +67 -0
  284. package/src/hooks/hooks.test.ts +411 -259
  285. package/src/hooks/hooks.ts +265 -66
  286. package/src/migration-engine/auto-from-schema.test.ts +14 -14
  287. package/src/migration-engine/auto-from-schema.ts +5 -2
  288. package/src/migration-engine/create.test.ts +2 -2
  289. package/src/migration-engine/generation-engine.test.ts +229 -104
  290. package/src/migration-engine/generation-engine.ts +94 -64
  291. package/src/migration-engine/shared.ts +1 -0
  292. package/src/mod.ts +78 -30
  293. package/src/naming/sql-naming.ts +180 -0
  294. package/src/outbox/outbox-builder.ts +241 -0
  295. package/src/outbox/outbox.test.ts +253 -0
  296. package/src/outbox/outbox.ts +137 -0
  297. package/src/query/column-defaults.ts +41 -3
  298. package/src/query/condition-builder.test.ts +3 -3
  299. package/src/query/cursor.test.ts +116 -18
  300. package/src/query/cursor.ts +75 -26
  301. package/src/query/db-now.ts +6 -0
  302. package/src/query/query-type.test.ts +2 -2
  303. package/src/query/serialize/create-sql-serializer.ts +7 -2
  304. package/src/query/serialize/dialect/mysql-serializer.ts +12 -4
  305. package/src/query/serialize/dialect/postgres-serializer.ts +34 -4
  306. package/src/query/serialize/dialect/sqlite-serializer.test.ts +51 -1
  307. package/src/query/serialize/dialect/sqlite-serializer.ts +92 -9
  308. package/src/query/serialize/sql-serializer.ts +4 -4
  309. package/src/query/simple-query-interface.ts +5 -0
  310. package/src/query/unit-of-work/execute-unit-of-work.test.ts +1512 -1458
  311. package/src/query/unit-of-work/execute-unit-of-work.ts +1708 -596
  312. package/src/query/unit-of-work/tx-builder.test.ts +1041 -0
  313. package/src/query/unit-of-work/unit-of-work-coordinator.test.ts +32 -32
  314. package/src/query/unit-of-work/unit-of-work-types.test.ts +1 -1
  315. package/src/query/unit-of-work/unit-of-work.test.ts +231 -36
  316. package/src/query/unit-of-work/unit-of-work.ts +229 -31
  317. package/src/query/value-decoding.test.ts +13 -2
  318. package/src/query/value-decoding.ts +17 -4
  319. package/src/query/value-encoding.test.ts +85 -2
  320. package/src/query/value-encoding.ts +56 -6
  321. package/src/schema/create.test.ts +129 -42
  322. package/src/schema/create.ts +187 -47
  323. package/src/schema/generate-id.test.ts +57 -0
  324. package/src/schema/generate-id.ts +38 -0
  325. package/src/schema/serialize.test.ts +14 -2
  326. package/src/schema/type-conversion/create-sql-type-mapper.ts +7 -2
  327. package/src/schema/type-conversion/dialect/sqlite.ts +18 -0
  328. package/src/schema/type-conversion/type-mapping.test.ts +25 -1
  329. package/src/schema/validator.test.ts +197 -0
  330. package/src/schema/validator.ts +231 -0
  331. package/src/{adapters/drizzle/generate.test.ts → schema-output/drizzle.test.ts} +179 -129
  332. package/src/{adapters/drizzle/generate.ts → schema-output/drizzle.ts} +143 -93
  333. package/src/schema-output/prisma.test.ts +536 -0
  334. package/src/schema-output/prisma.ts +573 -0
  335. package/src/util/default-database-adapter.ts +106 -0
  336. package/src/with-database.ts +22 -3
  337. package/tsdown.config.ts +6 -4
  338. package/dist/adapters/drizzle/drizzle-adapter.d.ts +0 -20
  339. package/dist/adapters/drizzle/drizzle-adapter.d.ts.map +0 -1
  340. package/dist/adapters/drizzle/drizzle-adapter.js +0 -27
  341. package/dist/adapters/drizzle/drizzle-adapter.js.map +0 -1
  342. package/dist/adapters/drizzle/generate.d.ts +0 -30
  343. package/dist/adapters/drizzle/generate.d.ts.map +0 -1
  344. package/dist/adapters/drizzle/generate.js.map +0 -1
  345. package/dist/adapters/kysely/kysely-adapter.d.ts +0 -19
  346. package/dist/adapters/kysely/kysely-adapter.d.ts.map +0 -1
  347. package/dist/adapters/kysely/kysely-adapter.js +0 -17
  348. package/dist/adapters/kysely/kysely-adapter.js.map +0 -1
  349. package/dist/adapters/shared/table-name-mapper.d.ts +0 -12
  350. package/dist/adapters/shared/table-name-mapper.d.ts.map +0 -1
  351. package/dist/adapters/shared/table-name-mapper.js +0 -43
  352. package/dist/adapters/shared/table-name-mapper.js.map +0 -1
  353. package/dist/node_modules/.pnpm/rou3@0.7.10/node_modules/rou3/dist/index.js.map +0 -1
  354. package/dist/schema-generator/schema-generator.d.ts +0 -15
  355. package/dist/schema-generator/schema-generator.d.ts.map +0 -1
  356. package/src/adapters/drizzle/drizzle-adapter.ts +0 -39
  357. package/src/adapters/kysely/kysely-adapter.ts +0 -27
  358. package/src/adapters/shared/table-name-mapper.ts +0 -50
  359. package/src/schema-generator/schema-generator.ts +0 -12
  360. package/src/shared/config.ts +0 -10
  361. package/src/shared/connection-pool.ts +0 -24
  362. package/src/shared/prisma.ts +0 -45
@@ -1 +1 @@
1
- {"version":3,"file":"column-defaults.js","names":[],"sources":["../../src/query/column-defaults.ts"],"sourcesContent":["import type { AnyColumn } from \"../schema/create\";\nimport { createId } from \"../id\";\n\n/**\n * Generate a runtime default value for a column that has defaultTo$()\n *\n * Only generates values for runtime defaults (defaultTo$), NOT static defaults (defaultTo).\n * Static defaults should be handled by the database via DEFAULT constraints.\n *\n * @param column - The column with a default value configuration\n * @returns The generated default value, or undefined if the column has no runtime default\n *\n * @internal\n */\nexport function generateRuntimeDefault(column: AnyColumn): unknown {\n // Check if column has a default value configuration\n if (!column.default) {\n return undefined;\n }\n\n // If it's a static default value (defaultTo), return undefined\n // as the database should handle this via DEFAULT constraint\n if (\"value\" in column.default) {\n return undefined;\n }\n\n // If it's a database-level special function (defaultTo(b => b.now())), return undefined\n // as the database should handle this via DEFAULT NOW() or equivalent\n if (\"dbSpecial\" in column.default) {\n return undefined;\n }\n\n // Handle runtime defaults (defaultTo$)\n const runtime = column.default.runtime;\n\n if (runtime === \"cuid\") {\n return createId();\n }\n\n if (runtime === \"now\") {\n return new Date();\n }\n\n if (typeof runtime === \"function\") {\n return runtime();\n }\n\n return undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAgB,uBAAuB,QAA4B;AAEjE,KAAI,CAAC,OAAO,QACV;AAKF,KAAI,WAAW,OAAO,QACpB;AAKF,KAAI,eAAe,OAAO,QACxB;CAIF,MAAM,UAAU,OAAO,QAAQ;AAE/B,KAAI,YAAY,OACd,QAAO,UAAU;AAGnB,KAAI,YAAY,MACd,wBAAO,IAAI,MAAM;AAGnB,KAAI,OAAO,YAAY,WACrB,QAAO,SAAS"}
1
+ {"version":3,"file":"column-defaults.js","names":[],"sources":["../../src/query/column-defaults.ts"],"sourcesContent":["import type { AnyColumn } from \"../schema/create\";\nimport { createId } from \"../id\";\n\nexport type RuntimeDefaultContext = {\n now?: () => Date;\n createId?: () => string;\n};\n\n/**\n * Generate a runtime default value for a column that has defaultTo$()\n *\n * Only generates values for runtime defaults (defaultTo$), NOT static defaults (defaultTo).\n * Static defaults should be handled by the database via DEFAULT constraints.\n *\n * @param column - The column with a default value configuration\n * @returns The generated default value, or undefined if the column has no runtime default\n *\n * @internal\n */\nexport function generateRuntimeDefault(\n column: AnyColumn,\n context: RuntimeDefaultContext = {},\n): unknown {\n // Check if column has a default value configuration\n if (!column.default) {\n return undefined;\n }\n\n // If it's a static default value (defaultTo), return undefined\n // as the database should handle this via DEFAULT constraint\n if (\"value\" in column.default) {\n return undefined;\n }\n\n // If it's a database-level special function (defaultTo(b => b.now())), return undefined\n // as the database should handle this via DEFAULT NOW() or equivalent\n if (\"dbSpecial\" in column.default) {\n return undefined;\n }\n\n // Handle runtime defaults (defaultTo$)\n const runtime = column.default.runtime;\n\n if (runtime === \"cuid\") {\n return (context.createId ?? createId)();\n }\n\n if (runtime === \"now\") {\n return (context.now ?? (() => new Date()))();\n }\n\n if (typeof runtime === \"function\") {\n return runtime();\n }\n\n return undefined;\n}\n\n/**\n * Generate a fallback value for database-level defaults.\n *\n * This is used by adapters that cannot rely on database DEFAULT constraints,\n * such as the in-memory adapter.\n *\n * @internal\n */\nexport function generateDatabaseDefault(\n column: AnyColumn,\n context: RuntimeDefaultContext = {},\n): unknown {\n if (!column.default) {\n return undefined;\n }\n\n if (\"value\" in column.default) {\n return column.default.value;\n }\n\n if (\"dbSpecial\" in column.default) {\n if (column.default.dbSpecial === \"now\") {\n return (context.now ?? (() => new Date()))();\n }\n return undefined;\n }\n\n return undefined;\n}\n"],"mappings":";;;;;;;;;;;;;;AAmBA,SAAgB,uBACd,QACA,UAAiC,EAAE,EAC1B;AAET,KAAI,CAAC,OAAO,QACV;AAKF,KAAI,WAAW,OAAO,QACpB;AAKF,KAAI,eAAe,OAAO,QACxB;CAIF,MAAM,UAAU,OAAO,QAAQ;AAE/B,KAAI,YAAY,OACd,SAAQ,QAAQ,YAAY,WAAW;AAGzC,KAAI,YAAY,MACd,SAAQ,QAAQ,8BAAc,IAAI,MAAM,IAAI;AAG9C,KAAI,OAAO,YAAY,WACrB,QAAO,SAAS;;;;;;;;;;AAcpB,SAAgB,wBACd,QACA,UAAiC,EAAE,EAC1B;AACT,KAAI,CAAC,OAAO,QACV;AAGF,KAAI,WAAW,OAAO,QACpB,QAAO,OAAO,QAAQ;AAGxB,KAAI,eAAe,OAAO,SAAS;AACjC,MAAI,OAAO,QAAQ,cAAc,MAC/B,SAAQ,QAAQ,8BAAc,IAAI,MAAM,IAAI;AAE9C"}
@@ -1,5 +1,6 @@
1
1
  import { AnyColumn } from "../schema/create.js";
2
2
  import { DriverConfig } from "../adapters/generic-sql/driver-config.js";
3
+ import { SQLiteStorageMode } from "../adapters/generic-sql/sqlite-storage.js";
3
4
 
4
5
  //#region src/query/cursor.d.ts
5
6
 
@@ -114,6 +115,7 @@ declare function createCursorFromRecord(record: Record<string, unknown>, indexCo
114
115
  * @param cursor - The cursor object
115
116
  * @param indexColumns - The columns that make up the index
116
117
  * @param driverConfig - The driver configuration
118
+ * @param sqliteStorageMode - Optional SQLite storage mode override
117
119
  * @returns Serialized values ready for database queries
118
120
  *
119
121
  * @example
@@ -125,7 +127,7 @@ declare function createCursorFromRecord(record: Record<string, unknown>, indexCo
125
127
  * );
126
128
  * ```
127
129
  */
128
- declare function serializeCursorValues(cursor: Cursor, indexColumns: AnyColumn[], driverConfig: DriverConfig): Record<string, unknown>;
130
+ declare function serializeCursorValues(cursor: Cursor, indexColumns: AnyColumn[], driverConfig: DriverConfig, sqliteStorageMode?: SQLiteStorageMode): Record<string, unknown>;
129
131
  //#endregion
130
132
  export { Cursor, CursorData, CursorResult, createCursorFromRecord, decodeCursor, serializeCursorValues };
131
133
  //# sourceMappingURL=cursor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cursor.d.ts","names":[],"sources":["../../src/query/cursor.ts"],"sourcesContent":[],"mappings":";;;;;;;AAQA;AAgEiB,cAhEJ,MAAA,CAgEgB;EAkBZ,CAAA,OAAA;EAgCD,WAAA,CAAA,IAAY,EAAA;IA8DZ,SAAA,EAAA,MAAA;IACN,cAAA,EAAA,KAAA,GAAA,MAAA;IACM,QAAA,EAAA,MAAA;IAMb,WAAA,EA9Kc,MA8Kd,CAAA,MAAA,EAAA,OAAA,CAAA;EAAM,CAAA;EAuCO;;;EAGA,IAAA,SAAA,CAAA,CAAA,EAAA,MAAA;EACb;;;;;;;;;;;qBAzLkB;;;;;;;;;UAsBJ;;;;SAIR;;;;WAIE;;;;;;;;;UAUM,UAAA;;;;;eAKF;;;;;;;;;;;;;;iBA2BC,YAAA,kBAA8B;;;;;;;;;;;;;;;;;;;;;;iBA8D9B,sBAAA,SACN,uCACM;;;;IAMb;;;;;;;;;;;;;;;;;;;;;;;;;iBAuCa,qBAAA,SACN,sBACM,2BACA,eACb"}
1
+ {"version":3,"file":"cursor.d.ts","names":[],"sources":["../../src/query/cursor.ts"],"sourcesContent":[],"mappings":";;;;;;;;AASA;AAiEiB,cAjEJ,MAAA,CAiEgB;EAkBZ,CAAA,OAAA;EAqCD,WAAA,CAAA,IAAY,EAAA;IAoEZ,SAAA,EAAA,MAAA;IACN,cAAA,EAAA,KAAA,GAAA,MAAA;IACM,QAAA,EAAA,MAAA;IAMb,WAAA,EA1Lc,MA0Ld,CAAA,MAAA,EAAA,OAAA,CAAA;EAAM,CAAA;EA4CO;;;EAGA,IAAA,SAAA,CAAA,CAAA,EAAA,MAAA;EACM;;;;;;;;;;;qBA1MD;;;;;;;;;UAuBJ;;;;SAIR;;;;WAIE;;;;;;;;;UAUM,UAAA;;;;;eAKF;;;;;;;;;;;;;;iBAgCC,YAAA,kBAA8B;;;;;;;;;;;;;;;;;;;;;;iBAoE9B,sBAAA,SACN,uCACM;;;;IAMb;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4Ca,qBAAA,SACN,sBACM,2BACA,kCACM,oBACnB"}
@@ -44,6 +44,7 @@ var Cursor = class {
44
44
  * Encode cursor to an opaque base64 string (safe to send to client)
45
45
  */
46
46
  encode() {
47
+ assertSerializableIndexValues(this.#indexValues);
47
48
  return encodeCursorData({
48
49
  v: 1,
49
50
  indexName: this.#indexName,
@@ -57,7 +58,12 @@ var Cursor = class {
57
58
  * Encode cursor data to a base64 string (internal)
58
59
  */
59
60
  function encodeCursorData(data) {
60
- const json = JSON.stringify(data);
61
+ let json;
62
+ try {
63
+ json = JSON.stringify(data);
64
+ } catch (error) {
65
+ throw new Error(`Invalid cursor: ${error instanceof Error ? error.message : "malformed data"}`);
66
+ }
61
67
  if (typeof Buffer !== "undefined") return Buffer.from(json, "utf-8").toString("base64");
62
68
  return btoa(json);
63
69
  }
@@ -79,14 +85,16 @@ function decodeCursor(cursor) {
79
85
  if (typeof Buffer !== "undefined") json = Buffer.from(cursor, "base64").toString("utf-8");
80
86
  else json = atob(cursor);
81
87
  const data = JSON.parse(json);
82
- if (!data || typeof data !== "object" || !data.indexValues || typeof data.indexValues !== "object" || typeof data.pageSize !== "number" || !data.indexName || !data.orderDirection || data.orderDirection !== "asc" && data.orderDirection !== "desc") throw new Error("Invalid cursor structure");
83
- const version = typeof data.v === "number" ? data.v : 0;
88
+ const record = data;
89
+ if (!isPlainObject(data) || !isPlainObject(record["indexValues"]) || typeof record["indexName"] !== "string" || record["indexName"].length === 0 || typeof record["orderDirection"] !== "string" || record["orderDirection"] !== "asc" && record["orderDirection"] !== "desc" || typeof record["pageSize"] !== "number" || !Number.isFinite(record["pageSize"]) || !Number.isInteger(record["pageSize"]) || record["pageSize"] <= 0) throw new Error("Invalid cursor structure");
90
+ if (typeof record["v"] !== "number") throw new Error("Unsupported cursor version: missing. Only v1 is supported.");
91
+ const version = record["v"];
84
92
  if (version !== 1) throw new Error(`Unsupported cursor version: ${version}. Only v1 is supported.`);
85
93
  return new Cursor({
86
- indexName: data.indexName,
87
- orderDirection: data.orderDirection,
88
- pageSize: data.pageSize,
89
- indexValues: data.indexValues
94
+ indexName: record["indexName"],
95
+ orderDirection: record["orderDirection"],
96
+ pageSize: record["pageSize"],
97
+ indexValues: record["indexValues"]
90
98
  });
91
99
  } catch (error) {
92
100
  throw new Error(`Invalid cursor: ${error instanceof Error ? error.message : "malformed data"}`);
@@ -115,7 +123,11 @@ function decodeCursor(cursor) {
115
123
  */
116
124
  function createCursorFromRecord(record, indexColumns, metadata) {
117
125
  const indexValues = {};
118
- for (const col of indexColumns) indexValues[col.ormName] = record[col.ormName];
126
+ for (const col of indexColumns) {
127
+ const value = record[col.name];
128
+ if (value === void 0) throw new Error(`Record is missing value for index column "${col.name}".`);
129
+ indexValues[col.name] = value;
130
+ }
119
131
  return new Cursor({
120
132
  indexName: metadata.indexName,
121
133
  orderDirection: metadata.orderDirection,
@@ -136,6 +148,7 @@ function createCursorFromRecord(record, indexColumns, metadata) {
136
148
  * @param cursor - The cursor object
137
149
  * @param indexColumns - The columns that make up the index
138
150
  * @param driverConfig - The driver configuration
151
+ * @param sqliteStorageMode - Optional SQLite storage mode override
139
152
  * @returns Serialized values ready for database queries
140
153
  *
141
154
  * @example
@@ -147,18 +160,36 @@ function createCursorFromRecord(record, indexColumns, metadata) {
147
160
  * );
148
161
  * ```
149
162
  */
150
- function serializeCursorValues(cursor, indexColumns, driverConfig) {
151
- const serializer = createSQLSerializer(driverConfig);
163
+ function serializeCursorValues(cursor, indexColumns, driverConfig, sqliteStorageMode) {
164
+ const serializer = createSQLSerializer(driverConfig, sqliteStorageMode);
152
165
  const serialized = {};
166
+ const missingColumns = [];
153
167
  for (const col of indexColumns) {
154
- const value = cursor.indexValues[col.ormName];
155
- if (value !== void 0) {
156
- const resolved = resolveFragnoIdValue(serializer.deserialize(value, col), col);
157
- serialized[col.ormName] = serializer.serialize(resolved, col);
168
+ const value = cursor.indexValues[col.name];
169
+ if (value === void 0) {
170
+ missingColumns.push(col.name);
171
+ continue;
158
172
  }
173
+ const resolved = resolveFragnoIdValue(serializer.deserialize(value, col), col);
174
+ serialized[col.name] = serializer.serialize(resolved, col);
175
+ }
176
+ if (missingColumns.length > 0) {
177
+ const suffix = cursor.indexName ? ` for index "${cursor.indexName}"` : "";
178
+ const columns = missingColumns.map((name) => `"${name}"`).join(", ");
179
+ const plural = missingColumns.length === 1 ? "" : "s";
180
+ throw new Error(`Cursor is missing values for index column${plural} ${columns}${suffix}.`);
159
181
  }
160
182
  return serialized;
161
183
  }
184
+ const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
185
+ const assertSerializableIndexValues = (values) => {
186
+ for (const [key, value] of Object.entries(values)) {
187
+ if (value === void 0) throw new Error(`Cursor index value "${key}" is undefined.`);
188
+ if (typeof value === "number" && !Number.isFinite(value)) throw new Error(`Cursor index value "${key}" must be a finite number.`);
189
+ if (typeof value === "bigint") throw new Error(`Cursor index value "${key}" must not be a BigInt.`);
190
+ if (typeof value === "function" || typeof value === "symbol") throw new Error(`Cursor index value "${key}" is not JSON-serializable.`);
191
+ }
192
+ };
162
193
 
163
194
  //#endregion
164
195
  export { Cursor, createCursorFromRecord, decodeCursor, serializeCursorValues };
@@ -1 +1 @@
1
- {"version":3,"file":"cursor.js","names":["#indexName","#orderDirection","#pageSize","#indexValues","json: string","indexValues: Record<string, unknown>","serialized: Record<string, unknown>"],"sources":["../../src/query/cursor.ts"],"sourcesContent":["import type { AnyColumn } from \"../schema/create\";\nimport { createSQLSerializer } from \"./serialize/create-sql-serializer\";\nimport { resolveFragnoIdValue } from \"./value-encoding\";\nimport type { DriverConfig } from \"../adapters/generic-sql/driver-config\";\n\n/**\n * Cursor object containing all information needed for pagination\n */\nexport class Cursor {\n readonly #indexName: string;\n readonly #orderDirection: \"asc\" | \"desc\";\n readonly #pageSize: number;\n readonly #indexValues: Record<string, unknown>;\n\n constructor(data: {\n indexName: string;\n orderDirection: \"asc\" | \"desc\";\n pageSize: number;\n indexValues: Record<string, unknown>;\n }) {\n this.#indexName = data.indexName;\n this.#orderDirection = data.orderDirection;\n this.#pageSize = data.pageSize;\n this.#indexValues = data.indexValues;\n }\n\n /**\n * Get the index name being used for pagination\n */\n get indexName(): string {\n return this.#indexName;\n }\n\n /**\n * Get the ordering direction\n */\n get orderDirection(): \"asc\" | \"desc\" {\n return this.#orderDirection;\n }\n\n /**\n * Get the page size\n */\n get pageSize(): number {\n return this.#pageSize;\n }\n\n /**\n * Get the cursor position values\n */\n get indexValues(): Record<string, unknown> {\n return this.#indexValues;\n }\n\n /**\n * Encode cursor to an opaque base64 string (safe to send to client)\n */\n encode(): string {\n const data: CursorData = {\n v: 1,\n indexName: this.#indexName,\n orderDirection: this.#orderDirection,\n pageSize: this.#pageSize,\n indexValues: this.#indexValues,\n };\n return encodeCursorData(data);\n }\n}\n\n/**\n * Result of a cursor-based query containing items and pagination cursor\n */\nexport interface CursorResult<T> {\n /**\n * The query results\n */\n items: T[];\n /**\n * Cursor to fetch the next page (undefined if no more results)\n */\n cursor?: Cursor;\n /**\n * Whether there are more results available after this page\n */\n hasNextPage: boolean;\n}\n\n/**\n * Cursor data structure for serialization\n */\nexport interface CursorData {\n v: number; // version\n indexName: string;\n orderDirection: \"asc\" | \"desc\";\n pageSize: number;\n indexValues: Record<string, unknown>;\n}\n\n/**\n * Encode cursor data to a base64 string (internal)\n */\nfunction encodeCursorData(data: CursorData): string {\n const json = JSON.stringify(data);\n // Use Buffer in Node.js or btoa in browsers\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(json, \"utf-8\").toString(\"base64\");\n }\n return btoa(json);\n}\n\n/**\n * Decode a base64 cursor string back to a Cursor object\n *\n * @param cursor - The base64-encoded cursor string\n * @returns Decoded Cursor object\n * @throws Error if cursor is invalid or malformed\n *\n * @example\n * ```ts\n * const cursor = decodeCursor(\"eyJpbmRleFZhbHVlcyI6e30sImRpcmVjdGlvbiI6ImZvcndhcmQifQ==\");\n * ```\n */\nexport function decodeCursor(cursor: string): Cursor {\n try {\n let json: string;\n if (typeof Buffer !== \"undefined\") {\n json = Buffer.from(cursor, \"base64\").toString(\"utf-8\");\n } else {\n json = atob(cursor);\n }\n const data = JSON.parse(json);\n\n // Validate structure\n if (\n !data ||\n typeof data !== \"object\" ||\n !data.indexValues ||\n typeof data.indexValues !== \"object\" ||\n typeof data.pageSize !== \"number\" ||\n !data.indexName ||\n !data.orderDirection ||\n (data.orderDirection !== \"asc\" && data.orderDirection !== \"desc\")\n ) {\n throw new Error(\"Invalid cursor structure\");\n }\n\n // Only support v1\n const version = typeof data.v === \"number\" ? data.v : 0;\n if (version !== 1) {\n throw new Error(`Unsupported cursor version: ${version}. Only v1 is supported.`);\n }\n\n return new Cursor({\n indexName: data.indexName,\n orderDirection: data.orderDirection,\n pageSize: data.pageSize,\n indexValues: data.indexValues,\n });\n } catch (error) {\n throw new Error(`Invalid cursor: ${error instanceof Error ? error.message : \"malformed data\"}`);\n }\n}\n\n/**\n * Create a cursor from a record and pagination metadata\n *\n * @param record - The database record\n * @param indexColumns - The columns that make up the index\n * @param metadata - Pagination metadata (index name, order direction, page size)\n * @returns Cursor object\n *\n * @example\n * ```ts\n * const cursor = createCursorFromRecord(\n * { id: \"abc\", name: \"Alice\", createdAt: 123 },\n * [table.columns.createdAt, table.columns.id],\n * {\n * indexName: \"idx_created\",\n * orderDirection: \"asc\",\n * pageSize: 10\n * }\n * );\n * ```\n */\nexport function createCursorFromRecord(\n record: Record<string, unknown>,\n indexColumns: AnyColumn[],\n metadata: {\n indexName: string;\n orderDirection: \"asc\" | \"desc\";\n pageSize: number;\n },\n): Cursor {\n const indexValues: Record<string, unknown> = {};\n\n for (const col of indexColumns) {\n indexValues[col.ormName] = record[col.ormName];\n }\n\n return new Cursor({\n indexName: metadata.indexName,\n orderDirection: metadata.orderDirection,\n pageSize: metadata.pageSize,\n indexValues,\n });\n}\n\n/**\n * Serialize cursor values for database queries\n *\n * Converts cursor values (which are in JSON-compatible format after decode)\n * to database format using the column serialization rules.\n *\n * This function performs a two-step process:\n * 1. Deserialize from JSON format to application format (e.g., ISO string → Date)\n * 2. Serialize from application format to database format (e.g., Date → driver format)\n *\n * @param cursor - The cursor object\n * @param indexColumns - The columns that make up the index\n * @param driverConfig - The driver configuration\n * @returns Serialized values ready for database queries\n *\n * @example\n * ```ts\n * const serialized = serializeCursorValues(\n * cursor,\n * [table.columns.createdAt],\n * driverConfig\n * );\n * ```\n */\nexport function serializeCursorValues(\n cursor: Cursor,\n indexColumns: AnyColumn[],\n driverConfig: DriverConfig,\n): Record<string, unknown> {\n const serializer = createSQLSerializer(driverConfig);\n const serialized: Record<string, unknown> = {};\n\n for (const col of indexColumns) {\n const value = cursor.indexValues[col.ormName];\n if (value !== undefined) {\n // First deserialize from JSON format to application format\n // (e.g., \"2025-11-07T09:36:57.959Z\" string → Date object)\n const deserialized = serializer.deserialize(value, col);\n // Resolve FragnoId/FragnoReference to primitive values (if present)\n const resolved = resolveFragnoIdValue(deserialized, col);\n // Then serialize to database format\n // (e.g., Date → database driver format)\n serialized[col.ormName] = serializer.serialize(resolved, col);\n }\n }\n\n return serialized;\n}\n"],"mappings":";;;;;;;AAQA,IAAa,SAAb,MAAoB;CAClB,CAASA;CACT,CAASC;CACT,CAASC;CACT,CAASC;CAET,YAAY,MAKT;AACD,QAAKH,YAAa,KAAK;AACvB,QAAKC,iBAAkB,KAAK;AAC5B,QAAKC,WAAY,KAAK;AACtB,QAAKC,cAAe,KAAK;;;;;CAM3B,IAAI,YAAoB;AACtB,SAAO,MAAKH;;;;;CAMd,IAAI,iBAAiC;AACnC,SAAO,MAAKC;;;;;CAMd,IAAI,WAAmB;AACrB,SAAO,MAAKC;;;;;CAMd,IAAI,cAAuC;AACzC,SAAO,MAAKC;;;;;CAMd,SAAiB;AAQf,SAAO,iBAPkB;GACvB,GAAG;GACH,WAAW,MAAKH;GAChB,gBAAgB,MAAKC;GACrB,UAAU,MAAKC;GACf,aAAa,MAAKC;GACnB,CAC4B;;;;;;AAoCjC,SAAS,iBAAiB,MAA0B;CAClD,MAAM,OAAO,KAAK,UAAU,KAAK;AAEjC,KAAI,OAAO,WAAW,YACpB,QAAO,OAAO,KAAK,MAAM,QAAQ,CAAC,SAAS,SAAS;AAEtD,QAAO,KAAK,KAAK;;;;;;;;;;;;;;AAenB,SAAgB,aAAa,QAAwB;AACnD,KAAI;EACF,IAAIC;AACJ,MAAI,OAAO,WAAW,YACpB,QAAO,OAAO,KAAK,QAAQ,SAAS,CAAC,SAAS,QAAQ;MAEtD,QAAO,KAAK,OAAO;EAErB,MAAM,OAAO,KAAK,MAAM,KAAK;AAG7B,MACE,CAAC,QACD,OAAO,SAAS,YAChB,CAAC,KAAK,eACN,OAAO,KAAK,gBAAgB,YAC5B,OAAO,KAAK,aAAa,YACzB,CAAC,KAAK,aACN,CAAC,KAAK,kBACL,KAAK,mBAAmB,SAAS,KAAK,mBAAmB,OAE1D,OAAM,IAAI,MAAM,2BAA2B;EAI7C,MAAM,UAAU,OAAO,KAAK,MAAM,WAAW,KAAK,IAAI;AACtD,MAAI,YAAY,EACd,OAAM,IAAI,MAAM,+BAA+B,QAAQ,yBAAyB;AAGlF,SAAO,IAAI,OAAO;GAChB,WAAW,KAAK;GAChB,gBAAgB,KAAK;GACrB,UAAU,KAAK;GACf,aAAa,KAAK;GACnB,CAAC;UACK,OAAO;AACd,QAAM,IAAI,MAAM,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;AAyBnG,SAAgB,uBACd,QACA,cACA,UAKQ;CACR,MAAMC,cAAuC,EAAE;AAE/C,MAAK,MAAM,OAAO,aAChB,aAAY,IAAI,WAAW,OAAO,IAAI;AAGxC,QAAO,IAAI,OAAO;EAChB,WAAW,SAAS;EACpB,gBAAgB,SAAS;EACzB,UAAU,SAAS;EACnB;EACD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BJ,SAAgB,sBACd,QACA,cACA,cACyB;CACzB,MAAM,aAAa,oBAAoB,aAAa;CACpD,MAAMC,aAAsC,EAAE;AAE9C,MAAK,MAAM,OAAO,cAAc;EAC9B,MAAM,QAAQ,OAAO,YAAY,IAAI;AACrC,MAAI,UAAU,QAAW;GAKvB,MAAM,WAAW,qBAFI,WAAW,YAAY,OAAO,IAAI,EAEH,IAAI;AAGxD,cAAW,IAAI,WAAW,WAAW,UAAU,UAAU,IAAI;;;AAIjE,QAAO"}
1
+ {"version":3,"file":"cursor.js","names":["#indexName","#orderDirection","#pageSize","#indexValues","json: string","indexValues: Record<string, unknown>","serialized: Record<string, unknown>","missingColumns: string[]"],"sources":["../../src/query/cursor.ts"],"sourcesContent":["import type { AnyColumn } from \"../schema/create\";\nimport { createSQLSerializer } from \"./serialize/create-sql-serializer\";\nimport { resolveFragnoIdValue } from \"./value-encoding\";\nimport type { DriverConfig } from \"../adapters/generic-sql/driver-config\";\nimport type { SQLiteStorageMode } from \"../adapters/generic-sql/sqlite-storage\";\n\n/**\n * Cursor object containing all information needed for pagination\n */\nexport class Cursor {\n readonly #indexName: string;\n readonly #orderDirection: \"asc\" | \"desc\";\n readonly #pageSize: number;\n readonly #indexValues: Record<string, unknown>;\n\n constructor(data: {\n indexName: string;\n orderDirection: \"asc\" | \"desc\";\n pageSize: number;\n indexValues: Record<string, unknown>;\n }) {\n this.#indexName = data.indexName;\n this.#orderDirection = data.orderDirection;\n this.#pageSize = data.pageSize;\n this.#indexValues = data.indexValues;\n }\n\n /**\n * Get the index name being used for pagination\n */\n get indexName(): string {\n return this.#indexName;\n }\n\n /**\n * Get the ordering direction\n */\n get orderDirection(): \"asc\" | \"desc\" {\n return this.#orderDirection;\n }\n\n /**\n * Get the page size\n */\n get pageSize(): number {\n return this.#pageSize;\n }\n\n /**\n * Get the cursor position values\n */\n get indexValues(): Record<string, unknown> {\n return this.#indexValues;\n }\n\n /**\n * Encode cursor to an opaque base64 string (safe to send to client)\n */\n encode(): string {\n assertSerializableIndexValues(this.#indexValues);\n const data: CursorData = {\n v: 1,\n indexName: this.#indexName,\n orderDirection: this.#orderDirection,\n pageSize: this.#pageSize,\n indexValues: this.#indexValues,\n };\n return encodeCursorData(data);\n }\n}\n\n/**\n * Result of a cursor-based query containing items and pagination cursor\n */\nexport interface CursorResult<T> {\n /**\n * The query results\n */\n items: T[];\n /**\n * Cursor to fetch the next page (undefined if no more results)\n */\n cursor?: Cursor;\n /**\n * Whether there are more results available after this page\n */\n hasNextPage: boolean;\n}\n\n/**\n * Cursor data structure for serialization\n */\nexport interface CursorData {\n v: number; // version\n indexName: string;\n orderDirection: \"asc\" | \"desc\";\n pageSize: number;\n indexValues: Record<string, unknown>;\n}\n\n/**\n * Encode cursor data to a base64 string (internal)\n */\nfunction encodeCursorData(data: CursorData): string {\n let json: string;\n try {\n json = JSON.stringify(data);\n } catch (error) {\n throw new Error(`Invalid cursor: ${error instanceof Error ? error.message : \"malformed data\"}`);\n }\n // Use Buffer in Node.js or btoa in browsers\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(json, \"utf-8\").toString(\"base64\");\n }\n return btoa(json);\n}\n\n/**\n * Decode a base64 cursor string back to a Cursor object\n *\n * @param cursor - The base64-encoded cursor string\n * @returns Decoded Cursor object\n * @throws Error if cursor is invalid or malformed\n *\n * @example\n * ```ts\n * const cursor = decodeCursor(\"eyJpbmRleFZhbHVlcyI6e30sImRpcmVjdGlvbiI6ImZvcndhcmQifQ==\");\n * ```\n */\nexport function decodeCursor(cursor: string): Cursor {\n try {\n let json: string;\n if (typeof Buffer !== \"undefined\") {\n json = Buffer.from(cursor, \"base64\").toString(\"utf-8\");\n } else {\n json = atob(cursor);\n }\n const data = JSON.parse(json);\n const record = data as Record<string, unknown>;\n\n // Validate structure\n if (\n !isPlainObject(data) ||\n !isPlainObject(record[\"indexValues\"]) ||\n typeof record[\"indexName\"] !== \"string\" ||\n record[\"indexName\"].length === 0 ||\n typeof record[\"orderDirection\"] !== \"string\" ||\n (record[\"orderDirection\"] !== \"asc\" && record[\"orderDirection\"] !== \"desc\") ||\n typeof record[\"pageSize\"] !== \"number\" ||\n !Number.isFinite(record[\"pageSize\"]) ||\n !Number.isInteger(record[\"pageSize\"]) ||\n record[\"pageSize\"] <= 0\n ) {\n throw new Error(\"Invalid cursor structure\");\n }\n\n // Only support v1\n if (typeof record[\"v\"] !== \"number\") {\n throw new Error(\"Unsupported cursor version: missing. Only v1 is supported.\");\n }\n const version = record[\"v\"];\n if (version !== 1) {\n throw new Error(`Unsupported cursor version: ${version}. Only v1 is supported.`);\n }\n\n return new Cursor({\n indexName: record[\"indexName\"],\n orderDirection: record[\"orderDirection\"],\n pageSize: record[\"pageSize\"],\n indexValues: record[\"indexValues\"],\n });\n } catch (error) {\n throw new Error(`Invalid cursor: ${error instanceof Error ? error.message : \"malformed data\"}`);\n }\n}\n\n/**\n * Create a cursor from a record and pagination metadata\n *\n * @param record - The database record\n * @param indexColumns - The columns that make up the index\n * @param metadata - Pagination metadata (index name, order direction, page size)\n * @returns Cursor object\n *\n * @example\n * ```ts\n * const cursor = createCursorFromRecord(\n * { id: \"abc\", name: \"Alice\", createdAt: 123 },\n * [table.columns.createdAt, table.columns.id],\n * {\n * indexName: \"idx_created\",\n * orderDirection: \"asc\",\n * pageSize: 10\n * }\n * );\n * ```\n */\nexport function createCursorFromRecord(\n record: Record<string, unknown>,\n indexColumns: AnyColumn[],\n metadata: {\n indexName: string;\n orderDirection: \"asc\" | \"desc\";\n pageSize: number;\n },\n): Cursor {\n const indexValues: Record<string, unknown> = {};\n\n for (const col of indexColumns) {\n const value = record[col.name];\n if (value === undefined) {\n throw new Error(`Record is missing value for index column \"${col.name}\".`);\n }\n indexValues[col.name] = value;\n }\n\n return new Cursor({\n indexName: metadata.indexName,\n orderDirection: metadata.orderDirection,\n pageSize: metadata.pageSize,\n indexValues,\n });\n}\n\n/**\n * Serialize cursor values for database queries\n *\n * Converts cursor values (which are in JSON-compatible format after decode)\n * to database format using the column serialization rules.\n *\n * This function performs a two-step process:\n * 1. Deserialize from JSON format to application format (e.g., ISO string → Date)\n * 2. Serialize from application format to database format (e.g., Date → driver format)\n *\n * @param cursor - The cursor object\n * @param indexColumns - The columns that make up the index\n * @param driverConfig - The driver configuration\n * @param sqliteStorageMode - Optional SQLite storage mode override\n * @returns Serialized values ready for database queries\n *\n * @example\n * ```ts\n * const serialized = serializeCursorValues(\n * cursor,\n * [table.columns.createdAt],\n * driverConfig\n * );\n * ```\n */\nexport function serializeCursorValues(\n cursor: Cursor,\n indexColumns: AnyColumn[],\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n): Record<string, unknown> {\n const serializer = createSQLSerializer(driverConfig, sqliteStorageMode);\n const serialized: Record<string, unknown> = {};\n const missingColumns: string[] = [];\n\n for (const col of indexColumns) {\n const value = cursor.indexValues[col.name];\n if (value === undefined) {\n missingColumns.push(col.name);\n continue;\n }\n // First deserialize from JSON format to application format\n // (e.g., \"2025-11-07T09:36:57.959Z\" string → Date object)\n const deserialized = serializer.deserialize(value, col);\n // Resolve FragnoId/FragnoReference to primitive values (if present)\n const resolved = resolveFragnoIdValue(deserialized, col);\n // Then serialize to database format\n // (e.g., Date → database driver format)\n serialized[col.name] = serializer.serialize(resolved, col);\n }\n\n if (missingColumns.length > 0) {\n const suffix = cursor.indexName ? ` for index \"${cursor.indexName}\"` : \"\";\n const columns = missingColumns.map((name) => `\"${name}\"`).join(\", \");\n const plural = missingColumns.length === 1 ? \"\" : \"s\";\n throw new Error(`Cursor is missing values for index column${plural} ${columns}${suffix}.`);\n }\n\n return serialized;\n}\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst assertSerializableIndexValues = (values: Record<string, unknown>): void => {\n for (const [key, value] of Object.entries(values)) {\n if (value === undefined) {\n throw new Error(`Cursor index value \"${key}\" is undefined.`);\n }\n if (typeof value === \"number\" && !Number.isFinite(value)) {\n throw new Error(`Cursor index value \"${key}\" must be a finite number.`);\n }\n if (typeof value === \"bigint\") {\n throw new Error(`Cursor index value \"${key}\" must not be a BigInt.`);\n }\n if (typeof value === \"function\" || typeof value === \"symbol\") {\n throw new Error(`Cursor index value \"${key}\" is not JSON-serializable.`);\n }\n }\n};\n"],"mappings":";;;;;;;AASA,IAAa,SAAb,MAAoB;CAClB,CAASA;CACT,CAASC;CACT,CAASC;CACT,CAASC;CAET,YAAY,MAKT;AACD,QAAKH,YAAa,KAAK;AACvB,QAAKC,iBAAkB,KAAK;AAC5B,QAAKC,WAAY,KAAK;AACtB,QAAKC,cAAe,KAAK;;;;;CAM3B,IAAI,YAAoB;AACtB,SAAO,MAAKH;;;;;CAMd,IAAI,iBAAiC;AACnC,SAAO,MAAKC;;;;;CAMd,IAAI,WAAmB;AACrB,SAAO,MAAKC;;;;;CAMd,IAAI,cAAuC;AACzC,SAAO,MAAKC;;;;;CAMd,SAAiB;AACf,gCAA8B,MAAKA,YAAa;AAQhD,SAAO,iBAPkB;GACvB,GAAG;GACH,WAAW,MAAKH;GAChB,gBAAgB,MAAKC;GACrB,UAAU,MAAKC;GACf,aAAa,MAAKC;GACnB,CAC4B;;;;;;AAoCjC,SAAS,iBAAiB,MAA0B;CAClD,IAAIC;AACJ,KAAI;AACF,SAAO,KAAK,UAAU,KAAK;UACpB,OAAO;AACd,QAAM,IAAI,MAAM,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,mBAAmB;;AAGjG,KAAI,OAAO,WAAW,YACpB,QAAO,OAAO,KAAK,MAAM,QAAQ,CAAC,SAAS,SAAS;AAEtD,QAAO,KAAK,KAAK;;;;;;;;;;;;;;AAenB,SAAgB,aAAa,QAAwB;AACnD,KAAI;EACF,IAAIA;AACJ,MAAI,OAAO,WAAW,YACpB,QAAO,OAAO,KAAK,QAAQ,SAAS,CAAC,SAAS,QAAQ;MAEtD,QAAO,KAAK,OAAO;EAErB,MAAM,OAAO,KAAK,MAAM,KAAK;EAC7B,MAAM,SAAS;AAGf,MACE,CAAC,cAAc,KAAK,IACpB,CAAC,cAAc,OAAO,eAAe,IACrC,OAAO,OAAO,iBAAiB,YAC/B,OAAO,aAAa,WAAW,KAC/B,OAAO,OAAO,sBAAsB,YACnC,OAAO,sBAAsB,SAAS,OAAO,sBAAsB,UACpE,OAAO,OAAO,gBAAgB,YAC9B,CAAC,OAAO,SAAS,OAAO,YAAY,IACpC,CAAC,OAAO,UAAU,OAAO,YAAY,IACrC,OAAO,eAAe,EAEtB,OAAM,IAAI,MAAM,2BAA2B;AAI7C,MAAI,OAAO,OAAO,SAAS,SACzB,OAAM,IAAI,MAAM,6DAA6D;EAE/E,MAAM,UAAU,OAAO;AACvB,MAAI,YAAY,EACd,OAAM,IAAI,MAAM,+BAA+B,QAAQ,yBAAyB;AAGlF,SAAO,IAAI,OAAO;GAChB,WAAW,OAAO;GAClB,gBAAgB,OAAO;GACvB,UAAU,OAAO;GACjB,aAAa,OAAO;GACrB,CAAC;UACK,OAAO;AACd,QAAM,IAAI,MAAM,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;AAyBnG,SAAgB,uBACd,QACA,cACA,UAKQ;CACR,MAAMC,cAAuC,EAAE;AAE/C,MAAK,MAAM,OAAO,cAAc;EAC9B,MAAM,QAAQ,OAAO,IAAI;AACzB,MAAI,UAAU,OACZ,OAAM,IAAI,MAAM,6CAA6C,IAAI,KAAK,IAAI;AAE5E,cAAY,IAAI,QAAQ;;AAG1B,QAAO,IAAI,OAAO;EAChB,WAAW,SAAS;EACpB,gBAAgB,SAAS;EACzB,UAAU,SAAS;EACnB;EACD,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BJ,SAAgB,sBACd,QACA,cACA,cACA,mBACyB;CACzB,MAAM,aAAa,oBAAoB,cAAc,kBAAkB;CACvE,MAAMC,aAAsC,EAAE;CAC9C,MAAMC,iBAA2B,EAAE;AAEnC,MAAK,MAAM,OAAO,cAAc;EAC9B,MAAM,QAAQ,OAAO,YAAY,IAAI;AACrC,MAAI,UAAU,QAAW;AACvB,kBAAe,KAAK,IAAI,KAAK;AAC7B;;EAMF,MAAM,WAAW,qBAFI,WAAW,YAAY,OAAO,IAAI,EAEH,IAAI;AAGxD,aAAW,IAAI,QAAQ,WAAW,UAAU,UAAU,IAAI;;AAG5D,KAAI,eAAe,SAAS,GAAG;EAC7B,MAAM,SAAS,OAAO,YAAY,eAAe,OAAO,UAAU,KAAK;EACvE,MAAM,UAAU,eAAe,KAAK,SAAS,IAAI,KAAK,GAAG,CAAC,KAAK,KAAK;EACpE,MAAM,SAAS,eAAe,WAAW,IAAI,KAAK;AAClD,QAAM,IAAI,MAAM,4CAA4C,OAAO,GAAG,UAAU,OAAO,GAAG;;AAG5F,QAAO;;AAGT,MAAM,iBAAiB,UACrB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;AAEtE,MAAM,iCAAiC,WAA0C;AAC/E,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAAE;AACjD,MAAI,UAAU,OACZ,OAAM,IAAI,MAAM,uBAAuB,IAAI,iBAAiB;AAE9D,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,MAAM,CACtD,OAAM,IAAI,MAAM,uBAAuB,IAAI,4BAA4B;AAEzE,MAAI,OAAO,UAAU,SACnB,OAAM,IAAI,MAAM,uBAAuB,IAAI,yBAAyB;AAEtE,MAAI,OAAO,UAAU,cAAc,OAAO,UAAU,SAClD,OAAM,IAAI,MAAM,uBAAuB,IAAI,6BAA6B"}
@@ -0,0 +1,8 @@
1
+ //#region src/query/db-now.d.ts
2
+ type DbNow = {
3
+ tag: "db-now";
4
+ };
5
+ declare const dbNow: () => DbNow;
6
+ //#endregion
7
+ export { DbNow, dbNow };
8
+ //# sourceMappingURL=db-now.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-now.d.ts","names":[],"sources":["../../src/query/db-now.ts"],"sourcesContent":[],"mappings":";KAAY,KAAA;EAAA,GAAA,EAAA,QAAK;AAEjB,CAAA;cAAa,aAAY"}
@@ -0,0 +1,7 @@
1
+ //#region src/query/db-now.ts
2
+ const dbNow = () => ({ tag: "db-now" });
3
+ const isDbNow = (value) => typeof value === "object" && value !== null && value.tag === "db-now";
4
+
5
+ //#endregion
6
+ export { dbNow, isDbNow };
7
+ //# sourceMappingURL=db-now.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db-now.js","names":[],"sources":["../../src/query/db-now.ts"],"sourcesContent":["export type DbNow = { tag: \"db-now\" };\n\nexport const dbNow = (): DbNow => ({ tag: \"db-now\" });\n\nexport const isDbNow = (value: unknown): value is DbNow =>\n typeof value === \"object\" && value !== null && (value as { tag?: string }).tag === \"db-now\";\n"],"mappings":";AAEA,MAAa,eAAsB,EAAE,KAAK,UAAU;AAEpD,MAAa,WAAW,UACtB,OAAO,UAAU,YAAY,UAAU,QAAS,MAA2B,QAAQ"}
@@ -11,13 +11,14 @@ import { MySQLSerializer } from "./dialect/mysql-serializer.js";
11
11
  * (PostgreSQL, MySQL, or SQLite).
12
12
  *
13
13
  * @param driverConfig - The driver configuration
14
+ * @param sqliteStorageMode - Optional SQLite storage mode override
14
15
  * @returns Dialect-specific SQLSerializer instance
15
16
  */
16
- function createSQLSerializer(driverConfig) {
17
+ function createSQLSerializer(driverConfig, sqliteStorageMode) {
17
18
  switch (driverConfig.databaseType) {
18
19
  case "postgresql": return new PostgreSQLSerializer(driverConfig);
19
20
  case "mysql": return new MySQLSerializer(driverConfig);
20
- case "sqlite": return new SQLiteSerializer(driverConfig);
21
+ case "sqlite": return new SQLiteSerializer(driverConfig, sqliteStorageMode);
21
22
  default: {
22
23
  const exhaustiveCheck = driverConfig.databaseType;
23
24
  throw new Error(`Unsupported database type: ${exhaustiveCheck}`);
@@ -1 +1 @@
1
- {"version":3,"file":"create-sql-serializer.js","names":["exhaustiveCheck: never"],"sources":["../../../src/query/serialize/create-sql-serializer.ts"],"sourcesContent":["import type { DriverConfig } from \"../../adapters/generic-sql/driver-config\";\nimport { SQLSerializer } from \"./sql-serializer\";\nimport { SQLiteSerializer } from \"./dialect/sqlite-serializer\";\nimport { PostgreSQLSerializer } from \"./dialect/postgres-serializer\";\nimport { MySQLSerializer } from \"./dialect/mysql-serializer\";\n\n// Re-export SQLSerializer for convenience\nexport { SQLSerializer } from \"./sql-serializer\";\n\n/**\n * Factory function to create a dialect-specific SQL serializer from a DriverConfig.\n *\n * Based on the database type, returns the appropriate serializer implementation\n * (PostgreSQL, MySQL, or SQLite).\n *\n * @param driverConfig - The driver configuration\n * @returns Dialect-specific SQLSerializer instance\n */\nexport function createSQLSerializer(driverConfig: DriverConfig): SQLSerializer {\n // TODO: The serializers are pretty lenient in what they accept (lost of typeof checks), it may\n // be beneficial to implement serializers per DriverConfig, and be less lenient.\n switch (driverConfig.databaseType) {\n case \"postgresql\":\n return new PostgreSQLSerializer(driverConfig);\n case \"mysql\":\n return new MySQLSerializer(driverConfig);\n case \"sqlite\":\n return new SQLiteSerializer(driverConfig);\n default: {\n const exhaustiveCheck: never = driverConfig.databaseType;\n throw new Error(`Unsupported database type: ${exhaustiveCheck}`);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAkBA,SAAgB,oBAAoB,cAA2C;AAG7E,SAAQ,aAAa,cAArB;EACE,KAAK,aACH,QAAO,IAAI,qBAAqB,aAAa;EAC/C,KAAK,QACH,QAAO,IAAI,gBAAgB,aAAa;EAC1C,KAAK,SACH,QAAO,IAAI,iBAAiB,aAAa;EAC3C,SAAS;GACP,MAAMA,kBAAyB,aAAa;AAC5C,SAAM,IAAI,MAAM,8BAA8B,kBAAkB"}
1
+ {"version":3,"file":"create-sql-serializer.js","names":["exhaustiveCheck: never"],"sources":["../../../src/query/serialize/create-sql-serializer.ts"],"sourcesContent":["import type { DriverConfig } from \"../../adapters/generic-sql/driver-config\";\nimport type { SQLiteStorageMode } from \"../../adapters/generic-sql/sqlite-storage\";\nimport { SQLSerializer } from \"./sql-serializer\";\nimport { SQLiteSerializer } from \"./dialect/sqlite-serializer\";\nimport { PostgreSQLSerializer } from \"./dialect/postgres-serializer\";\nimport { MySQLSerializer } from \"./dialect/mysql-serializer\";\n\n// Re-export SQLSerializer for convenience\nexport { SQLSerializer } from \"./sql-serializer\";\n\n/**\n * Factory function to create a dialect-specific SQL serializer from a DriverConfig.\n *\n * Based on the database type, returns the appropriate serializer implementation\n * (PostgreSQL, MySQL, or SQLite).\n *\n * @param driverConfig - The driver configuration\n * @param sqliteStorageMode - Optional SQLite storage mode override\n * @returns Dialect-specific SQLSerializer instance\n */\nexport function createSQLSerializer(\n driverConfig: DriverConfig,\n sqliteStorageMode?: SQLiteStorageMode,\n): SQLSerializer {\n // TODO: The serializers are pretty lenient in what they accept (lost of typeof checks), it may\n // be beneficial to implement serializers per DriverConfig, and be less lenient.\n switch (driverConfig.databaseType) {\n case \"postgresql\":\n return new PostgreSQLSerializer(driverConfig);\n case \"mysql\":\n return new MySQLSerializer(driverConfig);\n case \"sqlite\":\n return new SQLiteSerializer(driverConfig, sqliteStorageMode);\n default: {\n const exhaustiveCheck: never = driverConfig.databaseType;\n throw new Error(`Unsupported database type: ${exhaustiveCheck}`);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoBA,SAAgB,oBACd,cACA,mBACe;AAGf,SAAQ,aAAa,cAArB;EACE,KAAK,aACH,QAAO,IAAI,qBAAqB,aAAa;EAC/C,KAAK,QACH,QAAO,IAAI,gBAAgB,aAAa;EAC1C,KAAK,SACH,QAAO,IAAI,iBAAiB,cAAc,kBAAkB;EAC9D,SAAS;GACP,MAAMA,kBAAyB,aAAa;AAC5C,SAAM,IAAI,MAAM,8BAA8B,kBAAkB"}
@@ -17,7 +17,7 @@ var MySQLSerializer = class extends SQLSerializer {
17
17
  constructor(driverConfig) {
18
18
  super(driverConfig);
19
19
  }
20
- serializeDate(value) {
20
+ serializeDate(value, _col) {
21
21
  return value;
22
22
  }
23
23
  serializeBoolean(value) {
@@ -26,7 +26,7 @@ var MySQLSerializer = class extends SQLSerializer {
26
26
  serializeBigInt(value, _col) {
27
27
  return value;
28
28
  }
29
- deserializeDate(value) {
29
+ deserializeDate(value, _col) {
30
30
  if (value instanceof Date) return value;
31
31
  if (typeof value === "string") return new Date(value);
32
32
  throw new Error(`Cannot deserialize date from value: ${value}`);
@@ -55,10 +55,13 @@ var MySQLSerializer = class extends SQLSerializer {
55
55
  throw new Error(`Cannot deserialize binary from value: ${typeof value}`);
56
56
  }
57
57
  deserializeInteger(value) {
58
- if (typeof value === "number") return value;
58
+ if (typeof value === "number") {
59
+ if (Number.isNaN(value) || !Number.isFinite(value)) throw new Error(`Cannot deserialize integer from invalid number: ${value}`);
60
+ return value;
61
+ }
59
62
  if (typeof value === "string") {
60
63
  const num = Number(value);
61
- if (isNaN(num)) throw new Error(`Cannot deserialize integer from invalid string: ${value}`);
64
+ if (Number.isNaN(num) || !Number.isFinite(num)) throw new Error(`Cannot deserialize integer from invalid string: ${value}`);
62
65
  return num;
63
66
  }
64
67
  if (typeof value === "bigint") {
@@ -68,10 +71,13 @@ var MySQLSerializer = class extends SQLSerializer {
68
71
  throw new Error(`Cannot deserialize integer from value: ${typeof value}`);
69
72
  }
70
73
  deserializeDecimal(value) {
71
- if (typeof value === "number") return value;
74
+ if (typeof value === "number") {
75
+ if (Number.isNaN(value) || !Number.isFinite(value)) throw new Error(`Cannot deserialize decimal from invalid number: ${value}`);
76
+ return value;
77
+ }
72
78
  if (typeof value === "string") {
73
79
  const num = parseFloat(value);
74
- if (isNaN(num)) throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);
80
+ if (Number.isNaN(num) || !Number.isFinite(num)) throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);
75
81
  return num;
76
82
  }
77
83
  throw new Error(`Cannot deserialize decimal from value: ${typeof value}`);
@@ -1 +1 @@
1
- {"version":3,"file":"mysql-serializer.js","names":[],"sources":["../../../../src/query/serialize/dialect/mysql-serializer.ts"],"sourcesContent":["import type { AnyColumn } from \"../../../schema/create\";\nimport { SQLSerializer } from \"../sql-serializer\";\nimport type { DriverConfig } from \"../../../adapters/generic-sql/driver-config\";\n\n/**\n * MySQL-specific serializer.\n *\n * MySQL has good native type support:\n * - Native JSON support (MySQL 5.7+)\n * - Native boolean type (TINYINT(1))\n * - Native timestamp/datetime/date types\n * - Native bigint support\n *\n * Similar to PostgreSQL, most values pass through without conversion.\n * Timestamps/dates are returned as strings and need to be parsed.\n */\nexport class MySQLSerializer extends SQLSerializer {\n constructor(driverConfig: DriverConfig) {\n super(driverConfig);\n }\n\n protected serializeDate(value: Date): Date {\n // MySQL handles Date objects natively\n return value;\n }\n\n protected serializeBoolean(value: boolean): boolean {\n // MySQL handles boolean natively (as TINYINT(1))\n return value;\n }\n\n protected serializeBigInt(value: bigint, _col: AnyColumn): bigint {\n // MySQL handles bigint natively\n return value;\n }\n\n protected deserializeDate(value: unknown): Date {\n if (value instanceof Date) {\n return value;\n }\n // MySQL returns timestamps/dates as strings\n if (typeof value === \"string\") {\n return new Date(value);\n }\n throw new Error(`Cannot deserialize date from value: ${value}`);\n }\n\n protected deserializeBoolean(value: unknown): boolean {\n if (typeof value === \"boolean\") {\n return value;\n }\n // MySQL may return booleans as numbers (0/1)\n if (typeof value === \"number\") {\n return value === 1;\n }\n throw new Error(`Cannot deserialize boolean from value: ${value}`);\n }\n\n protected deserializeBigInt(value: unknown): bigint {\n if (typeof value === \"bigint\") {\n return value;\n }\n // MySQL may return bigints as strings\n if (typeof value === \"string\") {\n return BigInt(value);\n }\n if (typeof value === \"number\") {\n return BigInt(value);\n }\n throw new Error(`Cannot deserialize bigint from value: ${value}`);\n }\n\n protected serializeJson(value: unknown): unknown {\n // MySQL supports native JSON, pass through as-is\n return value;\n }\n\n protected deserializeJson(value: unknown): unknown {\n // MySQL returns parsed JSON objects, pass through as-is\n return value;\n }\n\n protected deserializeBinary(value: unknown): Uint8Array {\n // MySQL can return Buffer or Uint8Array for BLOB columns\n if (value instanceof Buffer) {\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n }\n if (value instanceof Uint8Array) {\n return value;\n }\n if (value instanceof ArrayBuffer) {\n return new Uint8Array(value);\n }\n throw new Error(`Cannot deserialize binary from value: ${typeof value}`);\n }\n\n protected deserializeInteger(value: unknown): number {\n if (typeof value === \"number\") {\n return value;\n }\n // MySQL may return integers as strings\n if (typeof value === \"string\") {\n const num = Number(value);\n if (isNaN(num)) {\n throw new Error(`Cannot deserialize integer from invalid string: ${value}`);\n }\n return num;\n }\n // MySQL may return bigint for large integers\n if (typeof value === \"bigint\") {\n if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {\n throw new RangeError(\n `Cannot deserialize integer value ${value}: exceeds safe integer range`,\n );\n }\n return Number(value);\n }\n throw new Error(`Cannot deserialize integer from value: ${typeof value}`);\n }\n\n protected deserializeDecimal(value: unknown): number {\n // MySQL can return decimals as numbers or strings\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value === \"string\") {\n const num = parseFloat(value);\n if (isNaN(num)) {\n throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);\n }\n return num;\n }\n throw new Error(`Cannot deserialize decimal from value: ${typeof value}`);\n }\n\n protected deserializeString(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n throw new Error(`Cannot deserialize string from value: ${typeof value}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,IAAa,kBAAb,cAAqC,cAAc;CACjD,YAAY,cAA4B;AACtC,QAAM,aAAa;;CAGrB,AAAU,cAAc,OAAmB;AAEzC,SAAO;;CAGT,AAAU,iBAAiB,OAAyB;AAElD,SAAO;;CAGT,AAAU,gBAAgB,OAAe,MAAyB;AAEhE,SAAO;;CAGT,AAAU,gBAAgB,OAAsB;AAC9C,MAAI,iBAAiB,KACnB,QAAO;AAGT,MAAI,OAAO,UAAU,SACnB,QAAO,IAAI,KAAK,MAAM;AAExB,QAAM,IAAI,MAAM,uCAAuC,QAAQ;;CAGjE,AAAU,mBAAmB,OAAyB;AACpD,MAAI,OAAO,UAAU,UACnB,QAAO;AAGT,MAAI,OAAO,UAAU,SACnB,QAAO,UAAU;AAEnB,QAAM,IAAI,MAAM,0CAA0C,QAAQ;;CAGpE,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAGT,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,QAAM,IAAI,MAAM,yCAAyC,QAAQ;;CAGnE,AAAU,cAAc,OAAyB;AAE/C,SAAO;;CAGT,AAAU,gBAAgB,OAAyB;AAEjD,SAAO;;CAGT,AAAU,kBAAkB,OAA4B;AAEtD,MAAI,iBAAiB,OACnB,QAAO,IAAI,WAAW,MAAM,QAAQ,MAAM,YAAY,MAAM,WAAW;AAEzE,MAAI,iBAAiB,WACnB,QAAO;AAET,MAAI,iBAAiB,YACnB,QAAO,IAAI,WAAW,MAAM;AAE9B,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ;;CAG1E,AAAU,mBAAmB,OAAwB;AACnD,MAAI,OAAO,UAAU,SACnB,QAAO;AAGT,MAAI,OAAO,UAAU,UAAU;GAC7B,MAAM,MAAM,OAAO,MAAM;AACzB,OAAI,MAAM,IAAI,CACZ,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAGT,MAAI,OAAO,UAAU,UAAU;AAC7B,OAAI,QAAQ,OAAO,oBAAoB,QAAQ,OAAO,iBACpD,OAAM,IAAI,WACR,oCAAoC,MAAM,8BAC3C;AAEH,UAAO,OAAO,MAAM;;AAEtB,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,mBAAmB,OAAwB;AAEnD,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,MAAI,OAAO,UAAU,UAAU;GAC7B,MAAM,MAAM,WAAW,MAAM;AAC7B,OAAI,MAAM,IAAI,CACZ,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAET,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ"}
1
+ {"version":3,"file":"mysql-serializer.js","names":[],"sources":["../../../../src/query/serialize/dialect/mysql-serializer.ts"],"sourcesContent":["import type { AnyColumn } from \"../../../schema/create\";\nimport { SQLSerializer } from \"../sql-serializer\";\nimport type { DriverConfig } from \"../../../adapters/generic-sql/driver-config\";\n\n/**\n * MySQL-specific serializer.\n *\n * MySQL has good native type support:\n * - Native JSON support (MySQL 5.7+)\n * - Native boolean type (TINYINT(1))\n * - Native timestamp/datetime/date types\n * - Native bigint support\n *\n * Similar to PostgreSQL, most values pass through without conversion.\n * Timestamps/dates are returned as strings and need to be parsed.\n */\nexport class MySQLSerializer extends SQLSerializer {\n constructor(driverConfig: DriverConfig) {\n super(driverConfig);\n }\n\n protected serializeDate(value: Date, _col: AnyColumn): Date {\n void _col;\n // MySQL handles Date objects natively\n return value;\n }\n\n protected serializeBoolean(value: boolean): boolean {\n // MySQL handles boolean natively (as TINYINT(1))\n return value;\n }\n\n protected serializeBigInt(value: bigint, _col: AnyColumn): bigint {\n // MySQL handles bigint natively\n return value;\n }\n\n protected deserializeDate(value: unknown, _col: AnyColumn): Date {\n void _col;\n if (value instanceof Date) {\n return value;\n }\n // MySQL returns timestamps/dates as strings\n if (typeof value === \"string\") {\n return new Date(value);\n }\n throw new Error(`Cannot deserialize date from value: ${value}`);\n }\n\n protected deserializeBoolean(value: unknown): boolean {\n if (typeof value === \"boolean\") {\n return value;\n }\n // MySQL may return booleans as numbers (0/1)\n if (typeof value === \"number\") {\n return value === 1;\n }\n throw new Error(`Cannot deserialize boolean from value: ${value}`);\n }\n\n protected deserializeBigInt(value: unknown): bigint {\n if (typeof value === \"bigint\") {\n return value;\n }\n // MySQL may return bigints as strings\n if (typeof value === \"string\") {\n return BigInt(value);\n }\n if (typeof value === \"number\") {\n return BigInt(value);\n }\n throw new Error(`Cannot deserialize bigint from value: ${value}`);\n }\n\n protected serializeJson(value: unknown): unknown {\n // MySQL supports native JSON, pass through as-is\n return value;\n }\n\n protected deserializeJson(value: unknown): unknown {\n // MySQL returns parsed JSON objects, pass through as-is\n return value;\n }\n\n protected deserializeBinary(value: unknown): Uint8Array {\n // MySQL can return Buffer or Uint8Array for BLOB columns\n if (value instanceof Buffer) {\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n }\n if (value instanceof Uint8Array) {\n return value;\n }\n if (value instanceof ArrayBuffer) {\n return new Uint8Array(value);\n }\n throw new Error(`Cannot deserialize binary from value: ${typeof value}`);\n }\n\n protected deserializeInteger(value: unknown): number {\n if (typeof value === \"number\") {\n if (Number.isNaN(value) || !Number.isFinite(value)) {\n throw new Error(`Cannot deserialize integer from invalid number: ${value}`);\n }\n return value;\n }\n // MySQL may return integers as strings\n if (typeof value === \"string\") {\n const num = Number(value);\n if (Number.isNaN(num) || !Number.isFinite(num)) {\n throw new Error(`Cannot deserialize integer from invalid string: ${value}`);\n }\n return num;\n }\n // MySQL may return bigint for large integers\n if (typeof value === \"bigint\") {\n if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {\n throw new RangeError(\n `Cannot deserialize integer value ${value}: exceeds safe integer range`,\n );\n }\n return Number(value);\n }\n throw new Error(`Cannot deserialize integer from value: ${typeof value}`);\n }\n\n protected deserializeDecimal(value: unknown): number {\n // MySQL can return decimals as numbers or strings\n if (typeof value === \"number\") {\n if (Number.isNaN(value) || !Number.isFinite(value)) {\n throw new Error(`Cannot deserialize decimal from invalid number: ${value}`);\n }\n return value;\n }\n if (typeof value === \"string\") {\n const num = parseFloat(value);\n if (Number.isNaN(num) || !Number.isFinite(num)) {\n throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);\n }\n return num;\n }\n throw new Error(`Cannot deserialize decimal from value: ${typeof value}`);\n }\n\n protected deserializeString(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n throw new Error(`Cannot deserialize string from value: ${typeof value}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,IAAa,kBAAb,cAAqC,cAAc;CACjD,YAAY,cAA4B;AACtC,QAAM,aAAa;;CAGrB,AAAU,cAAc,OAAa,MAAuB;AAG1D,SAAO;;CAGT,AAAU,iBAAiB,OAAyB;AAElD,SAAO;;CAGT,AAAU,gBAAgB,OAAe,MAAyB;AAEhE,SAAO;;CAGT,AAAU,gBAAgB,OAAgB,MAAuB;AAE/D,MAAI,iBAAiB,KACnB,QAAO;AAGT,MAAI,OAAO,UAAU,SACnB,QAAO,IAAI,KAAK,MAAM;AAExB,QAAM,IAAI,MAAM,uCAAuC,QAAQ;;CAGjE,AAAU,mBAAmB,OAAyB;AACpD,MAAI,OAAO,UAAU,UACnB,QAAO;AAGT,MAAI,OAAO,UAAU,SACnB,QAAO,UAAU;AAEnB,QAAM,IAAI,MAAM,0CAA0C,QAAQ;;CAGpE,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAGT,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,QAAM,IAAI,MAAM,yCAAyC,QAAQ;;CAGnE,AAAU,cAAc,OAAyB;AAE/C,SAAO;;CAGT,AAAU,gBAAgB,OAAyB;AAEjD,SAAO;;CAGT,AAAU,kBAAkB,OAA4B;AAEtD,MAAI,iBAAiB,OACnB,QAAO,IAAI,WAAW,MAAM,QAAQ,MAAM,YAAY,MAAM,WAAW;AAEzE,MAAI,iBAAiB,WACnB,QAAO;AAET,MAAI,iBAAiB,YACnB,QAAO,IAAI,WAAW,MAAM;AAE9B,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ;;CAG1E,AAAU,mBAAmB,OAAwB;AACnD,MAAI,OAAO,UAAU,UAAU;AAC7B,OAAI,OAAO,MAAM,MAAM,IAAI,CAAC,OAAO,SAAS,MAAM,CAChD,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAGT,MAAI,OAAO,UAAU,UAAU;GAC7B,MAAM,MAAM,OAAO,MAAM;AACzB,OAAI,OAAO,MAAM,IAAI,IAAI,CAAC,OAAO,SAAS,IAAI,CAC5C,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAGT,MAAI,OAAO,UAAU,UAAU;AAC7B,OAAI,QAAQ,OAAO,oBAAoB,QAAQ,OAAO,iBACpD,OAAM,IAAI,WACR,oCAAoC,MAAM,8BAC3C;AAEH,UAAO,OAAO,MAAM;;AAEtB,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,mBAAmB,OAAwB;AAEnD,MAAI,OAAO,UAAU,UAAU;AAC7B,OAAI,OAAO,MAAM,MAAM,IAAI,CAAC,OAAO,SAAS,MAAM,CAChD,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAET,MAAI,OAAO,UAAU,UAAU;GAC7B,MAAM,MAAM,WAAW,MAAM;AAC7B,OAAI,OAAO,MAAM,IAAI,IAAI,CAAC,OAAO,SAAS,IAAI,CAC5C,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAET,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ"}
@@ -16,7 +16,7 @@ var PostgreSQLSerializer = class extends SQLSerializer {
16
16
  constructor(driverConfig) {
17
17
  super(driverConfig);
18
18
  }
19
- serializeDate(value) {
19
+ serializeDate(value, _col) {
20
20
  return value;
21
21
  }
22
22
  serializeBoolean(value) {
@@ -25,9 +25,12 @@ var PostgreSQLSerializer = class extends SQLSerializer {
25
25
  serializeBigInt(value, _col) {
26
26
  return value;
27
27
  }
28
- deserializeDate(value) {
29
- if (value instanceof Date) return value;
30
- if (typeof value === "string") return new Date(value);
28
+ deserializeDate(value, _col) {
29
+ if (value instanceof Date) {
30
+ if (this.driverConfig.driverType === "pglite") return /* @__PURE__ */ new Date(value.getTime() - value.getTimezoneOffset() * 6e4);
31
+ return value;
32
+ }
33
+ if (typeof value === "string") return new Date(normalizeTimestampString(value));
31
34
  throw new Error(`Cannot deserialize date from value: ${value}`);
32
35
  }
33
36
  deserializeBoolean(value) {
@@ -53,7 +56,10 @@ var PostgreSQLSerializer = class extends SQLSerializer {
53
56
  throw new Error(`Cannot deserialize binary from value: ${typeof value}`);
54
57
  }
55
58
  deserializeInteger(value) {
56
- if (typeof value === "number") return value;
59
+ if (typeof value === "number") {
60
+ if (Number.isNaN(value) || !Number.isFinite(value)) throw new Error(`Cannot deserialize integer from invalid number: ${value}`);
61
+ return value;
62
+ }
57
63
  if (typeof value === "bigint") {
58
64
  if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) throw new RangeError(`Cannot deserialize integer value ${value}: exceeds safe integer range`);
59
65
  return Number(value);
@@ -61,10 +67,13 @@ var PostgreSQLSerializer = class extends SQLSerializer {
61
67
  throw new Error(`Cannot deserialize integer from value: ${typeof value}`);
62
68
  }
63
69
  deserializeDecimal(value) {
64
- if (typeof value === "number") return value;
70
+ if (typeof value === "number") {
71
+ if (Number.isNaN(value) || !Number.isFinite(value)) throw new Error(`Cannot deserialize decimal from invalid number: ${value}`);
72
+ return value;
73
+ }
65
74
  if (typeof value === "string") {
66
75
  const num = parseFloat(value);
67
- if (isNaN(num)) throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);
76
+ if (Number.isNaN(num) || !Number.isFinite(num)) throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);
68
77
  return num;
69
78
  }
70
79
  throw new Error(`Cannot deserialize decimal from value: ${typeof value}`);
@@ -74,6 +83,15 @@ var PostgreSQLSerializer = class extends SQLSerializer {
74
83
  throw new Error(`Cannot deserialize string from value: ${typeof value}`);
75
84
  }
76
85
  };
86
+ const normalizeTimestampString = (value) => {
87
+ if (!hasTimeComponent(value) || !isTimestampWithoutTimezone(value)) return value;
88
+ return `${value.includes(" ") ? value.replace(" ", "T") : value}Z`;
89
+ };
90
+ const hasTimeComponent = (value) => /\d{2}:\d{2}:\d{2}/.test(value);
91
+ const isTimestampWithoutTimezone = (value) => {
92
+ if (value.endsWith("Z")) return false;
93
+ return !/[+-]\d{2}(:?\d{2})?$/.test(value);
94
+ };
77
95
 
78
96
  //#endregion
79
97
  export { PostgreSQLSerializer };
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-serializer.js","names":[],"sources":["../../../../src/query/serialize/dialect/postgres-serializer.ts"],"sourcesContent":["import type { AnyColumn } from \"../../../schema/create\";\nimport { SQLSerializer } from \"../sql-serializer\";\nimport type { DriverConfig } from \"../../../adapters/generic-sql/driver-config\";\n\n/**\n * PostgreSQL-specific serializer.\n *\n * PostgreSQL has excellent native type support:\n * - Native JSON support\n * - Native boolean type\n * - Native timestamp/date types\n * - Native bigint support\n *\n * Most values pass through without conversion, only strings need to be parsed to Date.\n */\nexport class PostgreSQLSerializer extends SQLSerializer {\n constructor(driverConfig: DriverConfig) {\n super(driverConfig);\n }\n\n protected serializeDate(value: Date): Date {\n // PostgreSQL handles Date objects natively\n return value;\n }\n\n protected serializeBoolean(value: boolean): boolean {\n // PostgreSQL handles boolean natively\n return value;\n }\n\n protected serializeBigInt(value: bigint, _col: AnyColumn): bigint {\n // PostgreSQL handles bigint natively\n return value;\n }\n\n protected deserializeDate(value: unknown): Date {\n if (value instanceof Date) {\n return value;\n }\n // PostgreSQL returns timestamps/dates as strings\n if (typeof value === \"string\") {\n return new Date(value);\n }\n throw new Error(`Cannot deserialize date from value: ${value}`);\n }\n\n protected deserializeBoolean(value: unknown): boolean {\n if (typeof value === \"boolean\") {\n return value;\n }\n throw new Error(`Cannot deserialize boolean from value: ${value}`);\n }\n\n protected deserializeBigInt(value: unknown): bigint {\n if (typeof value === \"bigint\") {\n return value;\n }\n // PostgreSQL may return bigints as strings\n if (typeof value === \"string\") {\n return BigInt(value);\n }\n if (typeof value === \"number\") {\n return BigInt(value);\n }\n throw new Error(`Cannot deserialize bigint from value: ${value}`);\n }\n\n protected serializeJson(value: unknown): unknown {\n // PostgreSQL supports native JSON, pass through as-is\n return value;\n }\n\n protected deserializeJson(value: unknown): unknown {\n // PostgreSQL returns parsed JSON objects, pass through as-is\n return value;\n }\n\n protected deserializeBinary(value: unknown): Uint8Array {\n // PostgreSQL can return Buffer or Uint8Array for BYTEA columns\n if (value instanceof Buffer) {\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n }\n if (value instanceof Uint8Array) {\n return value;\n }\n if (value instanceof ArrayBuffer) {\n return new Uint8Array(value);\n }\n throw new Error(`Cannot deserialize binary from value: ${typeof value}`);\n }\n\n protected deserializeInteger(value: unknown): number {\n if (typeof value === \"number\") {\n return value;\n }\n // PostgreSQL may return bigint for large integers\n if (typeof value === \"bigint\") {\n if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {\n throw new RangeError(\n `Cannot deserialize integer value ${value}: exceeds safe integer range`,\n );\n }\n return Number(value);\n }\n throw new Error(`Cannot deserialize integer from value: ${typeof value}`);\n }\n\n protected deserializeDecimal(value: unknown): number {\n // PostgreSQL can return decimals as numbers or strings depending on precision\n if (typeof value === \"number\") {\n return value;\n }\n if (typeof value === \"string\") {\n const num = parseFloat(value);\n if (isNaN(num)) {\n throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);\n }\n return num;\n }\n throw new Error(`Cannot deserialize decimal from value: ${typeof value}`);\n }\n\n protected deserializeString(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n throw new Error(`Cannot deserialize string from value: ${typeof value}`);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAeA,IAAa,uBAAb,cAA0C,cAAc;CACtD,YAAY,cAA4B;AACtC,QAAM,aAAa;;CAGrB,AAAU,cAAc,OAAmB;AAEzC,SAAO;;CAGT,AAAU,iBAAiB,OAAyB;AAElD,SAAO;;CAGT,AAAU,gBAAgB,OAAe,MAAyB;AAEhE,SAAO;;CAGT,AAAU,gBAAgB,OAAsB;AAC9C,MAAI,iBAAiB,KACnB,QAAO;AAGT,MAAI,OAAO,UAAU,SACnB,QAAO,IAAI,KAAK,MAAM;AAExB,QAAM,IAAI,MAAM,uCAAuC,QAAQ;;CAGjE,AAAU,mBAAmB,OAAyB;AACpD,MAAI,OAAO,UAAU,UACnB,QAAO;AAET,QAAM,IAAI,MAAM,0CAA0C,QAAQ;;CAGpE,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAGT,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,QAAM,IAAI,MAAM,yCAAyC,QAAQ;;CAGnE,AAAU,cAAc,OAAyB;AAE/C,SAAO;;CAGT,AAAU,gBAAgB,OAAyB;AAEjD,SAAO;;CAGT,AAAU,kBAAkB,OAA4B;AAEtD,MAAI,iBAAiB,OACnB,QAAO,IAAI,WAAW,MAAM,QAAQ,MAAM,YAAY,MAAM,WAAW;AAEzE,MAAI,iBAAiB,WACnB,QAAO;AAET,MAAI,iBAAiB,YACnB,QAAO,IAAI,WAAW,MAAM;AAE9B,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ;;CAG1E,AAAU,mBAAmB,OAAwB;AACnD,MAAI,OAAO,UAAU,SACnB,QAAO;AAGT,MAAI,OAAO,UAAU,UAAU;AAC7B,OAAI,QAAQ,OAAO,oBAAoB,QAAQ,OAAO,iBACpD,OAAM,IAAI,WACR,oCAAoC,MAAM,8BAC3C;AAEH,UAAO,OAAO,MAAM;;AAEtB,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,mBAAmB,OAAwB;AAEnD,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,MAAI,OAAO,UAAU,UAAU;GAC7B,MAAM,MAAM,WAAW,MAAM;AAC7B,OAAI,MAAM,IAAI,CACZ,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAET,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ"}
1
+ {"version":3,"file":"postgres-serializer.js","names":[],"sources":["../../../../src/query/serialize/dialect/postgres-serializer.ts"],"sourcesContent":["import type { AnyColumn } from \"../../../schema/create\";\nimport { SQLSerializer } from \"../sql-serializer\";\nimport type { DriverConfig } from \"../../../adapters/generic-sql/driver-config\";\n\n/**\n * PostgreSQL-specific serializer.\n *\n * PostgreSQL has excellent native type support:\n * - Native JSON support\n * - Native boolean type\n * - Native timestamp/date types\n * - Native bigint support\n *\n * Most values pass through without conversion, only strings need to be parsed to Date.\n */\nexport class PostgreSQLSerializer extends SQLSerializer {\n constructor(driverConfig: DriverConfig) {\n super(driverConfig);\n }\n\n protected serializeDate(value: Date, _col: AnyColumn): Date {\n void _col;\n // PostgreSQL handles Date objects natively\n return value;\n }\n\n protected serializeBoolean(value: boolean): boolean {\n // PostgreSQL handles boolean natively\n return value;\n }\n\n protected serializeBigInt(value: bigint, _col: AnyColumn): bigint {\n // PostgreSQL handles bigint natively\n return value;\n }\n\n protected deserializeDate(value: unknown, _col: AnyColumn): Date {\n void _col;\n if (value instanceof Date) {\n if (this.driverConfig.driverType === \"pglite\") {\n return new Date(value.getTime() - value.getTimezoneOffset() * 60_000);\n }\n return value;\n }\n // PostgreSQL returns timestamps/dates as strings\n if (typeof value === \"string\") {\n // Normalize timezone-less timestamps to UTC to avoid local offset drift.\n return new Date(normalizeTimestampString(value));\n }\n throw new Error(`Cannot deserialize date from value: ${value}`);\n }\n\n protected deserializeBoolean(value: unknown): boolean {\n if (typeof value === \"boolean\") {\n return value;\n }\n throw new Error(`Cannot deserialize boolean from value: ${value}`);\n }\n\n protected deserializeBigInt(value: unknown): bigint {\n if (typeof value === \"bigint\") {\n return value;\n }\n // PostgreSQL may return bigints as strings\n if (typeof value === \"string\") {\n return BigInt(value);\n }\n if (typeof value === \"number\") {\n return BigInt(value);\n }\n throw new Error(`Cannot deserialize bigint from value: ${value}`);\n }\n\n protected serializeJson(value: unknown): unknown {\n // PostgreSQL supports native JSON, pass through as-is\n return value;\n }\n\n protected deserializeJson(value: unknown): unknown {\n // PostgreSQL returns parsed JSON objects, pass through as-is\n return value;\n }\n\n protected deserializeBinary(value: unknown): Uint8Array {\n // PostgreSQL can return Buffer or Uint8Array for BYTEA columns\n if (value instanceof Buffer) {\n return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n }\n if (value instanceof Uint8Array) {\n return value;\n }\n if (value instanceof ArrayBuffer) {\n return new Uint8Array(value);\n }\n throw new Error(`Cannot deserialize binary from value: ${typeof value}`);\n }\n\n protected deserializeInteger(value: unknown): number {\n if (typeof value === \"number\") {\n if (Number.isNaN(value) || !Number.isFinite(value)) {\n throw new Error(`Cannot deserialize integer from invalid number: ${value}`);\n }\n return value;\n }\n // PostgreSQL may return bigint for large integers\n if (typeof value === \"bigint\") {\n if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {\n throw new RangeError(\n `Cannot deserialize integer value ${value}: exceeds safe integer range`,\n );\n }\n return Number(value);\n }\n throw new Error(`Cannot deserialize integer from value: ${typeof value}`);\n }\n\n protected deserializeDecimal(value: unknown): number {\n // PostgreSQL can return decimals as numbers or strings depending on precision\n if (typeof value === \"number\") {\n if (Number.isNaN(value) || !Number.isFinite(value)) {\n throw new Error(`Cannot deserialize decimal from invalid number: ${value}`);\n }\n return value;\n }\n if (typeof value === \"string\") {\n const num = parseFloat(value);\n if (Number.isNaN(num) || !Number.isFinite(num)) {\n throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);\n }\n return num;\n }\n throw new Error(`Cannot deserialize decimal from value: ${typeof value}`);\n }\n\n protected deserializeString(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n throw new Error(`Cannot deserialize string from value: ${typeof value}`);\n }\n}\n\nconst normalizeTimestampString = (value: string) => {\n if (!hasTimeComponent(value) || !isTimestampWithoutTimezone(value)) {\n return value;\n }\n const withTimeSeparator = value.includes(\" \") ? value.replace(\" \", \"T\") : value;\n return `${withTimeSeparator}Z`;\n};\n\nconst hasTimeComponent = (value: string) => /\\d{2}:\\d{2}:\\d{2}/.test(value);\n\nconst isTimestampWithoutTimezone = (value: string) => {\n // Detect RFC3339-like timezone indicators: Z or +/-HH(:MM)?\n if (value.endsWith(\"Z\")) {\n return false;\n }\n return !/[+-]\\d{2}(:?\\d{2})?$/.test(value);\n};\n"],"mappings":";;;;;;;;;;;;;;AAeA,IAAa,uBAAb,cAA0C,cAAc;CACtD,YAAY,cAA4B;AACtC,QAAM,aAAa;;CAGrB,AAAU,cAAc,OAAa,MAAuB;AAG1D,SAAO;;CAGT,AAAU,iBAAiB,OAAyB;AAElD,SAAO;;CAGT,AAAU,gBAAgB,OAAe,MAAyB;AAEhE,SAAO;;CAGT,AAAU,gBAAgB,OAAgB,MAAuB;AAE/D,MAAI,iBAAiB,MAAM;AACzB,OAAI,KAAK,aAAa,eAAe,SACnC,wBAAO,IAAI,KAAK,MAAM,SAAS,GAAG,MAAM,mBAAmB,GAAG,IAAO;AAEvE,UAAO;;AAGT,MAAI,OAAO,UAAU,SAEnB,QAAO,IAAI,KAAK,yBAAyB,MAAM,CAAC;AAElD,QAAM,IAAI,MAAM,uCAAuC,QAAQ;;CAGjE,AAAU,mBAAmB,OAAyB;AACpD,MAAI,OAAO,UAAU,UACnB,QAAO;AAET,QAAM,IAAI,MAAM,0CAA0C,QAAQ;;CAGpE,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAGT,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,MAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,QAAM,IAAI,MAAM,yCAAyC,QAAQ;;CAGnE,AAAU,cAAc,OAAyB;AAE/C,SAAO;;CAGT,AAAU,gBAAgB,OAAyB;AAEjD,SAAO;;CAGT,AAAU,kBAAkB,OAA4B;AAEtD,MAAI,iBAAiB,OACnB,QAAO,IAAI,WAAW,MAAM,QAAQ,MAAM,YAAY,MAAM,WAAW;AAEzE,MAAI,iBAAiB,WACnB,QAAO;AAET,MAAI,iBAAiB,YACnB,QAAO,IAAI,WAAW,MAAM;AAE9B,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ;;CAG1E,AAAU,mBAAmB,OAAwB;AACnD,MAAI,OAAO,UAAU,UAAU;AAC7B,OAAI,OAAO,MAAM,MAAM,IAAI,CAAC,OAAO,SAAS,MAAM,CAChD,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAGT,MAAI,OAAO,UAAU,UAAU;AAC7B,OAAI,QAAQ,OAAO,oBAAoB,QAAQ,OAAO,iBACpD,OAAM,IAAI,WACR,oCAAoC,MAAM,8BAC3C;AAEH,UAAO,OAAO,MAAM;;AAEtB,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,mBAAmB,OAAwB;AAEnD,MAAI,OAAO,UAAU,UAAU;AAC7B,OAAI,OAAO,MAAM,MAAM,IAAI,CAAC,OAAO,SAAS,MAAM,CAChD,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAET,MAAI,OAAO,UAAU,UAAU;GAC7B,MAAM,MAAM,WAAW,MAAM;AAC7B,OAAI,OAAO,MAAM,IAAI,IAAI,CAAC,OAAO,SAAS,IAAI,CAC5C,OAAM,IAAI,MAAM,mDAAmD,QAAQ;AAE7E,UAAO;;AAET,QAAM,IAAI,MAAM,0CAA0C,OAAO,QAAQ;;CAG3E,AAAU,kBAAkB,OAAwB;AAClD,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,QAAM,IAAI,MAAM,yCAAyC,OAAO,QAAQ;;;AAI5E,MAAM,4BAA4B,UAAkB;AAClD,KAAI,CAAC,iBAAiB,MAAM,IAAI,CAAC,2BAA2B,MAAM,CAChE,QAAO;AAGT,QAAO,GADmB,MAAM,SAAS,IAAI,GAAG,MAAM,QAAQ,KAAK,IAAI,GAAG,MAC9C;;AAG9B,MAAM,oBAAoB,UAAkB,oBAAoB,KAAK,MAAM;AAE3E,MAAM,8BAA8B,UAAkB;AAEpD,KAAI,MAAM,SAAS,IAAI,CACrB,QAAO;AAET,QAAO,CAAC,uBAAuB,KAAK,MAAM"}
@@ -1,21 +1,33 @@
1
1
  import { SQLSerializer } from "../sql-serializer.js";
2
+ import { sqliteStorageDefault } from "../../../adapters/generic-sql/sqlite-storage.js";
2
3
 
3
4
  //#region src/query/serialize/dialect/sqlite-serializer.ts
5
+ const SQLITE_UTC_TIMESTAMP_REGEX = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/;
6
+ function parseSQLiteUtcTimestamp(value) {
7
+ const match = SQLITE_UTC_TIMESTAMP_REGEX.exec(value);
8
+ if (!match) return null;
9
+ const [, year, month, day, hour, minute, second, millis] = match;
10
+ const milliseconds = millis ? Number(millis.padEnd(3, "0")) : 0;
11
+ return new Date(Date.UTC(Number(year), Number(month) - 1, Number(day), Number(hour), Number(minute), Number(second), milliseconds));
12
+ }
4
13
  /**
5
14
  * SQLite-specific serializer.
6
15
  *
7
16
  * SQLite has limited native type support and requires conversions:
8
17
  * - JSON → strings (no native JSON support)
9
- * - Dates → numbers (timestamps)
18
+ * - Dates → numbers or ISO strings (storage-mode dependent)
10
19
  * - Booleans → 0/1
11
- * - BigInts → Buffer (except for internal-id and reference columns → number)
20
+ * - BigInts → Buffer or integer (storage-mode dependent; internal-id/reference stay integer)
12
21
  * - Numbers/strings → Date for timestamps/dates
13
22
  */
14
23
  var SQLiteSerializer = class extends SQLSerializer {
15
- constructor(driverConfig) {
24
+ sqliteStorageMode;
25
+ constructor(driverConfig, sqliteStorageMode) {
16
26
  super(driverConfig);
27
+ this.sqliteStorageMode = sqliteStorageMode ?? sqliteStorageDefault;
17
28
  }
18
- serializeDate(value) {
29
+ serializeDate(value, col) {
30
+ if ((col.type === "date" ? this.sqliteStorageMode.dateStorage : this.sqliteStorageMode.timestampStorage) === "iso-text") return value.toISOString();
19
31
  return value.getTime();
20
32
  }
21
33
  serializeBoolean(value) {
@@ -26,13 +38,34 @@ var SQLiteSerializer = class extends SQLSerializer {
26
38
  if (Math.abs(Number(value)) > Number.MAX_SAFE_INTEGER) throw new RangeError(`Cannot serialize bigint value ${value} for column "${col.name}": value exceeds Number.MAX_SAFE_INTEGER (${Number.MAX_SAFE_INTEGER}). SQLite reference and internal-id columns use INTEGER type which requires values to fit within JavaScript's safe integer range.`);
27
39
  return Number(value);
28
40
  }
41
+ if (this.sqliteStorageMode.bigintStorage === "integer") return value;
29
42
  const buf = Buffer.alloc(8);
30
43
  buf.writeBigInt64BE(value);
31
44
  return buf;
32
45
  }
33
- deserializeDate(value) {
46
+ deserializeDate(value, col) {
34
47
  if (value instanceof Date) return value;
35
- if (typeof value === "number" || typeof value === "string") return new Date(value);
48
+ if (typeof value === "string") {
49
+ if (/^\d+$/.test(value)) {
50
+ const numericDate = new Date(Number(value));
51
+ if (Number.isNaN(numericDate.getTime())) throw new Error(`Cannot deserialize date from value: ${value}`);
52
+ return numericDate;
53
+ }
54
+ const date = parseSQLiteUtcTimestamp(value) ?? new Date(value);
55
+ if (Number.isNaN(date.getTime())) throw new Error(`Cannot deserialize date from value: ${value}`);
56
+ return date;
57
+ }
58
+ if (typeof value === "number") {
59
+ if (Number.isNaN(value)) throw new Error(`Cannot deserialize date from value: ${value}`);
60
+ return new Date(value);
61
+ }
62
+ if (typeof value === "bigint") {
63
+ if ((col.type === "date" ? this.sqliteStorageMode.dateStorage : this.sqliteStorageMode.timestampStorage) === "epoch-ms") {
64
+ const date = new Date(Number(value));
65
+ if (Number.isNaN(date.getTime())) throw new Error(`Cannot deserialize date from value: ${value}`);
66
+ return date;
67
+ }
68
+ }
36
69
  throw new Error(`Cannot deserialize date from value: ${value}`);
37
70
  }
38
71
  deserializeBoolean(value) {
@@ -44,7 +77,12 @@ var SQLiteSerializer = class extends SQLSerializer {
44
77
  if (typeof value === "bigint") return value;
45
78
  if (value instanceof Buffer) return value.readBigInt64BE(0);
46
79
  if (typeof value === "string") return BigInt(value);
47
- if (typeof value === "number") return BigInt(value);
80
+ if (typeof value === "number") {
81
+ if (this.sqliteStorageMode.bigintStorage === "integer") {
82
+ if (Math.abs(value) > Number.MAX_SAFE_INTEGER) throw new RangeError(`Cannot deserialize bigint value ${value}: exceeds Number.MAX_SAFE_INTEGER`);
83
+ }
84
+ return BigInt(value);
85
+ }
48
86
  throw new Error(`Cannot deserialize bigint from value: ${value}`);
49
87
  }
50
88
  serializeJson(value) {
@@ -61,10 +99,13 @@ var SQLiteSerializer = class extends SQLSerializer {
61
99
  throw new Error(`Cannot deserialize binary from value: ${typeof value}`);
62
100
  }
63
101
  deserializeInteger(value) {
64
- if (typeof value === "number") return value;
102
+ if (typeof value === "number") {
103
+ if (Number.isNaN(value) || !Number.isFinite(value)) throw new Error(`Cannot deserialize integer from invalid number: ${value}`);
104
+ return value;
105
+ }
65
106
  if (typeof value === "string") {
66
107
  const num = Number(value);
67
- if (isNaN(num)) throw new Error(`Cannot deserialize integer from invalid string: ${value}`);
108
+ if (Number.isNaN(num) || !Number.isFinite(num)) throw new Error(`Cannot deserialize integer from invalid string: ${value}`);
68
109
  return num;
69
110
  }
70
111
  if (typeof value === "bigint") {
@@ -74,10 +115,13 @@ var SQLiteSerializer = class extends SQLSerializer {
74
115
  throw new Error(`Cannot deserialize integer from value: ${typeof value}`);
75
116
  }
76
117
  deserializeDecimal(value) {
77
- if (typeof value === "number") return value;
118
+ if (typeof value === "number") {
119
+ if (Number.isNaN(value) || !Number.isFinite(value)) throw new Error(`Cannot deserialize decimal from invalid number: ${value}`);
120
+ return value;
121
+ }
78
122
  if (typeof value === "string") {
79
123
  const num = parseFloat(value);
80
- if (isNaN(num)) throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);
124
+ if (Number.isNaN(num) || !Number.isFinite(num)) throw new Error(`Cannot deserialize decimal from invalid string: ${value}`);
81
125
  return num;
82
126
  }
83
127
  throw new Error(`Cannot deserialize decimal from value: ${typeof value}`);