@syncular/server 0.1.2 → 0.2.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 (758) hide show
  1. package/README.md +773 -13
  2. package/dist/admin.d.ts +136 -0
  3. package/dist/admin.js +168 -0
  4. package/dist/blob-handlers.d.ts +69 -0
  5. package/dist/blob-handlers.js +245 -0
  6. package/dist/blob-store.d.ts +111 -0
  7. package/dist/blob-store.js +0 -0
  8. package/dist/content-encoding.d.ts +27 -0
  9. package/dist/content-encoding.js +69 -0
  10. package/dist/context.d.ts +151 -0
  11. package/dist/context.js +21 -0
  12. package/dist/crdt-merger.d.ts +28 -0
  13. package/dist/crdt-merger.js +11 -0
  14. package/dist/d1-storage.d.ts +50 -0
  15. package/dist/d1-storage.js +0 -0
  16. package/dist/errors.d.ts +35 -9
  17. package/dist/errors.js +220 -11
  18. package/dist/events-ring.d.ts +55 -0
  19. package/dist/events-ring.js +96 -0
  20. package/dist/events.d.ts +231 -0
  21. package/dist/events.js +22 -0
  22. package/dist/frame-bytes.d.ts +20 -0
  23. package/dist/frame-bytes.js +75 -0
  24. package/dist/handler.d.ts +9 -0
  25. package/dist/handler.js +490 -0
  26. package/dist/index.d.ts +42 -33
  27. package/dist/index.js +45 -27
  28. package/dist/lease-store.d.ts +50 -0
  29. package/dist/lease-store.js +0 -0
  30. package/dist/pg-executor-pglite.d.ts +27 -0
  31. package/dist/pg-executor-pglite.js +33 -0
  32. package/dist/pg-executor.d.ts +67 -0
  33. package/dist/pg-executor.js +56 -0
  34. package/dist/postgres-fanout.d.ts +83 -0
  35. package/dist/postgres-fanout.js +71 -0
  36. package/dist/postgres-storage.d.ts +69 -0
  37. package/dist/postgres-storage.js +766 -0
  38. package/dist/prune.d.ts +24 -39
  39. package/dist/prune.js +44 -146
  40. package/dist/pull.d.ts +42 -67
  41. package/dist/pull.js +387 -1187
  42. package/dist/push.d.ts +31 -66
  43. package/dist/push.js +406 -655
  44. package/dist/realtime.d.ts +197 -0
  45. package/dist/realtime.js +848 -0
  46. package/dist/relational-rows.d.ts +229 -0
  47. package/dist/relational-rows.js +514 -0
  48. package/dist/s3-blob-store.d.ts +142 -0
  49. package/dist/s3-blob-store.js +458 -0
  50. package/dist/s3-segment-store.d.ts +95 -0
  51. package/dist/s3-segment-store.js +380 -0
  52. package/dist/schema.d.ts +82 -286
  53. package/dist/schema.js +133 -9
  54. package/dist/scopes.d.ts +48 -0
  55. package/dist/scopes.js +98 -0
  56. package/dist/segment-download.d.ts +14 -0
  57. package/dist/segment-download.js +125 -0
  58. package/dist/segment-store.d.ts +81 -0
  59. package/dist/segment-store.js +63 -0
  60. package/dist/signed-url.d.ts +139 -0
  61. package/dist/signed-url.js +143 -0
  62. package/dist/sigv4.d.ts +97 -0
  63. package/dist/sigv4.js +161 -0
  64. package/dist/sqlite-blob-store.d.ts +22 -0
  65. package/dist/sqlite-blob-store.js +86 -0
  66. package/dist/sqlite-dialect.d.ts +101 -0
  67. package/dist/sqlite-dialect.js +250 -0
  68. package/dist/sqlite-image.d.ts +27 -0
  69. package/dist/sqlite-image.js +83 -0
  70. package/dist/sqlite-lease-store.d.ts +21 -0
  71. package/dist/sqlite-lease-store.js +94 -0
  72. package/dist/sqlite-segment-store.d.ts +25 -0
  73. package/dist/sqlite-segment-store.js +115 -0
  74. package/dist/sqlite-storage.d.ts +47 -0
  75. package/dist/sqlite-storage.js +477 -0
  76. package/dist/storage.d.ts +252 -0
  77. package/dist/storage.js +1 -0
  78. package/dist/validate.d.ts +83 -0
  79. package/dist/validate.js +44 -0
  80. package/package.json +17 -325
  81. package/src/admin.ts +312 -0
  82. package/src/blob-handlers.ts +340 -0
  83. package/src/blob-store.ts +0 -0
  84. package/src/content-encoding.ts +94 -0
  85. package/src/context.ts +176 -0
  86. package/src/crdt-merger.ts +33 -0
  87. package/src/d1-storage.ts +0 -0
  88. package/src/errors.ts +241 -19
  89. package/src/events-ring.ts +116 -0
  90. package/src/events.ts +291 -0
  91. package/src/frame-bytes.ts +94 -0
  92. package/src/handler.ts +678 -0
  93. package/src/index.ts +44 -27
  94. package/src/lease-store.ts +0 -0
  95. package/src/pg-executor-pglite.ts +63 -0
  96. package/src/pg-executor.ts +87 -0
  97. package/src/postgres-fanout.ts +143 -0
  98. package/src/postgres-storage.ts +1182 -0
  99. package/src/prune.ts +63 -289
  100. package/src/pull.ts +505 -1805
  101. package/src/push.ts +623 -1006
  102. package/src/realtime.ts +1082 -0
  103. package/src/relational-rows.ts +633 -0
  104. package/src/s3-blob-store.ts +616 -0
  105. package/src/s3-segment-store.ts +519 -0
  106. package/src/schema.ts +242 -281
  107. package/src/scopes.ts +127 -0
  108. package/src/segment-download.ts +169 -0
  109. package/src/segment-store.ts +154 -0
  110. package/src/signed-url.ts +308 -0
  111. package/src/sigv4.ts +267 -0
  112. package/src/sqlite-blob-store.ts +125 -0
  113. package/src/sqlite-dialect.ts +337 -0
  114. package/src/sqlite-image.ts +124 -0
  115. package/src/sqlite-lease-store.ts +144 -0
  116. package/src/sqlite-segment-store.ts +204 -0
  117. package/src/sqlite-storage.ts +792 -0
  118. package/src/storage.ts +316 -0
  119. package/src/validate.ts +123 -0
  120. package/dist/auth-leases.d.ts +0 -85
  121. package/dist/auth-leases.d.ts.map +0 -1
  122. package/dist/auth-leases.js +0 -368
  123. package/dist/auth-leases.js.map +0 -1
  124. package/dist/better-sqlite3.d.ts +0 -22
  125. package/dist/better-sqlite3.d.ts.map +0 -1
  126. package/dist/better-sqlite3.js +0 -16
  127. package/dist/better-sqlite3.js.map +0 -1
  128. package/dist/blobs/access.d.ts +0 -35
  129. package/dist/blobs/access.d.ts.map +0 -1
  130. package/dist/blobs/access.js +0 -149
  131. package/dist/blobs/access.js.map +0 -1
  132. package/dist/blobs/adapters/database.d.ts +0 -100
  133. package/dist/blobs/adapters/database.d.ts.map +0 -1
  134. package/dist/blobs/adapters/database.js +0 -247
  135. package/dist/blobs/adapters/database.js.map +0 -1
  136. package/dist/blobs/index.d.ts +0 -9
  137. package/dist/blobs/index.d.ts.map +0 -1
  138. package/dist/blobs/index.js +0 -9
  139. package/dist/blobs/index.js.map +0 -1
  140. package/dist/blobs/manager.d.ts +0 -220
  141. package/dist/blobs/manager.d.ts.map +0 -1
  142. package/dist/blobs/manager.js +0 -625
  143. package/dist/blobs/manager.js.map +0 -1
  144. package/dist/blobs/migrate.d.ts +0 -27
  145. package/dist/blobs/migrate.d.ts.map +0 -1
  146. package/dist/blobs/migrate.js +0 -127
  147. package/dist/blobs/migrate.js.map +0 -1
  148. package/dist/blobs/types.d.ts +0 -58
  149. package/dist/blobs/types.d.ts.map +0 -1
  150. package/dist/blobs/types.js +0 -5
  151. package/dist/blobs/types.js.map +0 -1
  152. package/dist/bun-sqlite.d.ts +0 -19
  153. package/dist/bun-sqlite.d.ts.map +0 -1
  154. package/dist/bun-sqlite.js +0 -19
  155. package/dist/bun-sqlite.js.map +0 -1
  156. package/dist/clients.d.ts +0 -15
  157. package/dist/clients.d.ts.map +0 -1
  158. package/dist/clients.js +0 -7
  159. package/dist/clients.js.map +0 -1
  160. package/dist/cloudflare/durable-object.d.ts +0 -93
  161. package/dist/cloudflare/durable-object.d.ts.map +0 -1
  162. package/dist/cloudflare/durable-object.js +0 -210
  163. package/dist/cloudflare/durable-object.js.map +0 -1
  164. package/dist/cloudflare/index.d.ts +0 -22
  165. package/dist/cloudflare/index.d.ts.map +0 -1
  166. package/dist/cloudflare/index.js +0 -22
  167. package/dist/cloudflare/index.js.map +0 -1
  168. package/dist/cloudflare/r2.d.ts +0 -180
  169. package/dist/cloudflare/r2.d.ts.map +0 -1
  170. package/dist/cloudflare/r2.js +0 -258
  171. package/dist/cloudflare/r2.js.map +0 -1
  172. package/dist/cloudflare/scope-cache.d.ts +0 -54
  173. package/dist/cloudflare/scope-cache.d.ts.map +0 -1
  174. package/dist/cloudflare/scope-cache.js +0 -223
  175. package/dist/cloudflare/scope-cache.js.map +0 -1
  176. package/dist/cloudflare/sentry.d.ts +0 -47
  177. package/dist/cloudflare/sentry.d.ts.map +0 -1
  178. package/dist/cloudflare/sentry.js +0 -163
  179. package/dist/cloudflare/sentry.js.map +0 -1
  180. package/dist/cloudflare/worker.d.ts +0 -46
  181. package/dist/cloudflare/worker.d.ts.map +0 -1
  182. package/dist/cloudflare/worker.js +0 -63
  183. package/dist/cloudflare/worker.js.map +0 -1
  184. package/dist/commit-integrity.d.ts +0 -38
  185. package/dist/commit-integrity.d.ts.map +0 -1
  186. package/dist/commit-integrity.js +0 -260
  187. package/dist/commit-integrity.js.map +0 -1
  188. package/dist/compaction.d.ts +0 -27
  189. package/dist/compaction.d.ts.map +0 -1
  190. package/dist/compaction.js +0 -49
  191. package/dist/compaction.js.map +0 -1
  192. package/dist/crdt-yjs/index.d.ts +0 -99
  193. package/dist/crdt-yjs/index.d.ts.map +0 -1
  194. package/dist/crdt-yjs/index.js +0 -629
  195. package/dist/crdt-yjs/index.js.map +0 -1
  196. package/dist/d1.d.ts +0 -13
  197. package/dist/d1.d.ts.map +0 -1
  198. package/dist/d1.js +0 -14
  199. package/dist/d1.js.map +0 -1
  200. package/dist/dialect/base.d.ts +0 -93
  201. package/dist/dialect/base.d.ts.map +0 -1
  202. package/dist/dialect/base.js +0 -181
  203. package/dist/dialect/base.js.map +0 -1
  204. package/dist/dialect/helpers.d.ts +0 -16
  205. package/dist/dialect/helpers.d.ts.map +0 -1
  206. package/dist/dialect/helpers.js +0 -83
  207. package/dist/dialect/helpers.js.map +0 -1
  208. package/dist/dialect/index.d.ts +0 -7
  209. package/dist/dialect/index.d.ts.map +0 -1
  210. package/dist/dialect/index.js +0 -7
  211. package/dist/dialect/index.js.map +0 -1
  212. package/dist/dialect/types.d.ts +0 -187
  213. package/dist/dialect/types.d.ts.map +0 -1
  214. package/dist/dialect/types.js +0 -8
  215. package/dist/dialect/types.js.map +0 -1
  216. package/dist/encrypted-crdt.d.ts +0 -67
  217. package/dist/encrypted-crdt.d.ts.map +0 -1
  218. package/dist/encrypted-crdt.js +0 -426
  219. package/dist/encrypted-crdt.js.map +0 -1
  220. package/dist/errors.d.ts.map +0 -1
  221. package/dist/errors.js.map +0 -1
  222. package/dist/filesystem/index.d.ts +0 -44
  223. package/dist/filesystem/index.d.ts.map +0 -1
  224. package/dist/filesystem/index.js +0 -164
  225. package/dist/filesystem/index.js.map +0 -1
  226. package/dist/handlers/collection.d.ts +0 -20
  227. package/dist/handlers/collection.d.ts.map +0 -1
  228. package/dist/handlers/collection.js +0 -42
  229. package/dist/handlers/collection.js.map +0 -1
  230. package/dist/handlers/create-handler.d.ts +0 -156
  231. package/dist/handlers/create-handler.d.ts.map +0 -1
  232. package/dist/handlers/create-handler.js +0 -626
  233. package/dist/handlers/create-handler.js.map +0 -1
  234. package/dist/handlers/index.d.ts +0 -4
  235. package/dist/handlers/index.d.ts.map +0 -1
  236. package/dist/handlers/index.js +0 -4
  237. package/dist/handlers/index.js.map +0 -1
  238. package/dist/handlers/types.d.ts +0 -295
  239. package/dist/handlers/types.d.ts.map +0 -1
  240. package/dist/handlers/types.js +0 -2
  241. package/dist/handlers/types.js.map +0 -1
  242. package/dist/helpers/conflict.d.ts +0 -52
  243. package/dist/helpers/conflict.d.ts.map +0 -1
  244. package/dist/helpers/conflict.js +0 -49
  245. package/dist/helpers/conflict.js.map +0 -1
  246. package/dist/helpers/emitted-change.d.ts +0 -56
  247. package/dist/helpers/emitted-change.d.ts.map +0 -1
  248. package/dist/helpers/emitted-change.js +0 -46
  249. package/dist/helpers/emitted-change.js.map +0 -1
  250. package/dist/helpers/index.d.ts +0 -12
  251. package/dist/helpers/index.d.ts.map +0 -1
  252. package/dist/helpers/index.js +0 -12
  253. package/dist/helpers/index.js.map +0 -1
  254. package/dist/helpers/paginate.d.ts +0 -49
  255. package/dist/helpers/paginate.d.ts.map +0 -1
  256. package/dist/helpers/paginate.js +0 -54
  257. package/dist/helpers/paginate.js.map +0 -1
  258. package/dist/helpers/scope-authorization.d.ts +0 -7
  259. package/dist/helpers/scope-authorization.d.ts.map +0 -1
  260. package/dist/helpers/scope-authorization.js +0 -19
  261. package/dist/helpers/scope-authorization.js.map +0 -1
  262. package/dist/helpers/scope-commit-index.d.ts +0 -12
  263. package/dist/helpers/scope-commit-index.d.ts.map +0 -1
  264. package/dist/helpers/scope-commit-index.js +0 -35
  265. package/dist/helpers/scope-commit-index.js.map +0 -1
  266. package/dist/helpers/scope-strings.d.ts +0 -74
  267. package/dist/helpers/scope-strings.d.ts.map +0 -1
  268. package/dist/helpers/scope-strings.js +0 -82
  269. package/dist/helpers/scope-strings.js.map +0 -1
  270. package/dist/hono/api-key-auth.d.ts +0 -49
  271. package/dist/hono/api-key-auth.d.ts.map +0 -1
  272. package/dist/hono/api-key-auth.js +0 -108
  273. package/dist/hono/api-key-auth.js.map +0 -1
  274. package/dist/hono/audit-redaction.d.ts +0 -20
  275. package/dist/hono/audit-redaction.d.ts.map +0 -1
  276. package/dist/hono/audit-redaction.js +0 -85
  277. package/dist/hono/audit-redaction.js.map +0 -1
  278. package/dist/hono/blobs.d.ts +0 -75
  279. package/dist/hono/blobs.d.ts.map +0 -1
  280. package/dist/hono/blobs.js +0 -586
  281. package/dist/hono/blobs.js.map +0 -1
  282. package/dist/hono/console/gateway.d.ts +0 -42
  283. package/dist/hono/console/gateway.d.ts.map +0 -1
  284. package/dist/hono/console/gateway.js +0 -2158
  285. package/dist/hono/console/gateway.js.map +0 -1
  286. package/dist/hono/console/live-auth.d.ts +0 -7
  287. package/dist/hono/console/live-auth.d.ts.map +0 -1
  288. package/dist/hono/console/live-auth.js +0 -39
  289. package/dist/hono/console/live-auth.js.map +0 -1
  290. package/dist/hono/console/route-descriptor.d.ts +0 -6
  291. package/dist/hono/console/route-descriptor.d.ts.map +0 -1
  292. package/dist/hono/console/route-descriptor.js +0 -16
  293. package/dist/hono/console/route-descriptor.js.map +0 -1
  294. package/dist/hono/console/routes/api-keys.d.ts +0 -8
  295. package/dist/hono/console/routes/api-keys.d.ts.map +0 -1
  296. package/dist/hono/console/routes/api-keys.js +0 -575
  297. package/dist/hono/console/routes/api-keys.js.map +0 -1
  298. package/dist/hono/console/routes/clients.d.ts +0 -8
  299. package/dist/hono/console/routes/clients.d.ts.map +0 -1
  300. package/dist/hono/console/routes/clients.js +0 -322
  301. package/dist/hono/console/routes/clients.js.map +0 -1
  302. package/dist/hono/console/routes/commits.d.ts +0 -8
  303. package/dist/hono/console/routes/commits.d.ts.map +0 -1
  304. package/dist/hono/console/routes/commits.js +0 -882
  305. package/dist/hono/console/routes/commits.js.map +0 -1
  306. package/dist/hono/console/routes/context.d.ts +0 -188
  307. package/dist/hono/console/routes/context.d.ts.map +0 -1
  308. package/dist/hono/console/routes/context.js +0 -633
  309. package/dist/hono/console/routes/context.js.map +0 -1
  310. package/dist/hono/console/routes/events.d.ts +0 -8
  311. package/dist/hono/console/routes/events.d.ts.map +0 -1
  312. package/dist/hono/console/routes/events.js +0 -501
  313. package/dist/hono/console/routes/events.js.map +0 -1
  314. package/dist/hono/console/routes/maintenance.d.ts +0 -8
  315. package/dist/hono/console/routes/maintenance.d.ts.map +0 -1
  316. package/dist/hono/console/routes/maintenance.js +0 -341
  317. package/dist/hono/console/routes/maintenance.js.map +0 -1
  318. package/dist/hono/console/routes/shared.d.ts +0 -174
  319. package/dist/hono/console/routes/shared.d.ts.map +0 -1
  320. package/dist/hono/console/routes/shared.js +0 -583
  321. package/dist/hono/console/routes/shared.js.map +0 -1
  322. package/dist/hono/console/routes/stats.d.ts +0 -8
  323. package/dist/hono/console/routes/stats.d.ts.map +0 -1
  324. package/dist/hono/console/routes/stats.js +0 -295
  325. package/dist/hono/console/routes/stats.js.map +0 -1
  326. package/dist/hono/console/routes/storage.d.ts +0 -8
  327. package/dist/hono/console/routes/storage.d.ts.map +0 -1
  328. package/dist/hono/console/routes/storage.js +0 -121
  329. package/dist/hono/console/routes/storage.js.map +0 -1
  330. package/dist/hono/console/routes.d.ts +0 -36
  331. package/dist/hono/console/routes.d.ts.map +0 -1
  332. package/dist/hono/console/routes.js +0 -112
  333. package/dist/hono/console/routes.js.map +0 -1
  334. package/dist/hono/console/schema-errors.d.ts +0 -2
  335. package/dist/hono/console/schema-errors.d.ts.map +0 -1
  336. package/dist/hono/console/schema-errors.js +0 -17
  337. package/dist/hono/console/schema-errors.js.map +0 -1
  338. package/dist/hono/console/schemas.d.ts +0 -1515
  339. package/dist/hono/console/schemas.d.ts.map +0 -1
  340. package/dist/hono/console/schemas.js +0 -661
  341. package/dist/hono/console/schemas.js.map +0 -1
  342. package/dist/hono/console/types.d.ts +0 -213
  343. package/dist/hono/console/types.d.ts.map +0 -1
  344. package/dist/hono/console/types.js +0 -2
  345. package/dist/hono/console/types.js.map +0 -1
  346. package/dist/hono/console/ui.d.ts +0 -38
  347. package/dist/hono/console/ui.d.ts.map +0 -1
  348. package/dist/hono/console/ui.js +0 -43
  349. package/dist/hono/console/ui.js.map +0 -1
  350. package/dist/hono/create-server.d.ts +0 -71
  351. package/dist/hono/create-server.d.ts.map +0 -1
  352. package/dist/hono/create-server.js +0 -121
  353. package/dist/hono/create-server.js.map +0 -1
  354. package/dist/hono/errors.d.ts +0 -13
  355. package/dist/hono/errors.d.ts.map +0 -1
  356. package/dist/hono/errors.js +0 -21
  357. package/dist/hono/errors.js.map +0 -1
  358. package/dist/hono/index.d.ts +0 -20
  359. package/dist/hono/index.d.ts.map +0 -1
  360. package/dist/hono/index.js +0 -31
  361. package/dist/hono/index.js.map +0 -1
  362. package/dist/hono/openapi.d.ts +0 -72
  363. package/dist/hono/openapi.d.ts.map +0 -1
  364. package/dist/hono/openapi.js +0 -99
  365. package/dist/hono/openapi.js.map +0 -1
  366. package/dist/hono/proxy/connection-manager.d.ts +0 -78
  367. package/dist/hono/proxy/connection-manager.d.ts.map +0 -1
  368. package/dist/hono/proxy/connection-manager.js +0 -251
  369. package/dist/hono/proxy/connection-manager.js.map +0 -1
  370. package/dist/hono/proxy/index.d.ts +0 -8
  371. package/dist/hono/proxy/index.d.ts.map +0 -1
  372. package/dist/hono/proxy/index.js +0 -8
  373. package/dist/hono/proxy/index.js.map +0 -1
  374. package/dist/hono/proxy/routes.d.ts +0 -86
  375. package/dist/hono/proxy/routes.d.ts.map +0 -1
  376. package/dist/hono/proxy/routes.js +0 -183
  377. package/dist/hono/proxy/routes.js.map +0 -1
  378. package/dist/hono/rate-limit.d.ts +0 -101
  379. package/dist/hono/rate-limit.d.ts.map +0 -1
  380. package/dist/hono/rate-limit.js +0 -184
  381. package/dist/hono/rate-limit.js.map +0 -1
  382. package/dist/hono/realtime-sync-packs.d.ts +0 -43
  383. package/dist/hono/realtime-sync-packs.d.ts.map +0 -1
  384. package/dist/hono/realtime-sync-packs.js +0 -219
  385. package/dist/hono/realtime-sync-packs.js.map +0 -1
  386. package/dist/hono/routes/audit.d.ts +0 -12
  387. package/dist/hono/routes/audit.d.ts.map +0 -1
  388. package/dist/hono/routes/audit.js +0 -385
  389. package/dist/hono/routes/audit.js.map +0 -1
  390. package/dist/hono/routes/auth-leases.d.ts +0 -8
  391. package/dist/hono/routes/auth-leases.d.ts.map +0 -1
  392. package/dist/hono/routes/auth-leases.js +0 -88
  393. package/dist/hono/routes/auth-leases.js.map +0 -1
  394. package/dist/hono/routes/combined.d.ts +0 -8
  395. package/dist/hono/routes/combined.d.ts.map +0 -1
  396. package/dist/hono/routes/combined.js +0 -392
  397. package/dist/hono/routes/combined.js.map +0 -1
  398. package/dist/hono/routes/context.d.ts +0 -314
  399. package/dist/hono/routes/context.d.ts.map +0 -1
  400. package/dist/hono/routes/context.js +0 -1147
  401. package/dist/hono/routes/context.js.map +0 -1
  402. package/dist/hono/routes/health.d.ts +0 -8
  403. package/dist/hono/routes/health.d.ts.map +0 -1
  404. package/dist/hono/routes/health.js +0 -16
  405. package/dist/hono/routes/health.js.map +0 -1
  406. package/dist/hono/routes/realtime.d.ts +0 -9
  407. package/dist/hono/routes/realtime.d.ts.map +0 -1
  408. package/dist/hono/routes/realtime.js +0 -626
  409. package/dist/hono/routes/realtime.js.map +0 -1
  410. package/dist/hono/routes/shared.d.ts +0 -689
  411. package/dist/hono/routes/shared.d.ts.map +0 -1
  412. package/dist/hono/routes/shared.js +0 -972
  413. package/dist/hono/routes/shared.js.map +0 -1
  414. package/dist/hono/routes/snapshots.d.ts +0 -10
  415. package/dist/hono/routes/snapshots.d.ts.map +0 -1
  416. package/dist/hono/routes/snapshots.js +0 -281
  417. package/dist/hono/routes/snapshots.js.map +0 -1
  418. package/dist/hono/routes.d.ts +0 -19
  419. package/dist/hono/routes.d.ts.map +0 -1
  420. package/dist/hono/routes.js +0 -37
  421. package/dist/hono/routes.js.map +0 -1
  422. package/dist/hono/validation.d.ts +0 -5
  423. package/dist/hono/validation.d.ts.map +0 -1
  424. package/dist/hono/validation.js +0 -47
  425. package/dist/hono/validation.js.map +0 -1
  426. package/dist/hono/websocket-origin.d.ts +0 -9
  427. package/dist/hono/websocket-origin.d.ts.map +0 -1
  428. package/dist/hono/websocket-origin.js +0 -96
  429. package/dist/hono/websocket-origin.js.map +0 -1
  430. package/dist/hono/ws.d.ts +0 -341
  431. package/dist/hono/ws.d.ts.map +0 -1
  432. package/dist/hono/ws.js +0 -711
  433. package/dist/hono/ws.js.map +0 -1
  434. package/dist/index.d.ts.map +0 -1
  435. package/dist/index.js.map +0 -1
  436. package/dist/libsql.d.ts +0 -29
  437. package/dist/libsql.d.ts.map +0 -1
  438. package/dist/libsql.js +0 -25
  439. package/dist/libsql.js.map +0 -1
  440. package/dist/migrate.d.ts +0 -14
  441. package/dist/migrate.d.ts.map +0 -1
  442. package/dist/migrate.js +0 -13
  443. package/dist/migrate.js.map +0 -1
  444. package/dist/neon.d.ts +0 -21
  445. package/dist/neon.d.ts.map +0 -1
  446. package/dist/neon.js +0 -22
  447. package/dist/neon.js.map +0 -1
  448. package/dist/notify.d.ts +0 -77
  449. package/dist/notify.d.ts.map +0 -1
  450. package/dist/notify.js +0 -233
  451. package/dist/notify.js.map +0 -1
  452. package/dist/pglite.d.ts +0 -37
  453. package/dist/pglite.d.ts.map +0 -1
  454. package/dist/pglite.js +0 -37
  455. package/dist/pglite.js.map +0 -1
  456. package/dist/plugins/index.d.ts +0 -2
  457. package/dist/plugins/index.d.ts.map +0 -1
  458. package/dist/plugins/index.js +0 -2
  459. package/dist/plugins/index.js.map +0 -1
  460. package/dist/plugins/types.d.ts +0 -73
  461. package/dist/plugins/types.d.ts.map +0 -1
  462. package/dist/plugins/types.js +0 -30
  463. package/dist/plugins/types.js.map +0 -1
  464. package/dist/postgres/index.d.ts +0 -68
  465. package/dist/postgres/index.d.ts.map +0 -1
  466. package/dist/postgres/index.js +0 -924
  467. package/dist/postgres/index.js.map +0 -1
  468. package/dist/proxy/collection.d.ts +0 -7
  469. package/dist/proxy/collection.d.ts.map +0 -1
  470. package/dist/proxy/collection.js +0 -6
  471. package/dist/proxy/collection.js.map +0 -1
  472. package/dist/proxy/handler.d.ts +0 -42
  473. package/dist/proxy/handler.d.ts.map +0 -1
  474. package/dist/proxy/handler.js +0 -102
  475. package/dist/proxy/handler.js.map +0 -1
  476. package/dist/proxy/index.d.ts +0 -9
  477. package/dist/proxy/index.d.ts.map +0 -1
  478. package/dist/proxy/index.js +0 -14
  479. package/dist/proxy/index.js.map +0 -1
  480. package/dist/proxy/mutation-detector.d.ts +0 -35
  481. package/dist/proxy/mutation-detector.d.ts.map +0 -1
  482. package/dist/proxy/mutation-detector.js +0 -246
  483. package/dist/proxy/mutation-detector.js.map +0 -1
  484. package/dist/proxy/oplog.d.ts +0 -30
  485. package/dist/proxy/oplog.d.ts.map +0 -1
  486. package/dist/proxy/oplog.js +0 -137
  487. package/dist/proxy/oplog.js.map +0 -1
  488. package/dist/proxy/types.d.ts +0 -44
  489. package/dist/proxy/types.d.ts.map +0 -1
  490. package/dist/proxy/types.js +0 -7
  491. package/dist/proxy/types.js.map +0 -1
  492. package/dist/prune.d.ts.map +0 -1
  493. package/dist/prune.js.map +0 -1
  494. package/dist/pull.d.ts.map +0 -1
  495. package/dist/pull.js.map +0 -1
  496. package/dist/push.d.ts.map +0 -1
  497. package/dist/push.js.map +0 -1
  498. package/dist/realtime/in-memory.d.ts +0 -13
  499. package/dist/realtime/in-memory.d.ts.map +0 -1
  500. package/dist/realtime/in-memory.js +0 -28
  501. package/dist/realtime/in-memory.js.map +0 -1
  502. package/dist/realtime/index.d.ts +0 -4
  503. package/dist/realtime/index.d.ts.map +0 -1
  504. package/dist/realtime/index.js +0 -3
  505. package/dist/realtime/index.js.map +0 -1
  506. package/dist/realtime/types.d.ts +0 -62
  507. package/dist/realtime/types.d.ts.map +0 -1
  508. package/dist/realtime/types.js +0 -19
  509. package/dist/realtime/types.js.map +0 -1
  510. package/dist/relay/client-role/forward-engine.d.ts +0 -63
  511. package/dist/relay/client-role/forward-engine.d.ts.map +0 -1
  512. package/dist/relay/client-role/forward-engine.js +0 -267
  513. package/dist/relay/client-role/forward-engine.js.map +0 -1
  514. package/dist/relay/client-role/index.d.ts +0 -9
  515. package/dist/relay/client-role/index.d.ts.map +0 -1
  516. package/dist/relay/client-role/index.js +0 -9
  517. package/dist/relay/client-role/index.js.map +0 -1
  518. package/dist/relay/client-role/pull-engine.d.ts +0 -72
  519. package/dist/relay/client-role/pull-engine.d.ts.map +0 -1
  520. package/dist/relay/client-role/pull-engine.js +0 -249
  521. package/dist/relay/client-role/pull-engine.js.map +0 -1
  522. package/dist/relay/client-role/sequence-mapper.d.ts +0 -65
  523. package/dist/relay/client-role/sequence-mapper.d.ts.map +0 -1
  524. package/dist/relay/client-role/sequence-mapper.js +0 -161
  525. package/dist/relay/client-role/sequence-mapper.js.map +0 -1
  526. package/dist/relay/evaluation/relay-paths.d.ts +0 -41
  527. package/dist/relay/evaluation/relay-paths.d.ts.map +0 -1
  528. package/dist/relay/evaluation/relay-paths.js +0 -504
  529. package/dist/relay/evaluation/relay-paths.js.map +0 -1
  530. package/dist/relay/evaluation/rust-boundary.d.ts +0 -47
  531. package/dist/relay/evaluation/rust-boundary.d.ts.map +0 -1
  532. package/dist/relay/evaluation/rust-boundary.js +0 -220
  533. package/dist/relay/evaluation/rust-boundary.js.map +0 -1
  534. package/dist/relay/index.d.ts +0 -37
  535. package/dist/relay/index.d.ts.map +0 -1
  536. package/dist/relay/index.js +0 -44
  537. package/dist/relay/index.js.map +0 -1
  538. package/dist/relay/migrate.d.ts +0 -18
  539. package/dist/relay/migrate.d.ts.map +0 -1
  540. package/dist/relay/migrate.js +0 -99
  541. package/dist/relay/migrate.js.map +0 -1
  542. package/dist/relay/mode-manager.d.ts +0 -60
  543. package/dist/relay/mode-manager.d.ts.map +0 -1
  544. package/dist/relay/mode-manager.js +0 -114
  545. package/dist/relay/mode-manager.js.map +0 -1
  546. package/dist/relay/realtime.d.ts +0 -90
  547. package/dist/relay/realtime.d.ts.map +0 -1
  548. package/dist/relay/realtime.js +0 -147
  549. package/dist/relay/realtime.js.map +0 -1
  550. package/dist/relay/relay.d.ts +0 -190
  551. package/dist/relay/relay.d.ts.map +0 -1
  552. package/dist/relay/relay.js +0 -320
  553. package/dist/relay/relay.js.map +0 -1
  554. package/dist/relay/schema.d.ts +0 -158
  555. package/dist/relay/schema.d.ts.map +0 -1
  556. package/dist/relay/schema.js +0 -7
  557. package/dist/relay/schema.js.map +0 -1
  558. package/dist/relay/server-role/index.d.ts +0 -56
  559. package/dist/relay/server-role/index.d.ts.map +0 -1
  560. package/dist/relay/server-role/index.js +0 -193
  561. package/dist/relay/server-role/index.js.map +0 -1
  562. package/dist/relay/server-role/pull.d.ts +0 -27
  563. package/dist/relay/server-role/pull.d.ts.map +0 -1
  564. package/dist/relay/server-role/pull.js +0 -24
  565. package/dist/relay/server-role/pull.js.map +0 -1
  566. package/dist/relay/server-role/push.d.ts +0 -29
  567. package/dist/relay/server-role/push.d.ts.map +0 -1
  568. package/dist/relay/server-role/push.js +0 -122
  569. package/dist/relay/server-role/push.js.map +0 -1
  570. package/dist/s3/index.d.ts +0 -83
  571. package/dist/s3/index.d.ts.map +0 -1
  572. package/dist/s3/index.js +0 -223
  573. package/dist/s3/index.js.map +0 -1
  574. package/dist/schema.d.ts.map +0 -1
  575. package/dist/schema.js.map +0 -1
  576. package/dist/service-worker/index.d.ts +0 -114
  577. package/dist/service-worker/index.d.ts.map +0 -1
  578. package/dist/service-worker/index.js +0 -487
  579. package/dist/service-worker/index.js.map +0 -1
  580. package/dist/snapshot-artifacts/sqlite-bun.d.ts +0 -15
  581. package/dist/snapshot-artifacts/sqlite-bun.d.ts.map +0 -1
  582. package/dist/snapshot-artifacts/sqlite-bun.js +0 -128
  583. package/dist/snapshot-artifacts/sqlite-bun.js.map +0 -1
  584. package/dist/snapshot-artifacts.d.ts +0 -206
  585. package/dist/snapshot-artifacts.d.ts.map +0 -1
  586. package/dist/snapshot-artifacts.js +0 -545
  587. package/dist/snapshot-artifacts.js.map +0 -1
  588. package/dist/snapshot-chunks/db-metadata.d.ts +0 -56
  589. package/dist/snapshot-chunks/db-metadata.d.ts.map +0 -1
  590. package/dist/snapshot-chunks/db-metadata.js +0 -360
  591. package/dist/snapshot-chunks/db-metadata.js.map +0 -1
  592. package/dist/snapshot-chunks/index.d.ts +0 -8
  593. package/dist/snapshot-chunks/index.d.ts.map +0 -1
  594. package/dist/snapshot-chunks/index.js +0 -8
  595. package/dist/snapshot-chunks/index.js.map +0 -1
  596. package/dist/snapshot-chunks/types.d.ts +0 -80
  597. package/dist/snapshot-chunks/types.d.ts.map +0 -1
  598. package/dist/snapshot-chunks/types.js +0 -8
  599. package/dist/snapshot-chunks/types.js.map +0 -1
  600. package/dist/snapshot-chunks.d.ts +0 -90
  601. package/dist/snapshot-chunks.d.ts.map +0 -1
  602. package/dist/snapshot-chunks.js +0 -304
  603. package/dist/snapshot-chunks.js.map +0 -1
  604. package/dist/sqlite/index.d.ts +0 -53
  605. package/dist/sqlite/index.d.ts.map +0 -1
  606. package/dist/sqlite/index.js +0 -795
  607. package/dist/sqlite/index.js.map +0 -1
  608. package/dist/sqlite3.d.ts +0 -22
  609. package/dist/sqlite3.d.ts.map +0 -1
  610. package/dist/sqlite3.js +0 -99
  611. package/dist/sqlite3.js.map +0 -1
  612. package/dist/stats.d.ts +0 -28
  613. package/dist/stats.d.ts.map +0 -1
  614. package/dist/stats.js +0 -93
  615. package/dist/stats.js.map +0 -1
  616. package/dist/subscriptions/cache.d.ts +0 -58
  617. package/dist/subscriptions/cache.d.ts.map +0 -1
  618. package/dist/subscriptions/cache.js +0 -250
  619. package/dist/subscriptions/cache.js.map +0 -1
  620. package/dist/subscriptions/index.d.ts +0 -3
  621. package/dist/subscriptions/index.d.ts.map +0 -1
  622. package/dist/subscriptions/index.js +0 -3
  623. package/dist/subscriptions/index.js.map +0 -1
  624. package/dist/subscriptions/resolve.d.ts +0 -40
  625. package/dist/subscriptions/resolve.d.ts.map +0 -1
  626. package/dist/subscriptions/resolve.js +0 -275
  627. package/dist/subscriptions/resolve.js.map +0 -1
  628. package/dist/sync.d.ts +0 -24
  629. package/dist/sync.d.ts.map +0 -1
  630. package/dist/sync.js +0 -27
  631. package/dist/sync.js.map +0 -1
  632. package/src/auth-leases.ts +0 -649
  633. package/src/better-sqlite3.ts +0 -35
  634. package/src/blobs/access.ts +0 -244
  635. package/src/blobs/adapters/database.ts +0 -397
  636. package/src/blobs/index.ts +0 -9
  637. package/src/blobs/manager.ts +0 -901
  638. package/src/blobs/migrate.ts +0 -158
  639. package/src/blobs/types.ts +0 -74
  640. package/src/bun-sqlite-ambient.d.ts +0 -19
  641. package/src/bun-sqlite.ts +0 -27
  642. package/src/clients.ts +0 -22
  643. package/src/cloudflare/durable-object.ts +0 -289
  644. package/src/cloudflare/index.ts +0 -22
  645. package/src/cloudflare/r2.ts +0 -526
  646. package/src/cloudflare/scope-cache.ts +0 -341
  647. package/src/cloudflare/sentry.ts +0 -230
  648. package/src/cloudflare/worker.ts +0 -77
  649. package/src/commit-integrity.ts +0 -371
  650. package/src/compaction.ts +0 -77
  651. package/src/crdt-yjs/index.ts +0 -931
  652. package/src/d1.ts +0 -16
  653. package/src/dialect/base.ts +0 -360
  654. package/src/dialect/helpers.ts +0 -92
  655. package/src/dialect/index.ts +0 -7
  656. package/src/dialect/types.ts +0 -247
  657. package/src/encrypted-crdt.ts +0 -786
  658. package/src/filesystem/index.ts +0 -262
  659. package/src/handlers/collection.ts +0 -121
  660. package/src/handlers/create-handler.ts +0 -1134
  661. package/src/handlers/index.ts +0 -3
  662. package/src/handlers/types.ts +0 -403
  663. package/src/helpers/conflict.ts +0 -64
  664. package/src/helpers/emitted-change.ts +0 -69
  665. package/src/helpers/index.ts +0 -12
  666. package/src/helpers/paginate.ts +0 -82
  667. package/src/helpers/scope-authorization.ts +0 -27
  668. package/src/helpers/scope-commit-index.ts +0 -52
  669. package/src/helpers/scope-strings.ts +0 -101
  670. package/src/hono/api-key-auth.ts +0 -177
  671. package/src/hono/audit-redaction.ts +0 -135
  672. package/src/hono/blobs.ts +0 -851
  673. package/src/hono/console/gateway.ts +0 -3046
  674. package/src/hono/console/live-auth.ts +0 -46
  675. package/src/hono/console/route-descriptor.ts +0 -22
  676. package/src/hono/console/routes/api-keys.ts +0 -721
  677. package/src/hono/console/routes/clients.ts +0 -447
  678. package/src/hono/console/routes/commits.ts +0 -1137
  679. package/src/hono/console/routes/context.ts +0 -956
  680. package/src/hono/console/routes/events.ts +0 -669
  681. package/src/hono/console/routes/maintenance.ts +0 -461
  682. package/src/hono/console/routes/shared.ts +0 -816
  683. package/src/hono/console/routes/stats.ts +0 -392
  684. package/src/hono/console/routes/storage.ts +0 -159
  685. package/src/hono/console/routes.ts +0 -146
  686. package/src/hono/console/schema-errors.ts +0 -23
  687. package/src/hono/console/schemas.ts +0 -914
  688. package/src/hono/console/types.ts +0 -223
  689. package/src/hono/console/ui.ts +0 -100
  690. package/src/hono/create-server.ts +0 -230
  691. package/src/hono/errors.ts +0 -50
  692. package/src/hono/index.ts +0 -54
  693. package/src/hono/openapi.ts +0 -139
  694. package/src/hono/proxy/connection-manager.ts +0 -340
  695. package/src/hono/proxy/index.ts +0 -8
  696. package/src/hono/proxy/routes.ts +0 -272
  697. package/src/hono/rate-limit.ts +0 -319
  698. package/src/hono/realtime-sync-packs.ts +0 -354
  699. package/src/hono/routes/audit.ts +0 -499
  700. package/src/hono/routes/auth-leases.ts +0 -119
  701. package/src/hono/routes/combined.ts +0 -583
  702. package/src/hono/routes/context.ts +0 -1629
  703. package/src/hono/routes/health.ts +0 -26
  704. package/src/hono/routes/realtime.ts +0 -808
  705. package/src/hono/routes/shared.ts +0 -1626
  706. package/src/hono/routes/snapshots.ts +0 -345
  707. package/src/hono/routes.ts +0 -68
  708. package/src/hono/validation.ts +0 -81
  709. package/src/hono/websocket-origin.ts +0 -131
  710. package/src/hono/ws.ts +0 -1134
  711. package/src/libsql.ts +0 -51
  712. package/src/migrate.ts +0 -20
  713. package/src/neon.ts +0 -28
  714. package/src/notify.ts +0 -341
  715. package/src/pglite.ts +0 -68
  716. package/src/plugins/index.ts +0 -1
  717. package/src/plugins/types.ts +0 -144
  718. package/src/postgres/index.ts +0 -1291
  719. package/src/proxy/collection.ts +0 -17
  720. package/src/proxy/handler.ts +0 -159
  721. package/src/proxy/index.ts +0 -21
  722. package/src/proxy/mutation-detector.ts +0 -281
  723. package/src/proxy/oplog.ts +0 -181
  724. package/src/proxy/types.ts +0 -46
  725. package/src/realtime/in-memory.ts +0 -33
  726. package/src/realtime/index.ts +0 -7
  727. package/src/realtime/types.ts +0 -90
  728. package/src/relay/bun-types.d.ts +0 -50
  729. package/src/relay/client-role/forward-engine.ts +0 -355
  730. package/src/relay/client-role/index.ts +0 -9
  731. package/src/relay/client-role/pull-engine.ts +0 -329
  732. package/src/relay/client-role/sequence-mapper.ts +0 -201
  733. package/src/relay/evaluation/relay-paths.ts +0 -699
  734. package/src/relay/evaluation/rust-boundary.ts +0 -464
  735. package/src/relay/index.ts +0 -50
  736. package/src/relay/migrate.ts +0 -113
  737. package/src/relay/mode-manager.ts +0 -142
  738. package/src/relay/realtime.ts +0 -207
  739. package/src/relay/relay.ts +0 -431
  740. package/src/relay/schema.ts +0 -171
  741. package/src/relay/server-role/index.ts +0 -338
  742. package/src/relay/server-role/pull.ts +0 -43
  743. package/src/relay/server-role/push.ts +0 -164
  744. package/src/s3/index.ts +0 -346
  745. package/src/service-worker/index.ts +0 -773
  746. package/src/snapshot-artifacts/sqlite-bun.ts +0 -168
  747. package/src/snapshot-artifacts.ts +0 -896
  748. package/src/snapshot-chunks/db-metadata.ts +0 -537
  749. package/src/snapshot-chunks/index.ts +0 -8
  750. package/src/snapshot-chunks/types.ts +0 -105
  751. package/src/snapshot-chunks.ts +0 -453
  752. package/src/sqlite/index.ts +0 -1064
  753. package/src/sqlite3.ts +0 -137
  754. package/src/stats.ts +0 -180
  755. package/src/subscriptions/cache.ts +0 -376
  756. package/src/subscriptions/index.ts +0 -2
  757. package/src/subscriptions/resolve.ts +0 -357
  758. package/src/sync.ts +0 -111
@@ -0,0 +1,633 @@
1
+ /**
2
+ * Relational current-row storage (DESIGN-relational-server-storage.md).
3
+ *
4
+ * Every synced table is a REAL table in the server database — the app's
5
+ * columns with proper type affinities, queryable with plain SQL/joins/BI —
6
+ * plus five `_sync_*` meta columns:
7
+ *
8
+ * _sync_partition TEXT partition key (multi-partition servers
9
+ * share one database; same app PK in two
10
+ * partitions must coexist)
11
+ * _sync_row_id TEXT the change rowId (§2.2) — the string
12
+ * rendering of the app PK. The storage key
13
+ * stays TEXT so lookup and scan-pagination
14
+ * semantics are byte-identical to the old
15
+ * generic store regardless of the PK's type.
16
+ * _sync_server_version INTEGER §2.2 server version
17
+ * _sync_scopes TEXT/JSONB the stored-scope map the §3.4 authz read
18
+ * consumes (also present as real columns;
19
+ * the map is cheaper to read back)
20
+ * _sync_payload BLOB/BYTEA the verbatim row-codec bytes — the wire
21
+ * source of truth. The serve path reads
22
+ * THIS, never re-encodes from typed columns,
23
+ * so sync round-trips are byte-identical by
24
+ * construction. Typed columns are a
25
+ * queryable projection.
26
+ *
27
+ * PRIMARY KEY (_sync_partition, _sync_row_id).
28
+ *
29
+ * The typed columns are written from `decodeRow(payload)` in the same
30
+ * statement as the payload, so projection and payload cannot drift except
31
+ * through a codec bug — which the round-trip contract tests would catch.
32
+ *
33
+ * Dialect notes:
34
+ * - postgres maps `json` → JSONB (queryable: `->>`, GIN). JSONB normalizes
35
+ * bytes, which is safe because the wire never reads typed columns.
36
+ * A json value that fails to parse binds NULL on postgres (the payload
37
+ * still holds it verbatim); sqlite stores the text as-is.
38
+ * - D1's JSON transport represents integers as JS doubles; app integer
39
+ * columns beyond 2^53 lose precision in the PROJECTION only — the
40
+ * payload is exact, sync is unaffected.
41
+ * - Migration-added columns (ALTER TABLE ADD COLUMN) are always nullable at
42
+ * the DB layer: SQLite cannot add a NOT NULL column without a default, and
43
+ * the row codec — not the DB — is the type authority. Fresh CREATEs carry
44
+ * NOT NULL per the schema.
45
+ */
46
+ import {
47
+ decodeRow,
48
+ encodeRow,
49
+ type RowColumn,
50
+ type RowValue,
51
+ } from '@syncular/core';
52
+ import type { CompiledSchema, CompiledTable } from './schema';
53
+ import type { StoredRow } from './storage';
54
+
55
+ export type RelationalDialect = 'sqlite' | 'postgres';
56
+
57
+ export const SYNC_PARTITION_COLUMN = '_sync_partition';
58
+ export const SYNC_ROW_ID_COLUMN = '_sync_row_id';
59
+ export const SYNC_VERSION_COLUMN = '_sync_server_version';
60
+ export const SYNC_SCOPES_COLUMN = '_sync_scopes';
61
+ export const SYNC_PAYLOAD_COLUMN = '_sync_payload';
62
+
63
+ /** SQL-standard identifier quoting (both dialects). */
64
+ export function quoteIdent(name: string): string {
65
+ return `"${name.replaceAll('"', '""')}"`;
66
+ }
67
+
68
+ /** §5.3-style type affinities, per dialect (DESIGN type-mapping table). */
69
+ export function columnSqlType(
70
+ column: RowColumn,
71
+ dialect: RelationalDialect,
72
+ ): string {
73
+ if (dialect === 'postgres') {
74
+ switch (column.type) {
75
+ case 'string':
76
+ case 'blob_ref':
77
+ return 'TEXT';
78
+ case 'json':
79
+ return 'JSONB';
80
+ case 'integer':
81
+ return 'BIGINT';
82
+ case 'float':
83
+ return 'DOUBLE PRECISION';
84
+ case 'boolean':
85
+ return 'BOOLEAN';
86
+ case 'bytes':
87
+ case 'crdt':
88
+ return 'BYTEA';
89
+ default:
90
+ throw new Error(`unsupported column type: ${String(column.type)}`);
91
+ }
92
+ }
93
+ switch (column.type) {
94
+ case 'string':
95
+ case 'json':
96
+ case 'blob_ref':
97
+ return 'TEXT';
98
+ case 'integer':
99
+ return 'INTEGER';
100
+ case 'float':
101
+ return 'REAL';
102
+ case 'boolean':
103
+ return 'INTEGER';
104
+ case 'bytes':
105
+ case 'crdt':
106
+ return 'BLOB';
107
+ default:
108
+ throw new Error(`unsupported column type: ${String(column.type)}`);
109
+ }
110
+ }
111
+
112
+ /**
113
+ * The full column list of a relational row table, in INSERT order:
114
+ * partition, row id, app columns (schema order; only when the table is
115
+ * materialized), version, scopes, payload.
116
+ */
117
+ export function tableColumnNames(table: CompiledTable): string[] {
118
+ return [
119
+ SYNC_PARTITION_COLUMN,
120
+ SYNC_ROW_ID_COLUMN,
121
+ ...(table.materialize ? table.columns.map((column) => column.name) : []),
122
+ SYNC_VERSION_COLUMN,
123
+ SYNC_SCOPES_COLUMN,
124
+ SYNC_PAYLOAD_COLUMN,
125
+ ];
126
+ }
127
+
128
+ /** CREATE TABLE IF NOT EXISTS for one app table. */
129
+ export function createTableDdl(
130
+ table: CompiledTable,
131
+ dialect: RelationalDialect,
132
+ ): string {
133
+ const versionType = dialect === 'postgres' ? 'BIGINT' : 'INTEGER';
134
+ const scopesType = dialect === 'postgres' ? 'JSONB' : 'TEXT';
135
+ const payloadType = dialect === 'postgres' ? 'BYTEA' : 'BLOB';
136
+ const defs = [
137
+ `${quoteIdent(SYNC_PARTITION_COLUMN)} TEXT NOT NULL`,
138
+ `${quoteIdent(SYNC_ROW_ID_COLUMN)} TEXT NOT NULL`,
139
+ ...(table.materialize
140
+ ? table.columns.map((column) => {
141
+ const notNull = column.nullable ? '' : ' NOT NULL';
142
+ return `${quoteIdent(column.name)} ${columnSqlType(column, dialect)}${notNull}`;
143
+ })
144
+ : []),
145
+ `${quoteIdent(SYNC_VERSION_COLUMN)} ${versionType} NOT NULL`,
146
+ `${quoteIdent(SYNC_SCOPES_COLUMN)} ${scopesType} NOT NULL`,
147
+ `${quoteIdent(SYNC_PAYLOAD_COLUMN)} ${payloadType} NOT NULL`,
148
+ `PRIMARY KEY (${quoteIdent(SYNC_PARTITION_COLUMN)}, ${quoteIdent(SYNC_ROW_ID_COLUMN)})`,
149
+ ];
150
+ return `CREATE TABLE IF NOT EXISTS ${quoteIdent(table.name)} (${defs.join(', ')})`;
151
+ }
152
+
153
+ /**
154
+ * ALTER TABLE ADD COLUMN statements for schema columns missing from
155
+ * `existingColumns` (introspected). Added columns are nullable (header note).
156
+ */
157
+ export function addColumnDdl(
158
+ table: CompiledTable,
159
+ existingColumns: ReadonlySet<string>,
160
+ dialect: RelationalDialect,
161
+ ): string[] {
162
+ if (!table.materialize) return [];
163
+ const out: string[] = [];
164
+ for (const column of table.columns) {
165
+ if (existingColumns.has(column.name)) continue;
166
+ out.push(
167
+ `ALTER TABLE ${quoteIdent(table.name)} ADD COLUMN ${quoteIdent(column.name)} ${columnSqlType(column, dialect)}`,
168
+ );
169
+ }
170
+ return out;
171
+ }
172
+
173
+ /**
174
+ * CREATE INDEX IF NOT EXISTS for the table's user-declared indexes
175
+ * (DESIGN "user indexes" — the same names/columns the client materializes;
176
+ * cross-table index-name uniqueness is the user's schema concern, exactly
177
+ * as it is client-side).
178
+ */
179
+ export function createIndexDdl(table: CompiledTable): string[] {
180
+ // User indexes name app columns — nothing to index without the projection.
181
+ if (!table.materialize) return [];
182
+ return table.indexes.map((index) => {
183
+ const unique = index.unique ? 'UNIQUE ' : '';
184
+ const columns = index.columns
185
+ .map((column) => quoteIdent(column))
186
+ .join(', ');
187
+ return `CREATE ${unique}INDEX IF NOT EXISTS ${quoteIdent(index.name)} ON ${quoteIdent(table.name)} (${columns})`;
188
+ });
189
+ }
190
+
191
+ /**
192
+ * Convert one decoded row value to its SQL bind value.
193
+ * - boolean → 0/1 on sqlite (INTEGER affinity), native on postgres;
194
+ * - json → the raw string on sqlite; on postgres, NULL if unparseable
195
+ * (JSONB would reject the INSERT — the payload keeps the verbatim value);
196
+ * - everything else binds naturally (Uint8Array → BLOB/BYTEA).
197
+ */
198
+ export function toSqlValue(
199
+ column: RowColumn,
200
+ value: RowValue,
201
+ dialect: RelationalDialect,
202
+ ): unknown {
203
+ if (value === null) return null;
204
+ if (column.type === 'boolean' && dialect === 'sqlite') {
205
+ return value === true ? 1 : 0;
206
+ }
207
+ if (column.type === 'json' && dialect === 'postgres') {
208
+ if (typeof value !== 'string') return null;
209
+ try {
210
+ JSON.parse(value);
211
+ return value;
212
+ } catch {
213
+ return null;
214
+ }
215
+ }
216
+ return value;
217
+ }
218
+
219
+ /**
220
+ * Bind values for an upsert, in `tableColumnNames` order. Decodes the
221
+ * payload once; the typed columns and the verbatim payload land in one
222
+ * statement, so they cannot drift.
223
+ */
224
+ export function upsertValues(
225
+ table: CompiledTable,
226
+ partition: string,
227
+ row: StoredRow,
228
+ dialect: RelationalDialect,
229
+ ): unknown[] {
230
+ // A non-materialized table skips the decode entirely — the upsert is a
231
+ // five-column meta write (the old blob-store cost).
232
+ const projection = table.materialize
233
+ ? decodeRow(table.columns, row.payload)
234
+ : undefined;
235
+ return [
236
+ partition,
237
+ row.rowId,
238
+ ...(projection !== undefined
239
+ ? table.columns.map((column, index) =>
240
+ toSqlValue(column, projection[index] ?? null, dialect),
241
+ )
242
+ : []),
243
+ row.serverVersion,
244
+ JSON.stringify(row.scopes),
245
+ row.payload,
246
+ ];
247
+ }
248
+
249
+ function placeholderList(count: number, dialect: RelationalDialect): string {
250
+ if (dialect === 'sqlite') return new Array(count).fill('?').join(',');
251
+ const out: string[] = [];
252
+ for (let i = 1; i <= count; i++) out.push(`$${i}`);
253
+ return out.join(',');
254
+ }
255
+
256
+ /** Upsert statement text (bind with `upsertValues`). */
257
+ export function upsertSql(
258
+ table: CompiledTable,
259
+ dialect: RelationalDialect,
260
+ ): string {
261
+ const names = tableColumnNames(table);
262
+ const quoted = names.map((name) => quoteIdent(name)).join(', ');
263
+ const values = placeholderList(names.length, dialect);
264
+ if (dialect === 'sqlite') {
265
+ // INSERT OR REPLACE keys on the (_sync_partition, _sync_row_id) PK.
266
+ return `INSERT OR REPLACE INTO ${quoteIdent(table.name)} (${quoted}) VALUES (${values})`;
267
+ }
268
+ const updates = names
269
+ .slice(2) // partition + row id are the conflict key
270
+ .map((name) => `${quoteIdent(name)}=EXCLUDED.${quoteIdent(name)}`)
271
+ .join(', ');
272
+ return `INSERT INTO ${quoteIdent(table.name)} (${quoted}) VALUES (${values})
273
+ ON CONFLICT (${quoteIdent(SYNC_PARTITION_COLUMN)}, ${quoteIdent(SYNC_ROW_ID_COLUMN)}) DO UPDATE SET ${updates}`;
274
+ }
275
+
276
+ /**
277
+ * SELECT one stored row. Aliased to the legacy record shape
278
+ * (`row_id`/`server_version`/`scopes`/`payload`) so the existing
279
+ * `toStoredRow` converters keep working. Params: [partition, rowId].
280
+ */
281
+ export function selectRowSql(
282
+ table: CompiledTable,
283
+ dialect: RelationalDialect,
284
+ ): string {
285
+ const p = dialect === 'sqlite' ? ['?', '?'] : ['$1', '$2'];
286
+ return `SELECT ${quoteIdent(SYNC_ROW_ID_COLUMN)} AS row_id, ${quoteIdent(SYNC_VERSION_COLUMN)} AS server_version, ${quoteIdent(SYNC_SCOPES_COLUMN)} AS scopes, ${quoteIdent(SYNC_PAYLOAD_COLUMN)} AS payload FROM ${quoteIdent(table.name)} WHERE ${quoteIdent(SYNC_PARTITION_COLUMN)}=${p[0]} AND ${quoteIdent(SYNC_ROW_ID_COLUMN)}=${p[1]}`;
287
+ }
288
+
289
+ /**
290
+ * One-round-trip page scan for `scanRows`: candidates from the inverted
291
+ * scope index (ordered + LIMITed at the covering `sync_row_scopes` PK —
292
+ * exactly the old candidate query, so the index-first posture is unchanged)
293
+ * LEFT JOINed to the row table, so a whole page arrives in ONE statement
294
+ * instead of one lookup per candidate. That per-candidate lookup was the
295
+ * cold-bootstrap hot path: a 100k-row snapshot on Postgres paid ~100k
296
+ * network round-trips (~10 s at 0.1 ms each) before this join.
297
+ *
298
+ * LEFT JOIN (not INNER): a candidate whose row vanished (index entry
299
+ * without a row) must still reach the caller — its `row_id` advances the
300
+ * keyset cursor — so it comes back with NULL payload rather than
301
+ * disappearing from the page.
302
+ *
303
+ * Bind order:
304
+ * - postgres: [partition, tbl, var, ...values, afterRowId, limit]
305
+ * (the join reuses `$1` for the partition);
306
+ * - sqlite: [partition, tbl, var, ...values, afterRowId, limit,
307
+ * partition] (positional `?` — the partition binds again for the join).
308
+ */
309
+ export function scanRowPageSql(
310
+ table: CompiledTable,
311
+ valueCount: number,
312
+ dialect: RelationalDialect,
313
+ ): string {
314
+ const p = (n: number) => (dialect === 'sqlite' ? '?' : `$${n}`);
315
+ const values: string[] = [];
316
+ for (let i = 0; i < valueCount; i++) values.push(p(4 + i));
317
+ const after = p(4 + valueCount);
318
+ const limit = p(5 + valueCount);
319
+ const joinPartition = dialect === 'sqlite' ? '?' : '$1';
320
+ return `SELECT c.row_id AS row_id, r.${quoteIdent(SYNC_VERSION_COLUMN)} AS server_version, r.${quoteIdent(SYNC_SCOPES_COLUMN)} AS scopes, r.${quoteIdent(SYNC_PAYLOAD_COLUMN)} AS payload
321
+ FROM (SELECT DISTINCT row_id FROM sync_row_scopes
322
+ WHERE partition=${p(1)} AND tbl=${p(2)} AND var=${p(3)} AND value IN (${values.join(',')})
323
+ AND row_id>${after}
324
+ ORDER BY row_id LIMIT ${limit}) c
325
+ LEFT JOIN ${quoteIdent(table.name)} r
326
+ ON r.${quoteIdent(SYNC_PARTITION_COLUMN)}=${joinPartition} AND r.${quoteIdent(SYNC_ROW_ID_COLUMN)}=c.row_id
327
+ ORDER BY c.row_id`;
328
+ }
329
+
330
+ /**
331
+ * One-round-trip page read for `readCommitWindow` (sync_* tables only; it
332
+ * lives here beside `scanRowPageSql` because it is the same join-the-index
333
+ * posture, dialect-parameterized the same way): candidates from the inverted
334
+ * change-scope index (ordered + LIMITed at the covering `sync_change_scopes`
335
+ * PK — exactly the old candidate query, so the index-first invariant of
336
+ * `CommitWindowQuery` is unchanged) LEFT JOINed to the commit metadata and
337
+ * to the commit's changes for the table, so a whole window page arrives in
338
+ * ONE statement instead of 1 + 2×candidates round trips. This is the
339
+ * incremental-pull hot path — it runs on every sync round; before the join a
340
+ * 500-candidate catch-up window on Postgres paid ~1000 network round trips.
341
+ *
342
+ * LEFT JOIN (not INNER): a candidate whose commit vanished (scope-index
343
+ * entry without a commit/changes row) must still reach the caller — its
344
+ * `commit_seq` advances the window cursor — so it comes back with NULL
345
+ * meta/change columns rather than disappearing from the page.
346
+ *
347
+ * Rows arrive ordered (commit_seq, idx): oldest-first commits, each commit's
348
+ * change rows consecutive in `idx` order — the caller groups consecutive
349
+ * rows and verifies the full multi-variable scope match in JS.
350
+ *
351
+ * Bind order:
352
+ * - postgres: [partition, tbl, var, ...values, afterSeq, throughSeq,
353
+ * limit] (the joins reuse `$1`/`$2`);
354
+ * - sqlite: [partition, tbl, var, ...values, afterSeq, throughSeq,
355
+ * limit, partition, partition, tbl] (positional `?` — partition/tbl bind
356
+ * again for the joins).
357
+ */
358
+ export function commitWindowPageSql(
359
+ valueCount: number,
360
+ dialect: RelationalDialect,
361
+ ): string {
362
+ const p = (n: number) => (dialect === 'sqlite' ? '?' : `$${n}`);
363
+ const values: string[] = [];
364
+ for (let i = 0; i < valueCount; i++) values.push(p(4 + i));
365
+ const after = p(4 + valueCount);
366
+ const through = p(5 + valueCount);
367
+ const limit = p(6 + valueCount);
368
+ const joinPartition = dialect === 'sqlite' ? '?' : '$1';
369
+ const joinTbl = dialect === 'sqlite' ? '?' : '$2';
370
+ return `SELECT c.commit_seq AS commit_seq, m.actor_id AS actor_id, m.created_at_ms AS created_at_ms,
371
+ ch.tbl AS tbl, ch.row_id AS row_id, ch.op AS op, ch.row_version AS row_version, ch.scopes AS scopes, ch.payload AS payload
372
+ FROM (SELECT DISTINCT commit_seq FROM sync_change_scopes
373
+ WHERE partition=${p(1)} AND tbl=${p(2)} AND var=${p(3)} AND value IN (${values.join(',')})
374
+ AND commit_seq>${after} AND commit_seq<=${through}
375
+ ORDER BY commit_seq LIMIT ${limit}) c
376
+ LEFT JOIN sync_commits m
377
+ ON m.partition=${joinPartition} AND m.commit_seq=c.commit_seq
378
+ LEFT JOIN sync_changes ch
379
+ ON ch.partition=${joinPartition} AND ch.commit_seq=c.commit_seq AND ch.tbl=${joinTbl}
380
+ ORDER BY c.commit_seq, ch.idx`;
381
+ }
382
+
383
+ /** SELECT a row's version + scope map (admin/blob authz). Params: [partition, rowId]. */
384
+ export function selectRowScopesSql(
385
+ table: CompiledTable,
386
+ dialect: RelationalDialect,
387
+ ): string {
388
+ const p = dialect === 'sqlite' ? ['?', '?'] : ['$1', '$2'];
389
+ return `SELECT ${quoteIdent(SYNC_VERSION_COLUMN)} AS server_version, ${quoteIdent(SYNC_SCOPES_COLUMN)} AS scopes FROM ${quoteIdent(table.name)} WHERE ${quoteIdent(SYNC_PARTITION_COLUMN)}=${p[0]} AND ${quoteIdent(SYNC_ROW_ID_COLUMN)}=${p[1]}`;
390
+ }
391
+
392
+ /** DELETE one stored row. Params: [partition, rowId]. */
393
+ export function deleteRowSql(
394
+ table: CompiledTable,
395
+ dialect: RelationalDialect,
396
+ ): string {
397
+ const p = dialect === 'sqlite' ? ['?', '?'] : ['$1', '$2'];
398
+ return `DELETE FROM ${quoteIdent(table.name)} WHERE ${quoteIdent(SYNC_PARTITION_COLUMN)}=${p[0]} AND ${quoteIdent(SYNC_ROW_ID_COLUMN)}=${p[1]}`;
399
+ }
400
+
401
+ /**
402
+ * The schema-version marker table gating DDL work (DESIGN "server-side
403
+ * schema migration"): `ensureSchema` compares the stored version and skips
404
+ * all introspection/DDL when it matches — one cheap read per storage
405
+ * instance (relevant for D1's per-request instantiation).
406
+ *
407
+ * `layouts` persists each table's column layout (name/type/nullable, the
408
+ * exact inputs the row codec's byte layout depends on) as of the LAST
409
+ * applied schema version. The codec is strict — a payload only decodes
410
+ * under the column list it was encoded with — so a version bump MUST
411
+ * re-encode stored payloads (append trailing NULLs for added columns);
412
+ * decoding the old bytes requires the old layout, and this column is where
413
+ * it lives.
414
+ */
415
+ export const SCHEMA_META_DDL_SQLITE = `CREATE TABLE IF NOT EXISTS sync_schema_meta(
416
+ id INTEGER PRIMARY KEY CHECK (id = 1),
417
+ schema_version INTEGER NOT NULL,
418
+ layouts TEXT NOT NULL DEFAULT '{}'
419
+ )`;
420
+
421
+ export const SCHEMA_META_DDL_POSTGRES = `CREATE TABLE IF NOT EXISTS sync_schema_meta(
422
+ id INTEGER PRIMARY KEY CHECK (id = 1),
423
+ schema_version BIGINT NOT NULL,
424
+ layouts TEXT NOT NULL DEFAULT '{}'
425
+ )`;
426
+
427
+ // -- column layouts + payload migration (version bumps) ----------------------
428
+
429
+ /** The codec-relevant subset of a column, persisted per applied version. */
430
+ export interface StoredColumnLayout {
431
+ readonly name: string;
432
+ readonly type: RowColumn['type'];
433
+ readonly nullable: boolean;
434
+ }
435
+
436
+ export type StoredLayouts = Record<string, readonly StoredColumnLayout[]>;
437
+
438
+ /** The layouts JSON persisted alongside the schema version marker. */
439
+ export function layoutsOf(schema: CompiledSchema): string {
440
+ const out: Record<string, StoredColumnLayout[]> = {};
441
+ for (const table of schema.tables.values()) {
442
+ out[table.name] = table.columns.map((column) => ({
443
+ name: column.name,
444
+ type: column.type,
445
+ nullable: column.nullable,
446
+ }));
447
+ }
448
+ return JSON.stringify(out);
449
+ }
450
+
451
+ export function parseLayouts(json: string | null | undefined): StoredLayouts {
452
+ if (json === null || json === undefined || json.length === 0) return {};
453
+ return JSON.parse(json) as StoredLayouts;
454
+ }
455
+
456
+ /**
457
+ * Enforce the migration subset on a table's column list: the old layout
458
+ * must be an exact prefix (same name, type, nullability) of the new one,
459
+ * and appended columns must be nullable (there is no default to backfill).
460
+ * Returns `true` iff columns were appended.
461
+ */
462
+ export function assertAppendOnlyMigration(
463
+ tableName: string,
464
+ oldLayout: readonly StoredColumnLayout[],
465
+ table: CompiledTable,
466
+ ): boolean {
467
+ if (oldLayout.length > table.columns.length) {
468
+ throw new Error(
469
+ `table ${JSON.stringify(tableName)}: the schema removed columns — only CREATE TABLE / ADD COLUMN / CREATE INDEX migrations are supported`,
470
+ );
471
+ }
472
+ for (let i = 0; i < oldLayout.length; i++) {
473
+ const before = oldLayout[i];
474
+ const after = table.columns[i];
475
+ if (
476
+ before === undefined ||
477
+ after === undefined ||
478
+ before.name !== after.name ||
479
+ before.type !== after.type ||
480
+ before.nullable !== after.nullable
481
+ ) {
482
+ throw new Error(
483
+ `table ${JSON.stringify(tableName)}: column ${i} changed (${JSON.stringify(before)} → ${JSON.stringify({ name: after?.name, type: after?.type, nullable: after?.nullable })}) — only appending nullable columns is supported`,
484
+ );
485
+ }
486
+ }
487
+ for (let i = oldLayout.length; i < table.columns.length; i++) {
488
+ const added = table.columns[i];
489
+ if (added !== undefined && !added.nullable) {
490
+ throw new Error(
491
+ `table ${JSON.stringify(tableName)}: added column ${JSON.stringify(added.name)} must be nullable — existing rows have no value to backfill`,
492
+ );
493
+ }
494
+ }
495
+ return oldLayout.length < table.columns.length;
496
+ }
497
+
498
+ /**
499
+ * Re-encode an old-layout payload under the current columns: decode with
500
+ * the layout it was written under, append NULLs for the added columns,
501
+ * encode with the current column list. The write path (§3.4 scope-strip,
502
+ * CRDT merge, conflict serverRow) and the bootstrap serve path both decode
503
+ * stored payloads under the CURRENT schema, so this migration is a
504
+ * correctness requirement of the version bump, not an optimization.
505
+ */
506
+ export function migratePayload(
507
+ oldLayout: readonly StoredColumnLayout[],
508
+ table: CompiledTable,
509
+ payload: Uint8Array,
510
+ ): Uint8Array {
511
+ const values = decodeRow(oldLayout as readonly RowColumn[], payload);
512
+ while (values.length < table.columns.length) values.push(null);
513
+ return encodeRow(table.columns, values);
514
+ }
515
+
516
+ /**
517
+ * Keyset-paged scan of a row table for the migration rewrite.
518
+ * Params: [afterPartition, afterRowId, limit].
519
+ */
520
+ export function selectRowsForRewriteSql(
521
+ table: CompiledTable,
522
+ dialect: RelationalDialect,
523
+ ): string {
524
+ const p = dialect === 'sqlite' ? ['?', '?', '?'] : ['$1', '$2', '$3'];
525
+ return `SELECT ${quoteIdent(SYNC_PARTITION_COLUMN)} AS partition, ${quoteIdent(SYNC_ROW_ID_COLUMN)} AS row_id, ${quoteIdent(SYNC_PAYLOAD_COLUMN)} AS payload
526
+ FROM ${quoteIdent(table.name)}
527
+ WHERE (${quoteIdent(SYNC_PARTITION_COLUMN)}, ${quoteIdent(SYNC_ROW_ID_COLUMN)}) > (${p[0]}, ${p[1]})
528
+ ORDER BY ${quoteIdent(SYNC_PARTITION_COLUMN)}, ${quoteIdent(SYNC_ROW_ID_COLUMN)}
529
+ LIMIT ${p[2]}`;
530
+ }
531
+
532
+ /**
533
+ * Rewrite one row during a migration: refresh the projection columns (when
534
+ * materialized) and the payload. Bind with `rewriteValues`.
535
+ */
536
+ export function rewriteRowSql(
537
+ table: CompiledTable,
538
+ dialect: RelationalDialect,
539
+ ): string {
540
+ const sets: string[] = [];
541
+ let i = 1;
542
+ if (table.materialize) {
543
+ for (const column of table.columns) {
544
+ sets.push(
545
+ `${quoteIdent(column.name)}=${dialect === 'sqlite' ? '?' : `$${i}`}`,
546
+ );
547
+ i++;
548
+ }
549
+ }
550
+ sets.push(
551
+ `${quoteIdent(SYNC_PAYLOAD_COLUMN)}=${dialect === 'sqlite' ? '?' : `$${i}`}`,
552
+ );
553
+ i++;
554
+ const wherePartition = dialect === 'sqlite' ? '?' : `$${i}`;
555
+ const whereRowId = dialect === 'sqlite' ? '?' : `$${i + 1}`;
556
+ return `UPDATE ${quoteIdent(table.name)} SET ${sets.join(', ')} WHERE ${quoteIdent(SYNC_PARTITION_COLUMN)}=${wherePartition} AND ${quoteIdent(SYNC_ROW_ID_COLUMN)}=${whereRowId}`;
557
+ }
558
+
559
+ /** Bind values for `rewriteRowSql` from the (already migrated) payload. */
560
+ export function rewriteValues(
561
+ table: CompiledTable,
562
+ partition: string,
563
+ rowId: string,
564
+ payload: Uint8Array,
565
+ dialect: RelationalDialect,
566
+ ): unknown[] {
567
+ const out: unknown[] = [];
568
+ if (table.materialize) {
569
+ const values = decodeRow(table.columns, payload);
570
+ for (let i = 0; i < table.columns.length; i++) {
571
+ const column = table.columns[i];
572
+ if (column === undefined) continue;
573
+ out.push(toSqlValue(column, values[i] ?? null, dialect));
574
+ }
575
+ }
576
+ out.push(payload, partition, rowId);
577
+ return out;
578
+ }
579
+
580
+ /**
581
+ * What the migration rewrite phase must do for one table, derived from the
582
+ * persisted layouts + the physical columns present before this run.
583
+ *
584
+ * - `migrate`: the layout gained columns — every stored payload re-encodes
585
+ * under the new column list (correctness; see `migratePayload`).
586
+ * - `backfill`: the table just gained physical projection columns whose
587
+ * values exist in stored payloads (materialization flipped on) — the
588
+ * projection refreshes from the payload, no re-encode.
589
+ */
590
+ export function rewritePlan(
591
+ table: CompiledTable,
592
+ oldLayout: readonly StoredColumnLayout[] | undefined,
593
+ physicalColumnsBefore: ReadonlySet<string> | undefined,
594
+ ): { migrate: boolean; backfill: boolean } {
595
+ if (oldLayout === undefined || physicalColumnsBefore === undefined) {
596
+ // Fresh table (or a pre-layout database, which cannot be reasoned
597
+ // about): nothing stored to rewrite.
598
+ return { migrate: false, backfill: false };
599
+ }
600
+ const migrate = assertAppendOnlyMigration(table.name, oldLayout, table);
601
+ const backfill =
602
+ table.materialize &&
603
+ table.columns.some(
604
+ (column, index) =>
605
+ index < oldLayout.length && // value exists in old payloads
606
+ !physicalColumnsBefore.has(column.name), // column was just added
607
+ );
608
+ return { migrate, backfill };
609
+ }
610
+
611
+ /**
612
+ * Every DDL statement to bring a database from `existingColumnsByTable`
613
+ * (introspected; a missing key = table absent) to `schema`: CREATE TABLE
614
+ * for absent tables, ADD COLUMN for missing columns, CREATE INDEX for the
615
+ * declared user indexes — exactly the migration subset.
616
+ */
617
+ export function schemaDdl(
618
+ schema: CompiledSchema,
619
+ existingColumnsByTable: ReadonlyMap<string, ReadonlySet<string>>,
620
+ dialect: RelationalDialect,
621
+ ): string[] {
622
+ const out: string[] = [];
623
+ for (const table of schema.tables.values()) {
624
+ const existing = existingColumnsByTable.get(table.name);
625
+ if (existing === undefined) {
626
+ out.push(createTableDdl(table, dialect));
627
+ } else {
628
+ out.push(...addColumnDdl(table, existing, dialect));
629
+ }
630
+ out.push(...createIndexDdl(table));
631
+ }
632
+ return out;
633
+ }