@farukada/aws-langgraph-dynamodb-ts 0.9.0 → 1.0.0-rc.2

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 (512) hide show
  1. package/README.md +1720 -154
  2. package/dist/backfill/backfill.d.ts +168 -0
  3. package/dist/backfill/backfill.js +393 -0
  4. package/dist/checkpointer/actions/delete-thread.d.ts +47 -6
  5. package/dist/checkpointer/actions/delete-thread.js +58 -21
  6. package/dist/checkpointer/actions/get-tuple.d.ts +29 -4
  7. package/dist/checkpointer/actions/get-tuple.js +44 -10
  8. package/dist/checkpointer/actions/list.d.ts +46 -4
  9. package/dist/checkpointer/actions/list.js +121 -66
  10. package/dist/checkpointer/actions/put-writes.d.ts +41 -9
  11. package/dist/checkpointer/actions/put-writes.js +62 -77
  12. package/dist/checkpointer/actions/put.d.ts +83 -4
  13. package/dist/checkpointer/actions/put.js +177 -25
  14. package/dist/checkpointer/internal/delta-history.d.ts +112 -0
  15. package/dist/checkpointer/internal/delta-history.js +252 -0
  16. package/dist/checkpointer/internal/listing.d.ts +149 -0
  17. package/dist/checkpointer/internal/listing.js +245 -0
  18. package/dist/checkpointer/internal/parse.d.ts +262 -0
  19. package/dist/checkpointer/internal/parse.js +372 -0
  20. package/dist/checkpointer/internal/pending-writes.d.ts +275 -0
  21. package/dist/checkpointer/internal/pending-writes.js +588 -0
  22. package/dist/checkpointer/internal/read.d.ts +130 -0
  23. package/dist/checkpointer/internal/read.js +264 -0
  24. package/dist/checkpointer/internal/rows.d.ts +571 -0
  25. package/dist/checkpointer/internal/rows.js +834 -0
  26. package/dist/checkpointer/internal/setup.d.ts +42 -19
  27. package/dist/checkpointer/internal/setup.js +65 -29
  28. package/dist/checkpointer/saver.d.ts +256 -16
  29. package/dist/checkpointer/saver.js +275 -29
  30. package/dist/checkpointer/types.d.ts +39 -39
  31. package/dist/checkpointer/types.js +10 -1
  32. package/dist/factory/factory.d.ts +134 -28
  33. package/dist/factory/factory.js +240 -21
  34. package/dist/factory/types.d.ts +76 -0
  35. package/dist/factory/types.js +10 -0
  36. package/dist/history/actions/add-messages.d.ts +31 -4
  37. package/dist/history/actions/add-messages.js +38 -58
  38. package/dist/history/actions/clear.d.ts +49 -6
  39. package/dist/history/actions/clear.js +66 -14
  40. package/dist/history/actions/get-messages.d.ts +54 -6
  41. package/dist/history/actions/get-messages.js +126 -43
  42. package/dist/history/actions/list-sessions.d.ts +52 -10
  43. package/dist/history/actions/list-sessions.js +139 -40
  44. package/dist/history/actions/reconcile-count.d.ts +42 -10
  45. package/dist/history/actions/reconcile-count.js +45 -45
  46. package/dist/history/chat-message-history.d.ts +220 -33
  47. package/dist/history/chat-message-history.js +240 -43
  48. package/dist/history/internal/append.d.ts +212 -0
  49. package/dist/history/internal/append.js +500 -0
  50. package/dist/history/internal/message-read.d.ts +84 -0
  51. package/dist/history/internal/message-read.js +204 -0
  52. package/dist/history/internal/parse.d.ts +153 -0
  53. package/dist/history/internal/parse.js +252 -0
  54. package/dist/history/internal/rows.d.ts +195 -0
  55. package/dist/history/internal/rows.js +250 -0
  56. package/dist/history/internal/session.d.ts +331 -0
  57. package/dist/history/internal/session.js +628 -0
  58. package/dist/history/internal/setup.d.ts +52 -17
  59. package/dist/history/internal/setup.js +92 -21
  60. package/dist/history/session-adapter.d.ts +102 -7
  61. package/dist/history/session-adapter.js +103 -9
  62. package/dist/history/types.d.ts +80 -29
  63. package/dist/history/types.js +10 -1
  64. package/dist/index.d.ts +42 -11
  65. package/dist/index.js +33 -12
  66. package/dist/shared/adapter.d.ts +135 -0
  67. package/dist/shared/adapter.js +143 -0
  68. package/dist/shared/clock.d.ts +51 -2
  69. package/dist/shared/clock.js +57 -2
  70. package/dist/shared/codec/codec.d.ts +288 -13
  71. package/dist/shared/codec/codec.js +416 -19
  72. package/dist/shared/codec/compression.d.ts +43 -7
  73. package/dist/shared/codec/compression.js +53 -13
  74. package/dist/shared/codec/json-serde.d.ts +76 -4
  75. package/dist/shared/codec/json-serde.js +181 -8
  76. package/dist/shared/codec/s3/client-types.d.ts +53 -0
  77. package/dist/shared/codec/s3/client-types.js +26 -0
  78. package/dist/shared/codec/s3/client.d.ts +43 -10
  79. package/dist/shared/codec/s3/client.js +82 -9
  80. package/dist/shared/codec/s3/config.d.ts +242 -11
  81. package/dist/shared/codec/s3/config.js +293 -11
  82. package/dist/shared/codec/s3/lifecycle.d.ts +164 -6
  83. package/dist/shared/codec/s3/lifecycle.js +335 -27
  84. package/dist/shared/codec/s3/offloader.d.ts +393 -18
  85. package/dist/shared/codec/s3/offloader.js +595 -37
  86. package/dist/shared/concurrency.d.ts +43 -0
  87. package/dist/shared/concurrency.js +78 -0
  88. package/dist/shared/dynamodb/abort.d.ts +47 -0
  89. package/dist/shared/dynamodb/abort.js +59 -0
  90. package/dist/shared/dynamodb/batch-write.d.ts +77 -14
  91. package/dist/shared/dynamodb/batch-write.js +146 -27
  92. package/dist/shared/dynamodb/cancellation.d.ts +121 -4
  93. package/dist/shared/dynamodb/cancellation.js +147 -3
  94. package/dist/shared/dynamodb/client.d.ts +162 -8
  95. package/dist/shared/dynamodb/client.js +153 -5
  96. package/dist/shared/dynamodb/idempotent-write.d.ts +551 -0
  97. package/dist/shared/dynamodb/idempotent-write.js +593 -0
  98. package/dist/shared/dynamodb/paginate.d.ts +105 -9
  99. package/dist/shared/dynamodb/paginate.js +175 -7
  100. package/dist/shared/dynamodb/partition-delete.d.ts +185 -14
  101. package/dist/shared/dynamodb/partition-delete.js +314 -44
  102. package/dist/shared/dynamodb/recency-index.d.ts +231 -0
  103. package/dist/shared/dynamodb/recency-index.js +377 -0
  104. package/dist/shared/dynamodb/retry.d.ts +276 -8
  105. package/dist/shared/dynamodb/retry.js +433 -23
  106. package/dist/shared/dynamodb/table-schema.d.ts +190 -0
  107. package/dist/shared/dynamodb/table-schema.js +209 -0
  108. package/dist/shared/errors/base-error.d.ts +184 -10
  109. package/dist/shared/errors/base-error.js +160 -14
  110. package/dist/shared/errors/boundary.d.ts +71 -0
  111. package/dist/shared/errors/boundary.js +143 -0
  112. package/dist/shared/errors/classify.d.ts +97 -0
  113. package/dist/shared/errors/classify.js +257 -0
  114. package/dist/shared/errors/error-code.d.ts +77 -2
  115. package/dist/shared/errors/error-code.js +83 -1
  116. package/dist/shared/errors/errors.d.ts +158 -59
  117. package/dist/shared/errors/errors.js +219 -92
  118. package/dist/shared/logging/logger.d.ts +69 -3
  119. package/dist/shared/logging/logger.js +97 -3
  120. package/dist/shared/logging/redaction.d.ts +92 -8
  121. package/dist/shared/logging/redaction.js +273 -17
  122. package/dist/shared/logging/secret-patterns.d.ts +149 -19
  123. package/dist/shared/logging/secret-patterns.js +188 -27
  124. package/dist/shared/logging/truncate.d.ts +197 -0
  125. package/dist/shared/logging/truncate.js +231 -0
  126. package/dist/shared/options.d.ts +59 -7
  127. package/dist/shared/options.js +9 -1
  128. package/dist/shared/ulid.d.ts +77 -7
  129. package/dist/shared/ulid.js +103 -8
  130. package/dist/shared/validation/collaborators.d.ts +141 -0
  131. package/dist/shared/validation/collaborators.js +188 -0
  132. package/dist/shared/validation/option-shape.d.ts +89 -0
  133. package/dist/shared/validation/option-shape.js +113 -0
  134. package/dist/shared/validation/options.d.ts +145 -0
  135. package/dist/shared/validation/options.js +328 -0
  136. package/dist/shared/validation/primitives.d.ts +288 -21
  137. package/dist/shared/validation/primitives.js +353 -50
  138. package/dist/shared/validation/ttl.d.ts +66 -10
  139. package/dist/shared/validation/ttl.js +113 -15
  140. package/dist/store/actions/list-namespaces.d.ts +76 -6
  141. package/dist/store/actions/list-namespaces.js +166 -24
  142. package/dist/store/actions/put.d.ts +33 -8
  143. package/dist/store/actions/put.js +53 -60
  144. package/dist/store/actions/reconcile-vector-index.d.ts +31 -10
  145. package/dist/store/actions/reconcile-vector-index.js +34 -15
  146. package/dist/store/actions/search.d.ts +34 -6
  147. package/dist/store/actions/search.js +56 -51
  148. package/dist/store/internal/batch-plan.d.ts +26 -0
  149. package/dist/store/internal/batch-plan.js +109 -0
  150. package/dist/store/internal/filter.d.ts +36 -3
  151. package/dist/store/internal/filter.js +66 -15
  152. package/dist/store/internal/get-item.d.ts +45 -0
  153. package/dist/store/internal/get-item.js +115 -0
  154. package/dist/store/internal/item-write.d.ts +230 -0
  155. package/dist/store/internal/item-write.js +463 -0
  156. package/dist/store/internal/parse.d.ts +225 -0
  157. package/dist/store/internal/parse.js +350 -0
  158. package/dist/store/internal/rows.d.ts +355 -0
  159. package/dist/store/internal/rows.js +447 -0
  160. package/dist/store/internal/semantic-search.d.ts +161 -6
  161. package/dist/store/internal/semantic-search.js +360 -18
  162. package/dist/store/internal/setup.d.ts +77 -20
  163. package/dist/store/internal/setup.js +178 -47
  164. package/dist/store/internal/table-search.d.ts +100 -0
  165. package/dist/store/internal/table-search.js +213 -0
  166. package/dist/store/internal/vector-index.d.ts +247 -0
  167. package/dist/store/internal/vector-index.js +546 -0
  168. package/dist/store/store.d.ts +270 -17
  169. package/dist/store/store.js +329 -38
  170. package/dist/store/types.d.ts +76 -26
  171. package/dist/store/types.js +13 -1
  172. package/dist/store/vector-backend.d.ts +64 -4
  173. package/dist/store/vector-backend.js +15 -1
  174. package/package.json +58 -36
  175. package/dist/checkpointer/actions/delete-thread.d.ts.map +0 -1
  176. package/dist/checkpointer/actions/delete-thread.js.map +0 -1
  177. package/dist/checkpointer/actions/get-tuple.d.ts.map +0 -1
  178. package/dist/checkpointer/actions/get-tuple.js.map +0 -1
  179. package/dist/checkpointer/actions/list.d.ts.map +0 -1
  180. package/dist/checkpointer/actions/list.js.map +0 -1
  181. package/dist/checkpointer/actions/put-writes.d.ts.map +0 -1
  182. package/dist/checkpointer/actions/put-writes.js.map +0 -1
  183. package/dist/checkpointer/actions/put.d.ts.map +0 -1
  184. package/dist/checkpointer/actions/put.js.map +0 -1
  185. package/dist/checkpointer/internal/assemble.d.ts +0 -10
  186. package/dist/checkpointer/internal/assemble.d.ts.map +0 -1
  187. package/dist/checkpointer/internal/assemble.js +0 -37
  188. package/dist/checkpointer/internal/assemble.js.map +0 -1
  189. package/dist/checkpointer/internal/configurable.d.ts +0 -13
  190. package/dist/checkpointer/internal/configurable.d.ts.map +0 -1
  191. package/dist/checkpointer/internal/configurable.js +0 -23
  192. package/dist/checkpointer/internal/configurable.js.map +0 -1
  193. package/dist/checkpointer/internal/fetch.d.ts +0 -10
  194. package/dist/checkpointer/internal/fetch.d.ts.map +0 -1
  195. package/dist/checkpointer/internal/fetch.js +0 -46
  196. package/dist/checkpointer/internal/fetch.js.map +0 -1
  197. package/dist/checkpointer/internal/filter-match.d.ts +0 -12
  198. package/dist/checkpointer/internal/filter-match.d.ts.map +0 -1
  199. package/dist/checkpointer/internal/filter-match.js +0 -14
  200. package/dist/checkpointer/internal/filter-match.js.map +0 -1
  201. package/dist/checkpointer/internal/item-reader.d.ts +0 -55
  202. package/dist/checkpointer/internal/item-reader.d.ts.map +0 -1
  203. package/dist/checkpointer/internal/item-reader.js +0 -88
  204. package/dist/checkpointer/internal/item-reader.js.map +0 -1
  205. package/dist/checkpointer/internal/item-writer.d.ts +0 -26
  206. package/dist/checkpointer/internal/item-writer.d.ts.map +0 -1
  207. package/dist/checkpointer/internal/item-writer.js +0 -92
  208. package/dist/checkpointer/internal/item-writer.js.map +0 -1
  209. package/dist/checkpointer/internal/keys.d.ts +0 -31
  210. package/dist/checkpointer/internal/keys.d.ts.map +0 -1
  211. package/dist/checkpointer/internal/keys.js +0 -87
  212. package/dist/checkpointer/internal/keys.js.map +0 -1
  213. package/dist/checkpointer/internal/query.d.ts +0 -20
  214. package/dist/checkpointer/internal/query.d.ts.map +0 -1
  215. package/dist/checkpointer/internal/query.js +0 -36
  216. package/dist/checkpointer/internal/query.js.map +0 -1
  217. package/dist/checkpointer/internal/setup.d.ts.map +0 -1
  218. package/dist/checkpointer/internal/setup.js.map +0 -1
  219. package/dist/checkpointer/internal/special-write-cas.d.ts +0 -30
  220. package/dist/checkpointer/internal/special-write-cas.d.ts.map +0 -1
  221. package/dist/checkpointer/internal/special-write-cas.js +0 -104
  222. package/dist/checkpointer/internal/special-write-cas.js.map +0 -1
  223. package/dist/checkpointer/internal/special-write-cleanup.d.ts +0 -24
  224. package/dist/checkpointer/internal/special-write-cleanup.d.ts.map +0 -1
  225. package/dist/checkpointer/internal/special-write-cleanup.js +0 -47
  226. package/dist/checkpointer/internal/special-write-cleanup.js.map +0 -1
  227. package/dist/checkpointer/internal/special-write-verify.d.ts +0 -54
  228. package/dist/checkpointer/internal/special-write-verify.d.ts.map +0 -1
  229. package/dist/checkpointer/internal/special-write-verify.js +0 -65
  230. package/dist/checkpointer/internal/special-write-verify.js.map +0 -1
  231. package/dist/checkpointer/internal/validation.d.ts +0 -13
  232. package/dist/checkpointer/internal/validation.d.ts.map +0 -1
  233. package/dist/checkpointer/internal/validation.js +0 -30
  234. package/dist/checkpointer/internal/validation.js.map +0 -1
  235. package/dist/checkpointer/internal/write-guard.d.ts +0 -13
  236. package/dist/checkpointer/internal/write-guard.d.ts.map +0 -1
  237. package/dist/checkpointer/internal/write-guard.js +0 -39
  238. package/dist/checkpointer/internal/write-guard.js.map +0 -1
  239. package/dist/checkpointer/internal/write-index.d.ts +0 -37
  240. package/dist/checkpointer/internal/write-index.d.ts.map +0 -1
  241. package/dist/checkpointer/internal/write-index.js +0 -42
  242. package/dist/checkpointer/internal/write-index.js.map +0 -1
  243. package/dist/checkpointer/saver.d.ts.map +0 -1
  244. package/dist/checkpointer/saver.js.map +0 -1
  245. package/dist/checkpointer/types.d.ts.map +0 -1
  246. package/dist/checkpointer/types.js.map +0 -1
  247. package/dist/factory/factory.d.ts.map +0 -1
  248. package/dist/factory/factory.js.map +0 -1
  249. package/dist/history/actions/add-messages.d.ts.map +0 -1
  250. package/dist/history/actions/add-messages.js.map +0 -1
  251. package/dist/history/actions/clear.d.ts.map +0 -1
  252. package/dist/history/actions/clear.js.map +0 -1
  253. package/dist/history/actions/get-messages.d.ts.map +0 -1
  254. package/dist/history/actions/get-messages.js.map +0 -1
  255. package/dist/history/actions/list-sessions.d.ts.map +0 -1
  256. package/dist/history/actions/list-sessions.js.map +0 -1
  257. package/dist/history/actions/reconcile-count.d.ts.map +0 -1
  258. package/dist/history/actions/reconcile-count.js.map +0 -1
  259. package/dist/history/chat-message-history.d.ts.map +0 -1
  260. package/dist/history/chat-message-history.js.map +0 -1
  261. package/dist/history/internal/append-saga.d.ts +0 -20
  262. package/dist/history/internal/append-saga.d.ts.map +0 -1
  263. package/dist/history/internal/append-saga.js +0 -35
  264. package/dist/history/internal/append-saga.js.map +0 -1
  265. package/dist/history/internal/compensation.d.ts +0 -21
  266. package/dist/history/internal/compensation.d.ts.map +0 -1
  267. package/dist/history/internal/compensation.js +0 -84
  268. package/dist/history/internal/compensation.js.map +0 -1
  269. package/dist/history/internal/item-mapper.d.ts +0 -12
  270. package/dist/history/internal/item-mapper.d.ts.map +0 -1
  271. package/dist/history/internal/item-mapper.js +0 -33
  272. package/dist/history/internal/item-mapper.js.map +0 -1
  273. package/dist/history/internal/keys.d.ts +0 -17
  274. package/dist/history/internal/keys.d.ts.map +0 -1
  275. package/dist/history/internal/keys.js +0 -49
  276. package/dist/history/internal/keys.js.map +0 -1
  277. package/dist/history/internal/message-chunker.d.ts +0 -14
  278. package/dist/history/internal/message-chunker.d.ts.map +0 -1
  279. package/dist/history/internal/message-chunker.js +0 -68
  280. package/dist/history/internal/message-chunker.js.map +0 -1
  281. package/dist/history/internal/message-transaction.d.ts +0 -26
  282. package/dist/history/internal/message-transaction.d.ts.map +0 -1
  283. package/dist/history/internal/message-transaction.js +0 -60
  284. package/dist/history/internal/message-transaction.js.map +0 -1
  285. package/dist/history/internal/query.d.ts +0 -10
  286. package/dist/history/internal/query.d.ts.map +0 -1
  287. package/dist/history/internal/query.js +0 -31
  288. package/dist/history/internal/query.js.map +0 -1
  289. package/dist/history/internal/session-count.d.ts +0 -41
  290. package/dist/history/internal/session-count.d.ts.map +0 -1
  291. package/dist/history/internal/session-count.js +0 -109
  292. package/dist/history/internal/session-count.js.map +0 -1
  293. package/dist/history/internal/session-title.d.ts +0 -20
  294. package/dist/history/internal/session-title.d.ts.map +0 -1
  295. package/dist/history/internal/session-title.js +0 -44
  296. package/dist/history/internal/session-title.js.map +0 -1
  297. package/dist/history/internal/session-update.d.ts +0 -28
  298. package/dist/history/internal/session-update.d.ts.map +0 -1
  299. package/dist/history/internal/session-update.js +0 -70
  300. package/dist/history/internal/session-update.js.map +0 -1
  301. package/dist/history/internal/setup.d.ts.map +0 -1
  302. package/dist/history/internal/setup.js.map +0 -1
  303. package/dist/history/internal/title-generator.d.ts +0 -13
  304. package/dist/history/internal/title-generator.d.ts.map +0 -1
  305. package/dist/history/internal/title-generator.js +0 -25
  306. package/dist/history/internal/title-generator.js.map +0 -1
  307. package/dist/history/internal/ttl-anchor.d.ts +0 -25
  308. package/dist/history/internal/ttl-anchor.d.ts.map +0 -1
  309. package/dist/history/internal/ttl-anchor.js +0 -38
  310. package/dist/history/internal/ttl-anchor.js.map +0 -1
  311. package/dist/history/internal/validation.d.ts +0 -9
  312. package/dist/history/internal/validation.d.ts.map +0 -1
  313. package/dist/history/internal/validation.js +0 -16
  314. package/dist/history/internal/validation.js.map +0 -1
  315. package/dist/history/session-adapter.d.ts.map +0 -1
  316. package/dist/history/session-adapter.js.map +0 -1
  317. package/dist/history/types.d.ts.map +0 -1
  318. package/dist/history/types.js.map +0 -1
  319. package/dist/index.d.ts.map +0 -1
  320. package/dist/index.js.map +0 -1
  321. package/dist/shared/clock.d.ts.map +0 -1
  322. package/dist/shared/clock.js.map +0 -1
  323. package/dist/shared/codec/codec.d.ts.map +0 -1
  324. package/dist/shared/codec/codec.js.map +0 -1
  325. package/dist/shared/codec/compression.d.ts.map +0 -1
  326. package/dist/shared/codec/compression.js.map +0 -1
  327. package/dist/shared/codec/descriptor-keys.d.ts +0 -4
  328. package/dist/shared/codec/descriptor-keys.d.ts.map +0 -1
  329. package/dist/shared/codec/descriptor-keys.js +0 -14
  330. package/dist/shared/codec/descriptor-keys.js.map +0 -1
  331. package/dist/shared/codec/json-serde.d.ts.map +0 -1
  332. package/dist/shared/codec/json-serde.js.map +0 -1
  333. package/dist/shared/codec/s3/client.d.ts.map +0 -1
  334. package/dist/shared/codec/s3/client.js.map +0 -1
  335. package/dist/shared/codec/s3/config.d.ts.map +0 -1
  336. package/dist/shared/codec/s3/config.js.map +0 -1
  337. package/dist/shared/codec/s3/delete.d.ts +0 -8
  338. package/dist/shared/codec/s3/delete.d.ts.map +0 -1
  339. package/dist/shared/codec/s3/delete.js +0 -29
  340. package/dist/shared/codec/s3/delete.js.map +0 -1
  341. package/dist/shared/codec/s3/lifecycle.d.ts.map +0 -1
  342. package/dist/shared/codec/s3/lifecycle.js.map +0 -1
  343. package/dist/shared/codec/s3/offloader.d.ts.map +0 -1
  344. package/dist/shared/codec/s3/offloader.js.map +0 -1
  345. package/dist/shared/codec/s3/orphans.d.ts +0 -18
  346. package/dist/shared/codec/s3/orphans.d.ts.map +0 -1
  347. package/dist/shared/codec/s3/orphans.js +0 -58
  348. package/dist/shared/codec/s3/orphans.js.map +0 -1
  349. package/dist/shared/codec/s3/read-write.d.ts +0 -14
  350. package/dist/shared/codec/s3/read-write.d.ts.map +0 -1
  351. package/dist/shared/codec/s3/read-write.js +0 -43
  352. package/dist/shared/codec/s3/read-write.js.map +0 -1
  353. package/dist/shared/codec/s3/retry.d.ts +0 -5
  354. package/dist/shared/codec/s3/retry.d.ts.map +0 -1
  355. package/dist/shared/codec/s3/retry.js +0 -25
  356. package/dist/shared/codec/s3/retry.js.map +0 -1
  357. package/dist/shared/constants.d.ts +0 -64
  358. package/dist/shared/constants.d.ts.map +0 -1
  359. package/dist/shared/constants.js +0 -67
  360. package/dist/shared/constants.js.map +0 -1
  361. package/dist/shared/dynamodb/backoff.d.ts +0 -15
  362. package/dist/shared/dynamodb/backoff.d.ts.map +0 -1
  363. package/dist/shared/dynamodb/backoff.js +0 -48
  364. package/dist/shared/dynamodb/backoff.js.map +0 -1
  365. package/dist/shared/dynamodb/batch-write.d.ts.map +0 -1
  366. package/dist/shared/dynamodb/batch-write.js.map +0 -1
  367. package/dist/shared/dynamodb/cancellation.d.ts.map +0 -1
  368. package/dist/shared/dynamodb/cancellation.js.map +0 -1
  369. package/dist/shared/dynamodb/client.d.ts.map +0 -1
  370. package/dist/shared/dynamodb/client.js.map +0 -1
  371. package/dist/shared/dynamodb/conditional-put.d.ts +0 -51
  372. package/dist/shared/dynamodb/conditional-put.d.ts.map +0 -1
  373. package/dist/shared/dynamodb/conditional-put.js +0 -59
  374. package/dist/shared/dynamodb/conditional-put.js.map +0 -1
  375. package/dist/shared/dynamodb/drain-unprocessed.d.ts +0 -19
  376. package/dist/shared/dynamodb/drain-unprocessed.d.ts.map +0 -1
  377. package/dist/shared/dynamodb/drain-unprocessed.js +0 -44
  378. package/dist/shared/dynamodb/drain-unprocessed.js.map +0 -1
  379. package/dist/shared/dynamodb/paginate-core.d.ts +0 -22
  380. package/dist/shared/dynamodb/paginate-core.d.ts.map +0 -1
  381. package/dist/shared/dynamodb/paginate-core.js +0 -52
  382. package/dist/shared/dynamodb/paginate-core.js.map +0 -1
  383. package/dist/shared/dynamodb/paginate.d.ts.map +0 -1
  384. package/dist/shared/dynamodb/paginate.js.map +0 -1
  385. package/dist/shared/dynamodb/partition-delete.d.ts.map +0 -1
  386. package/dist/shared/dynamodb/partition-delete.js.map +0 -1
  387. package/dist/shared/dynamodb/retry-classifier.d.ts +0 -9
  388. package/dist/shared/dynamodb/retry-classifier.d.ts.map +0 -1
  389. package/dist/shared/dynamodb/retry-classifier.js +0 -87
  390. package/dist/shared/dynamodb/retry-classifier.js.map +0 -1
  391. package/dist/shared/dynamodb/retry.d.ts.map +0 -1
  392. package/dist/shared/dynamodb/retry.js.map +0 -1
  393. package/dist/shared/dynamodb/scan.d.ts +0 -15
  394. package/dist/shared/dynamodb/scan.d.ts.map +0 -1
  395. package/dist/shared/dynamodb/scan.js +0 -20
  396. package/dist/shared/dynamodb/scan.js.map +0 -1
  397. package/dist/shared/dynamodb/types.d.ts +0 -24
  398. package/dist/shared/dynamodb/types.d.ts.map +0 -1
  399. package/dist/shared/dynamodb/types.js +0 -3
  400. package/dist/shared/dynamodb/types.js.map +0 -1
  401. package/dist/shared/errors/base-error.d.ts.map +0 -1
  402. package/dist/shared/errors/base-error.js.map +0 -1
  403. package/dist/shared/errors/error-code.d.ts.map +0 -1
  404. package/dist/shared/errors/error-code.js.map +0 -1
  405. package/dist/shared/errors/errors.d.ts.map +0 -1
  406. package/dist/shared/errors/errors.js.map +0 -1
  407. package/dist/shared/errors/wrap-error.d.ts +0 -16
  408. package/dist/shared/errors/wrap-error.d.ts.map +0 -1
  409. package/dist/shared/errors/wrap-error.js +0 -30
  410. package/dist/shared/errors/wrap-error.js.map +0 -1
  411. package/dist/shared/logging/logger.d.ts.map +0 -1
  412. package/dist/shared/logging/logger.js.map +0 -1
  413. package/dist/shared/logging/redaction-walk.d.ts +0 -23
  414. package/dist/shared/logging/redaction-walk.d.ts.map +0 -1
  415. package/dist/shared/logging/redaction-walk.js +0 -92
  416. package/dist/shared/logging/redaction-walk.js.map +0 -1
  417. package/dist/shared/logging/redaction.d.ts.map +0 -1
  418. package/dist/shared/logging/redaction.js.map +0 -1
  419. package/dist/shared/logging/secret-patterns.d.ts.map +0 -1
  420. package/dist/shared/logging/secret-patterns.js.map +0 -1
  421. package/dist/shared/options.d.ts.map +0 -1
  422. package/dist/shared/options.js.map +0 -1
  423. package/dist/shared/ulid.d.ts.map +0 -1
  424. package/dist/shared/ulid.js.map +0 -1
  425. package/dist/shared/validation/primitives.d.ts.map +0 -1
  426. package/dist/shared/validation/primitives.js.map +0 -1
  427. package/dist/shared/validation/ttl.d.ts.map +0 -1
  428. package/dist/shared/validation/ttl.js.map +0 -1
  429. package/dist/store/actions/get.d.ts +0 -5
  430. package/dist/store/actions/get.d.ts.map +0 -1
  431. package/dist/store/actions/get.js +0 -35
  432. package/dist/store/actions/get.js.map +0 -1
  433. package/dist/store/actions/list-namespaces.d.ts.map +0 -1
  434. package/dist/store/actions/list-namespaces.js.map +0 -1
  435. package/dist/store/actions/put.d.ts.map +0 -1
  436. package/dist/store/actions/put.js.map +0 -1
  437. package/dist/store/actions/reconcile-vector-index.d.ts.map +0 -1
  438. package/dist/store/actions/reconcile-vector-index.js.map +0 -1
  439. package/dist/store/actions/search.d.ts.map +0 -1
  440. package/dist/store/actions/search.js.map +0 -1
  441. package/dist/store/internal/backend-search.d.ts +0 -5
  442. package/dist/store/internal/backend-search.d.ts.map +0 -1
  443. package/dist/store/internal/backend-search.js +0 -68
  444. package/dist/store/internal/backend-search.js.map +0 -1
  445. package/dist/store/internal/filter.d.ts.map +0 -1
  446. package/dist/store/internal/filter.js.map +0 -1
  447. package/dist/store/internal/index-reconcile.d.ts +0 -22
  448. package/dist/store/internal/index-reconcile.d.ts.map +0 -1
  449. package/dist/store/internal/index-reconcile.js +0 -105
  450. package/dist/store/internal/index-reconcile.js.map +0 -1
  451. package/dist/store/internal/index-sync.d.ts +0 -11
  452. package/dist/store/internal/index-sync.d.ts.map +0 -1
  453. package/dist/store/internal/index-sync.js +0 -26
  454. package/dist/store/internal/index-sync.js.map +0 -1
  455. package/dist/store/internal/item-mapper.d.ts +0 -25
  456. package/dist/store/internal/item-mapper.d.ts.map +0 -1
  457. package/dist/store/internal/item-mapper.js +0 -53
  458. package/dist/store/internal/item-mapper.js.map +0 -1
  459. package/dist/store/internal/keys.d.ts +0 -18
  460. package/dist/store/internal/keys.d.ts.map +0 -1
  461. package/dist/store/internal/keys.js +0 -42
  462. package/dist/store/internal/keys.js.map +0 -1
  463. package/dist/store/internal/namespace-match.d.ts +0 -12
  464. package/dist/store/internal/namespace-match.d.ts.map +0 -1
  465. package/dist/store/internal/namespace-match.js +0 -41
  466. package/dist/store/internal/namespace-match.js.map +0 -1
  467. package/dist/store/internal/overwrite-swap.d.ts +0 -33
  468. package/dist/store/internal/overwrite-swap.d.ts.map +0 -1
  469. package/dist/store/internal/overwrite-swap.js +0 -62
  470. package/dist/store/internal/overwrite-swap.js.map +0 -1
  471. package/dist/store/internal/persist.d.ts +0 -27
  472. package/dist/store/internal/persist.d.ts.map +0 -1
  473. package/dist/store/internal/persist.js +0 -59
  474. package/dist/store/internal/persist.js.map +0 -1
  475. package/dist/store/internal/query.d.ts +0 -6
  476. package/dist/store/internal/query.d.ts.map +0 -1
  477. package/dist/store/internal/query.js +0 -32
  478. package/dist/store/internal/query.js.map +0 -1
  479. package/dist/store/internal/ranker.d.ts +0 -13
  480. package/dist/store/internal/ranker.d.ts.map +0 -1
  481. package/dist/store/internal/ranker.js +0 -31
  482. package/dist/store/internal/ranker.js.map +0 -1
  483. package/dist/store/internal/read-existing.d.ts +0 -19
  484. package/dist/store/internal/read-existing.d.ts.map +0 -1
  485. package/dist/store/internal/read-existing.js +0 -29
  486. package/dist/store/internal/read-existing.js.map +0 -1
  487. package/dist/store/internal/score-direction.d.ts +0 -32
  488. package/dist/store/internal/score-direction.d.ts.map +0 -1
  489. package/dist/store/internal/score-direction.js +0 -39
  490. package/dist/store/internal/score-direction.js.map +0 -1
  491. package/dist/store/internal/search-filter.d.ts +0 -4
  492. package/dist/store/internal/search-filter.d.ts.map +0 -1
  493. package/dist/store/internal/search-filter.js +0 -11
  494. package/dist/store/internal/search-filter.js.map +0 -1
  495. package/dist/store/internal/semantic-search.d.ts.map +0 -1
  496. package/dist/store/internal/semantic-search.js.map +0 -1
  497. package/dist/store/internal/setup.d.ts.map +0 -1
  498. package/dist/store/internal/setup.js.map +0 -1
  499. package/dist/store/internal/validation.d.ts +0 -13
  500. package/dist/store/internal/validation.d.ts.map +0 -1
  501. package/dist/store/internal/validation.js +0 -35
  502. package/dist/store/internal/validation.js.map +0 -1
  503. package/dist/store/internal/write-verify.d.ts +0 -37
  504. package/dist/store/internal/write-verify.d.ts.map +0 -1
  505. package/dist/store/internal/write-verify.js +0 -68
  506. package/dist/store/internal/write-verify.js.map +0 -1
  507. package/dist/store/store.d.ts.map +0 -1
  508. package/dist/store/store.js.map +0 -1
  509. package/dist/store/types.d.ts.map +0 -1
  510. package/dist/store/types.js.map +0 -1
  511. package/dist/store/vector-backend.d.ts.map +0 -1
  512. package/dist/store/vector-backend.js.map +0 -1
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Hides how rows written before the recency index are given its keys.
3
+ *
4
+ * The index is opt-in (record 8), so a table can hold rows from before it
5
+ * existed. An operator walks the table a page at a time, resumably, and gives
6
+ * each row the keys its adapter would have written; which rows those are is
7
+ * each adapter's own answer, asked here, and a row that gained keys since the
8
+ * scan read it is left alone.
9
+ */
10
+ import type { AttributeMap, DynamoDBDocumentLike } from '../shared/dynamodb/client';
11
+ import { type IndexTarget } from '../shared/dynamodb/recency-index';
12
+ import { type RetryOptions } from '../shared/dynamodb/retry';
13
+ /**
14
+ * Give rows written before the recency index their index keys.
15
+ *
16
+ * **Run this before setting `indexName` on any adapter.** A row without the
17
+ * keys is not in the index, so enabling the index first would make every
18
+ * pre-existing session, item and checkpoint silently vanish from the listings
19
+ * that read it — the rows are still there, and every other read still returns
20
+ * them, but a listing would not.
21
+ *
22
+ * Safe to re-run and safe to run while adapters are writing: every write is
23
+ * conditional on the row still being there and having no keys yet, so a row a
24
+ * live adapter has already indexed is left exactly as it is, and a row deleted
25
+ * after the scan found it stays deleted rather than being re-created by an
26
+ * `UpdateItem`, which upserts.
27
+ *
28
+ * `indexShards` must match what the adapters use. A mismatch puts rows on
29
+ * shards no listing queries, which looks exactly like the rows being missing.
30
+ *
31
+ * Accepts: `options` — validated in full before any read: only the keys
32
+ * `BackfillOptions` declares; `tableName`, `indexShards` and the numbers in
33
+ * `retry` by the adapters' rules; `signal` as their methods check it; a
34
+ * `client` providing `scan` and `update`. `options.pageSize` — a positive integer,
35
+ * default 100. `options.cursor` — from a previous run, to resume.
36
+ * `options.maxPages` — how far one run goes, so a large table can be
37
+ * backfilled in bounded slices. `options.indexShards` — must equal the
38
+ * adapters' setting, and has their ceiling. `options.dryRun` — a boolean.
39
+ * `options.signal` — cancels the run; `retry.signal` does so when there is no
40
+ * top-level `signal`, and the top-level one wins when both are given.
41
+ *
42
+ * Returns: how many rows were scanned, how many were given keys and how many
43
+ * were skipped — a row no listing reaches, and a row whose write the condition
44
+ * refused because the row already has keys or is gone — plus a `nextCursor`
45
+ * when the run stopped short of the end. An absent cursor means the table is
46
+ * fully backfilled.
47
+ *
48
+ * Throws: `VALIDATION` naming the offending option, before any DynamoDB
49
+ * call; `RETRY_EXHAUSTED` once a transient failure has used every attempt;
50
+ * `ABORTED` when `signal` fires, or `retry.signal` when no top-level `signal`
51
+ * is given; any other error the scan or the writes throw, wrapped with the
52
+ * code the classifier assigns — this is the function's own error boundary,
53
+ * the same as every adapter's public methods, so a caller's mistake never escapes as a bare
54
+ * exception. A refused write is none of these: it is an outcome for one row,
55
+ * reported in `skipped`.
56
+ *
57
+ * Guarantees: every write is conditional on the row still being there and
58
+ * having no keys yet, so re-running is safe, running against a live table is
59
+ * safe, a row a live adapter has already indexed is left exactly as it is, and
60
+ * a row deleted between the scan and the write is never re-created. Neither
61
+ * refusal stops the run: both mean this run has nothing to do for that row, so
62
+ * the row is counted as skipped and the walk carries on to the rest of the
63
+ * table.
64
+ */
65
+ export declare function backfillRecencyIndex(options: BackfillOptions): Promise<BackfillResult>;
66
+ /**
67
+ * Which rows the index covers: each adapter answers for its own, and no row belongs to two.
68
+ *
69
+ * Accepts: `row` — any row a table scan returns, including a foreign one and
70
+ * one whose `PK`/`SK` are not strings.
71
+ *
72
+ * Returns: the index identity, or undefined for a row no listing reaches — a
73
+ * foreign row, a payload or write row, a META row carrying no `checkpointId`.
74
+ *
75
+ * Throws: nothing. A backfill walks the whole table; one unrecognised row must
76
+ * be skipped, not fatal.
77
+ */
78
+ export declare function indexTargetOf(row: AttributeMap): IndexTarget | undefined;
79
+ /**
80
+ * A scan position, as an opaque string.
81
+ *
82
+ * Accepts: `key` — a `LastEvaluatedKey` from the scan being resumed.
83
+ *
84
+ * Returns: it base64url-encoded. Opaque to the caller: its shape is not a
85
+ * promise, which is what leaves the encoding free to change.
86
+ *
87
+ * Throws: nothing.
88
+ */
89
+ export declare function encodeScanCursor(key: AttributeMap): string;
90
+ /**
91
+ * The scan position a cursor encodes.
92
+ *
93
+ * Accepts: `cursor` — as a previous page returned it.
94
+ *
95
+ * Returns: the `ExclusiveStartKey` to resume from — always exactly `{ PK,
96
+ * SK }`, both strings, since a plain table `Scan` (no `IndexName`) never
97
+ * returns a `LastEvaluatedKey` shaped any other way.
98
+ *
99
+ * Throws: `VALIDATION` naming `cursor` for anything this tool did not
100
+ * issue — text that is not base64url, that does not decode to JSON, or that
101
+ * decodes to anything but `{ PK: string, SK: string }`: an array, an object
102
+ * missing either key, carrying an extra one, or carrying a non-string value
103
+ * for either. A cursor is fed straight back to DynamoDB as
104
+ * `ExclusiveStartKey`, so a value of the wrong shape is refused here rather
105
+ * than surfacing as a raw `ValidationException` from the service.
106
+ */
107
+ export declare function decodeScanCursor(cursor: string): AttributeMap;
108
+ /** What one pass of the backfill did, and where to resume. */
109
+ export interface BackfillResult {
110
+ /** Rows the scan evaluated. */
111
+ scanned: number;
112
+ /** Rows given index keys. */
113
+ indexed: number;
114
+ /**
115
+ * Rows this run wrote no keys for: one no listing reaches, and one whose
116
+ * write the condition refused because it already has keys or is gone.
117
+ */
118
+ skipped: number;
119
+ /**
120
+ * Opaque; absent when the table is fully walked. Pass it back to continue —
121
+ * the pass is resumable, so a large table can be backfilled in bounded runs.
122
+ */
123
+ nextCursor?: string;
124
+ }
125
+ /** What the backfill needs to walk a table. A key this type does not declare is refused. */
126
+ export interface BackfillOptions {
127
+ client: DynamoDBDocumentLike;
128
+ tableName: string;
129
+ /** Must equal the adapters' `indexShards`, or rows land on shards no listing queries. */
130
+ indexShards?: number;
131
+ /** Rows per scan page. */
132
+ pageSize?: number;
133
+ /** Stop after this many pages and return a cursor. Default: walk the whole table. */
134
+ maxPages?: number;
135
+ cursor?: string;
136
+ /** Report what would change without writing. */
137
+ dryRun?: boolean;
138
+ /**
139
+ * The full retry surface, not the adapters' narrower `RetryPolicy`:
140
+ * `onRetry` is backfill's only way to observe retries in progress, since it
141
+ * takes no `logger`.
142
+ */
143
+ retry?: RetryOptions;
144
+ signal?: AbortSignal;
145
+ }
146
+ /**
147
+ * Validate every option `backfillRecencyIndex` reads, before any of them is
148
+ * read for real.
149
+ *
150
+ * Accepts: `options` — must be an object naming only the nine keys
151
+ * {@link BackfillOptions} declares. `tableName` and `client` are required, the
152
+ * rest optional; each, when given, follows the same rule an adapter's own
153
+ * option of the same name does. `tableName` reuses the adapters' own
154
+ * `tableName` validator outright; `indexShards` is held to the adapters'
155
+ * shard cap, `MAX_INDEX_SHARDS`; and `retry` shares its numeric bounds with
156
+ * the adapters' own `retry` validator while accepting the wider surface
157
+ * backfill's `RetryOptions` needs, so a mismatch between backfill and the
158
+ * adapters it feeds cannot drift in on what a bound means.
159
+ *
160
+ * Returns: nothing: the value is kept under its declared type, and this
161
+ * checks it.
162
+ *
163
+ * Throws: `VALIDATION` naming `options.<key>` for an unknown key;
164
+ * `tableName`; `client` or `client.<member>`; `indexShards`, `pageSize` or
165
+ * `maxPages` for a non-positive-integer bound (`indexShards` is additionally
166
+ * capped); `dryRun` for a non-boolean; `retry`/`retry.<key>`; `signal`.
167
+ */
168
+ export declare function assertBackfillOptions(options: BackfillOptions): void;
@@ -0,0 +1,393 @@
1
+ "use strict";
2
+ /**
3
+ * Hides how rows written before the recency index are given its keys.
4
+ *
5
+ * The index is opt-in (record 8), so a table can hold rows from before it
6
+ * existed. An operator walks the table a page at a time, resumably, and gives
7
+ * each row the keys its adapter would have written; which rows those are is
8
+ * each adapter's own answer, asked here, and a row that gained keys since the
9
+ * scan read it is left alone.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.backfillRecencyIndex = backfillRecencyIndex;
13
+ exports.indexTargetOf = indexTargetOf;
14
+ exports.encodeScanCursor = encodeScanCursor;
15
+ exports.decodeScanCursor = decodeScanCursor;
16
+ exports.assertBackfillOptions = assertBackfillOptions;
17
+ const rows_1 = require("../checkpointer/internal/rows");
18
+ const session_1 = require("../history/internal/session");
19
+ const concurrency_1 = require("../shared/concurrency");
20
+ const idempotent_write_1 = require("../shared/dynamodb/idempotent-write");
21
+ const recency_index_1 = require("../shared/dynamodb/recency-index");
22
+ const retry_1 = require("../shared/dynamodb/retry");
23
+ const table_schema_1 = require("../shared/dynamodb/table-schema");
24
+ const boundary_1 = require("../shared/errors/boundary");
25
+ const errors_1 = require("../shared/errors/errors");
26
+ const collaborators_1 = require("../shared/validation/collaborators");
27
+ const option_shape_1 = require("../shared/validation/option-shape");
28
+ const options_1 = require("../shared/validation/options");
29
+ const primitives_1 = require("../shared/validation/primitives");
30
+ const rows_2 = require("../store/internal/rows");
31
+ /**
32
+ * The retry policy every request of one run uses: the caller's `retry`, with
33
+ * the signal that cancels the run. That is the top-level `signal` when one is
34
+ * given and `retry.signal` otherwise — the top-level one is the caller's handle
35
+ * on the whole operation, so it wins when both are set.
36
+ */
37
+ function runRetry(options) {
38
+ return { ...options.retry, signal: options.signal ?? options.retry?.signal };
39
+ }
40
+ /**
41
+ * Write one row's index keys; false when this run wrote none for it.
42
+ *
43
+ * False is an ordinary outcome and never a failure. Either the row is not one a
44
+ * listing reaches, so it needs no keys; or the conditional update was refused,
45
+ * which by the terms of that condition means the row already carries keys a
46
+ * live adapter gave it, or the row is gone. In every one of those cases this
47
+ * run has nothing to do for the row, and the row is counted as skipped.
48
+ *
49
+ * Which is why the refusal ends the row rather than the run. Both races are
50
+ * ordinary on a table that is being written to, and that is the only kind of
51
+ * table anyone runs a backfill against; a tool that stopped whenever the table
52
+ * it is migrating is in use would never finish one. Re-running is cheap and
53
+ * safe besides — the scan's own `attribute_not_exists` filter never looks at a
54
+ * row an earlier run indexed.
55
+ *
56
+ * Any other failure is rethrown and ends the run, because nothing about it says
57
+ * this row needed no writing.
58
+ */
59
+ async function indexRow(options, row, shards) {
60
+ const target = indexTargetOf(row);
61
+ if (target === undefined)
62
+ return false;
63
+ const keys = (0, recency_index_1.indexKeys)(target.tag, target.id, target.at, shards);
64
+ if (options.dryRun)
65
+ return true;
66
+ try {
67
+ await writeIndexKeys(options, row, keys);
68
+ }
69
+ catch (error) {
70
+ if (!(0, idempotent_write_1.isConditionalCheckFailed)(error))
71
+ throw error;
72
+ return false;
73
+ }
74
+ return true;
75
+ }
76
+ /** The conditional `UpdateItem` that gives one row the keys computed for it. */
77
+ async function writeIndexKeys(options, row, keys) {
78
+ await (0, retry_1.withDynamoDBRetry)((request) => options.client.update({
79
+ TableName: options.tableName,
80
+ Key: (0, table_schema_1.rowKeyOf)(row),
81
+ UpdateExpression: 'SET #gpk = :gpk, #gsk = :gsk',
82
+ ExpressionAttributeNames: { '#gpk': 'gsi1pk', '#gsk': 'gsi1sk' },
83
+ ExpressionAttributeValues: { ':gpk': keys.gsi1pk, ':gsk': keys.gsi1sk },
84
+ // Two clauses, and both are load-bearing.
85
+ //
86
+ // `attribute_not_exists(#gpk)` never overwrites keys a row already has:
87
+ // a row a running adapter wrote carries its true timestamp, and
88
+ // replacing it with the pre-index epoch would move a live row to the
89
+ // bottom of every listing.
90
+ //
91
+ // `attribute_exists(PK)` is what makes this an update rather than an
92
+ // upsert, which is what `UpdateItem` is by default. A condition naming
93
+ // only the index attribute is satisfied by a key holding *nothing at
94
+ // all*, so without it, a row deleted between the scan that found it
95
+ // and this update would be re-created as a stub carrying nothing but
96
+ // `PK`, `SK` and the two index keys — and carrying them, it would land
97
+ // in the recency index that the cross-partition listings read. The
98
+ // tool exists to give keys to rows that are already there, so nothing
99
+ // legitimate is refused.
100
+ ConditionExpression: `attribute_exists(${table_schema_1.PARTITION_KEY_ATTRIBUTE}) AND attribute_not_exists(#gpk)`,
101
+ }, request), runRetry(options));
102
+ }
103
+ /** One scan page, and the rows of it that were given keys. */
104
+ async function backfillPage(options, shards, startKey) {
105
+ const result = await (0, retry_1.withDynamoDBRetry)((request) => options.client.scan({
106
+ TableName: options.tableName,
107
+ Limit: options.pageSize ?? 100,
108
+ ExclusiveStartKey: startKey,
109
+ // Rows that already carry keys are not read into memory at all.
110
+ FilterExpression: 'attribute_not_exists(#gpk)',
111
+ ExpressionAttributeNames: { '#gpk': 'gsi1pk' },
112
+ }, request), runRetry(options));
113
+ const rows = (result.Items ?? []);
114
+ const written = await (0, concurrency_1.mapWithConcurrency)(rows, concurrency_1.DEFAULT_READ_CONCURRENCY, (row) => indexRow(options, row, shards));
115
+ return {
116
+ rows: rows.length,
117
+ indexed: written.filter(Boolean).length,
118
+ nextKey: result.LastEvaluatedKey,
119
+ };
120
+ }
121
+ /**
122
+ * Give rows written before the recency index their index keys.
123
+ *
124
+ * **Run this before setting `indexName` on any adapter.** A row without the
125
+ * keys is not in the index, so enabling the index first would make every
126
+ * pre-existing session, item and checkpoint silently vanish from the listings
127
+ * that read it — the rows are still there, and every other read still returns
128
+ * them, but a listing would not.
129
+ *
130
+ * Safe to re-run and safe to run while adapters are writing: every write is
131
+ * conditional on the row still being there and having no keys yet, so a row a
132
+ * live adapter has already indexed is left exactly as it is, and a row deleted
133
+ * after the scan found it stays deleted rather than being re-created by an
134
+ * `UpdateItem`, which upserts.
135
+ *
136
+ * `indexShards` must match what the adapters use. A mismatch puts rows on
137
+ * shards no listing queries, which looks exactly like the rows being missing.
138
+ *
139
+ * Accepts: `options` — validated in full before any read: only the keys
140
+ * `BackfillOptions` declares; `tableName`, `indexShards` and the numbers in
141
+ * `retry` by the adapters' rules; `signal` as their methods check it; a
142
+ * `client` providing `scan` and `update`. `options.pageSize` — a positive integer,
143
+ * default 100. `options.cursor` — from a previous run, to resume.
144
+ * `options.maxPages` — how far one run goes, so a large table can be
145
+ * backfilled in bounded slices. `options.indexShards` — must equal the
146
+ * adapters' setting, and has their ceiling. `options.dryRun` — a boolean.
147
+ * `options.signal` — cancels the run; `retry.signal` does so when there is no
148
+ * top-level `signal`, and the top-level one wins when both are given.
149
+ *
150
+ * Returns: how many rows were scanned, how many were given keys and how many
151
+ * were skipped — a row no listing reaches, and a row whose write the condition
152
+ * refused because the row already has keys or is gone — plus a `nextCursor`
153
+ * when the run stopped short of the end. An absent cursor means the table is
154
+ * fully backfilled.
155
+ *
156
+ * Throws: `VALIDATION` naming the offending option, before any DynamoDB
157
+ * call; `RETRY_EXHAUSTED` once a transient failure has used every attempt;
158
+ * `ABORTED` when `signal` fires, or `retry.signal` when no top-level `signal`
159
+ * is given; any other error the scan or the writes throw, wrapped with the
160
+ * code the classifier assigns — this is the function's own error boundary,
161
+ * the same as every adapter's public methods, so a caller's mistake never escapes as a bare
162
+ * exception. A refused write is none of these: it is an outcome for one row,
163
+ * reported in `skipped`.
164
+ *
165
+ * Guarantees: every write is conditional on the row still being there and
166
+ * having no keys yet, so re-running is safe, running against a live table is
167
+ * safe, a row a live adapter has already indexed is left exactly as it is, and
168
+ * a row deleted between the scan and the write is never re-created. Neither
169
+ * refusal stops the run: both mean this run has nothing to do for that row, so
170
+ * the row is counted as skipped and the walk carries on to the rest of the
171
+ * table.
172
+ */
173
+ async function backfillRecencyIndex(options) {
174
+ return (0, boundary_1.guardPublic)('backfillRecencyIndex', async () => {
175
+ assertBackfillOptions(options);
176
+ const shards = options.indexShards ?? recency_index_1.DEFAULT_INDEX_SHARDS;
177
+ let startKey = options.cursor === undefined ? undefined : decodeScanCursor(options.cursor);
178
+ let scanned = 0;
179
+ let indexed = 0;
180
+ for (let page = 1;; page++) {
181
+ const result = await backfillPage(options, shards, startKey);
182
+ scanned += result.rows;
183
+ indexed += result.indexed;
184
+ startKey = result.nextKey;
185
+ if (startKey === undefined)
186
+ break;
187
+ if (options.maxPages !== undefined && page >= options.maxPages) {
188
+ return {
189
+ scanned,
190
+ indexed,
191
+ skipped: scanned - indexed,
192
+ nextCursor: encodeScanCursor(startKey),
193
+ };
194
+ }
195
+ }
196
+ return { scanned, indexed, skipped: scanned - indexed };
197
+ });
198
+ }
199
+ /**
200
+ * Which rows the index covers: each adapter answers for its own, and no row belongs to two.
201
+ *
202
+ * Accepts: `row` — any row a table scan returns, including a foreign one and
203
+ * one whose `PK`/`SK` are not strings.
204
+ *
205
+ * Returns: the index identity, or undefined for a row no listing reaches — a
206
+ * foreign row, a payload or write row, a META row carrying no `checkpointId`.
207
+ *
208
+ * Throws: nothing. A backfill walks the whole table; one unrecognised row must
209
+ * be skipped, not fatal.
210
+ */
211
+ function indexTargetOf(row) {
212
+ return (0, rows_1.checkpointIndexTarget)(row) ?? (0, rows_2.storeIndexTarget)(row) ?? (0, session_1.sessionIndexTarget)(row);
213
+ }
214
+ /**
215
+ * A scan position, as an opaque string.
216
+ *
217
+ * Accepts: `key` — a `LastEvaluatedKey` from the scan being resumed.
218
+ *
219
+ * Returns: it base64url-encoded. Opaque to the caller: its shape is not a
220
+ * promise, which is what leaves the encoding free to change.
221
+ *
222
+ * Throws: nothing.
223
+ */
224
+ function encodeScanCursor(key) {
225
+ return Buffer.from(JSON.stringify(key), 'utf8').toString('base64url');
226
+ }
227
+ /** Whether `value` is exactly the base table's primary key: `PK` and `SK`, both strings, nothing else. */
228
+ function isTableKeyShape(value) {
229
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
230
+ return false;
231
+ const keys = Object.keys(value);
232
+ return keys.length === 2 && typeof value.PK === 'string' && typeof value.SK === 'string';
233
+ }
234
+ /**
235
+ * The scan position a cursor encodes.
236
+ *
237
+ * Accepts: `cursor` — as a previous page returned it.
238
+ *
239
+ * Returns: the `ExclusiveStartKey` to resume from — always exactly `{ PK,
240
+ * SK }`, both strings, since a plain table `Scan` (no `IndexName`) never
241
+ * returns a `LastEvaluatedKey` shaped any other way.
242
+ *
243
+ * Throws: `VALIDATION` naming `cursor` for anything this tool did not
244
+ * issue — text that is not base64url, that does not decode to JSON, or that
245
+ * decodes to anything but `{ PK: string, SK: string }`: an array, an object
246
+ * missing either key, carrying an extra one, or carrying a non-string value
247
+ * for either. A cursor is fed straight back to DynamoDB as
248
+ * `ExclusiveStartKey`, so a value of the wrong shape is refused here rather
249
+ * than surfacing as a raw `ValidationException` from the service.
250
+ */
251
+ function decodeScanCursor(cursor) {
252
+ try {
253
+ const decoded = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8'));
254
+ if (!isTableKeyShape(decoded))
255
+ throw new Error('not a scan position');
256
+ return decoded;
257
+ }
258
+ catch {
259
+ throw (0, errors_1.validationError)('cursor is not one this tool issued', 'cursor');
260
+ }
261
+ }
262
+ /**
263
+ * The keys of {@link BackfillOptions}, exhaustive in both directions —
264
+ * `allKeysOf<T>` fails to compile if this list omits or invents one.
265
+ */
266
+ const BACKFILL_KEYS = (0, option_shape_1.allKeysOf)({
267
+ client: 'client',
268
+ tableName: 'tableName',
269
+ indexShards: 'indexShards',
270
+ pageSize: 'pageSize',
271
+ maxPages: 'maxPages',
272
+ cursor: 'cursor',
273
+ dryRun: 'dryRun',
274
+ retry: 'retry',
275
+ signal: 'signal',
276
+ });
277
+ /** The `DynamoDBDocument` methods the backfill calls on an injected `client`. */
278
+ const BACKFILL_CLIENT_MEMBERS = ['scan', 'update'];
279
+ /**
280
+ * The keys of {@link RetryOptions}, exhaustive in both directions. Backfill
281
+ * accepts the full retry surface, not the adapters' narrower `RetryPolicy`
282
+ * `assertRetryPolicy` checks — `onRetry` is backfill's only way to observe
283
+ * retries, since it takes no `logger`.
284
+ *
285
+ * `deadlineAt` is the one exclusion: it is an internal per-call bound a write
286
+ * path sets on itself, not something an application names, so it stays an
287
+ * unknown key here and is refused like any other. Excluding it by `Omit`
288
+ * rather than by leaving it out keeps the list exhaustive, so a genuinely new
289
+ * option still fails to compile until it is decided on here.
290
+ */
291
+ const BACKFILL_RETRY_KEYS = (0, option_shape_1.allKeysOf)({
292
+ maxAttempts: 'maxAttempts',
293
+ baseDelayMs: 'baseDelayMs',
294
+ maxDelayMs: 'maxDelayMs',
295
+ retryableErrors: 'retryableErrors',
296
+ isRetryable: 'isRetryable',
297
+ onRetry: 'onRetry',
298
+ signal: 'signal',
299
+ rng: 'rng',
300
+ });
301
+ /**
302
+ * Validate a `backfillRecencyIndex` retry policy against the full
303
+ * {@link RetryOptions} surface.
304
+ *
305
+ * Accepts: `retry` — must be an object naming only {@link BACKFILL_RETRY_KEYS}.
306
+ * `maxAttempts`/`baseDelayMs`/`maxDelayMs` share the adapters' own bounds
307
+ * ({@link assertRetryBounds}), so backfill and the adapters it feeds cannot
308
+ * drift apart on what a legal value is. `retryableErrors`, when given, must be
309
+ * an array of strings. `isRetryable`, `onRetry` and `rng`, when given, must
310
+ * each be a function. `signal` is checked the same way the top-level
311
+ * `options.signal` is. Either one cancels the run; when both are given the
312
+ * top-level one wins, since the caller's own signal is meant to cancel the
313
+ * whole operation.
314
+ *
315
+ * Returns: nothing: the value is kept under its declared type, and this
316
+ * checks it.
317
+ *
318
+ * Throws: `VALIDATION` naming `retry`, `retry.<numeric key>`,
319
+ * `retry.retryableErrors`, `retry.isRetryable`, `retry.onRetry`, `retry.rng`
320
+ * or `retry.signal`.
321
+ */
322
+ function assertBackfillRetryOptions(retry) {
323
+ (0, option_shape_1.assertShape)(retry, BACKFILL_RETRY_KEYS, 'retry');
324
+ (0, options_1.assertRetryBounds)(retry);
325
+ if (retry.retryableErrors !== undefined) {
326
+ (0, primitives_1.assertStringArray)(retry.retryableErrors, 'retry.retryableErrors');
327
+ }
328
+ if (retry.isRetryable !== undefined && typeof retry.isRetryable !== 'function') {
329
+ throw (0, errors_1.validationError)('retry.isRetryable must be a function', 'retry.isRetryable');
330
+ }
331
+ if (retry.onRetry !== undefined && typeof retry.onRetry !== 'function') {
332
+ throw (0, errors_1.validationError)('retry.onRetry must be a function', 'retry.onRetry');
333
+ }
334
+ if (retry.rng !== undefined && typeof retry.rng !== 'function') {
335
+ throw (0, errors_1.validationError)('retry.rng must be a function', 'retry.rng');
336
+ }
337
+ (0, collaborators_1.assertSignalLike)(retry.signal, 'retry.signal');
338
+ }
339
+ /**
340
+ * Reject a non-integer positive bound, `undefined` left to its own default.
341
+ *
342
+ * Accepts: `value` — `options.pageSize`, `options.maxPages` or
343
+ * `options.indexShards`, as the caller gave it. `field` — what the error
344
+ * names. `max` — an upper bound, when one applies.
345
+ *
346
+ * Returns: nothing: the value is kept under its declared type, and this
347
+ * checks it.
348
+ *
349
+ * Throws: `VALIDATION` naming `field` — including for `null`, which is a
350
+ * caller's explicit (wrong) value, not "unset", so it is refused rather than
351
+ * silently falling through to the default the way `??` alone would.
352
+ */
353
+ function assertPositiveBound(value, field, max) {
354
+ if (value === undefined)
355
+ return;
356
+ (0, primitives_1.assertInteger)(value, field, max === undefined ? { min: 1 } : { min: 1, max });
357
+ }
358
+ /**
359
+ * Validate every option `backfillRecencyIndex` reads, before any of them is
360
+ * read for real.
361
+ *
362
+ * Accepts: `options` — must be an object naming only the nine keys
363
+ * {@link BackfillOptions} declares. `tableName` and `client` are required, the
364
+ * rest optional; each, when given, follows the same rule an adapter's own
365
+ * option of the same name does. `tableName` reuses the adapters' own
366
+ * `tableName` validator outright; `indexShards` is held to the adapters'
367
+ * shard cap, `MAX_INDEX_SHARDS`; and `retry` shares its numeric bounds with
368
+ * the adapters' own `retry` validator while accepting the wider surface
369
+ * backfill's `RetryOptions` needs, so a mismatch between backfill and the
370
+ * adapters it feeds cannot drift in on what a bound means.
371
+ *
372
+ * Returns: nothing: the value is kept under its declared type, and this
373
+ * checks it.
374
+ *
375
+ * Throws: `VALIDATION` naming `options.<key>` for an unknown key;
376
+ * `tableName`; `client` or `client.<member>`; `indexShards`, `pageSize` or
377
+ * `maxPages` for a non-positive-integer bound (`indexShards` is additionally
378
+ * capped); `dryRun` for a non-boolean; `retry`/`retry.<key>`; `signal`.
379
+ */
380
+ function assertBackfillOptions(options) {
381
+ (0, option_shape_1.assertShape)(options, BACKFILL_KEYS, 'options');
382
+ (0, options_1.assertTableName)(options.tableName);
383
+ (0, collaborators_1.assertMembers)(options.client, BACKFILL_CLIENT_MEMBERS, 'client');
384
+ assertPositiveBound(options.indexShards, 'indexShards', recency_index_1.MAX_INDEX_SHARDS);
385
+ assertPositiveBound(options.pageSize, 'pageSize');
386
+ assertPositiveBound(options.maxPages, 'maxPages');
387
+ if (options.dryRun !== undefined && typeof options.dryRun !== 'boolean') {
388
+ throw (0, errors_1.validationError)('dryRun must be a boolean', 'dryRun');
389
+ }
390
+ if (options.retry !== undefined)
391
+ assertBackfillRetryOptions(options.retry);
392
+ (0, collaborators_1.assertSignalLike)(options.signal);
393
+ }
@@ -1,9 +1,50 @@
1
+ /**
2
+ * Hides what deleting a thread means for the checkpointer's rows.
3
+ *
4
+ * The partition delete itself is shared; what is decided here is which rows of
5
+ * a thread's partition are the checkpointer's to remove, which objects each one
6
+ * names, and which write id pins each delete, so a checkpoint or a pending
7
+ * write rewritten after the read is left alone. A caller names a thread and
8
+ * never learns the row kinds, their sort keys or how a refusal is counted.
9
+ */
1
10
  import type { CheckpointerContext } from '../internal/setup';
2
11
  /**
3
- * Delete every checkpoint, payload, and write for a thread (all share the
4
- * thread's partition), best-effort deleting any offloaded S3 objects. Rows
5
- * this adapter does not own are left in place and logged, so a shared-table
6
- * partition holding a foreign row is never collaterally wiped.
12
+ * Delete exactly the checkpoint, payload and write rows of one thread that the
13
+ * partition read observed.
14
+ *
15
+ * Accepts: `threadId` — validated like every identifier. `options.signal` —
16
+ * stops the read between pages.
17
+ *
18
+ * Returns: nothing. Deleting a thread that does not exist is not an error:
19
+ * there is simply nothing in the partition.
20
+ *
21
+ * Throws: `VALIDATION` for a malformed `threadId`;
22
+ * `BATCH_WRITE_INCOMPLETE` when a row's delete fails, carrying what did
23
+ * succeed; `ABORTED` when the signal fires, whether between pages or during
24
+ * a row's delete — a cancel is reported as a cancel and never as an incomplete
25
+ * delete, and no further row is issued after it. A refused row is **not** one of
26
+ * those failures and raises nothing: the pin turned it away because it was
27
+ * rewritten after the read, and deleting it would erase a write already
28
+ * acknowledged to its author and release the object that write uploaded, so
29
+ * leaving it is the safe answer rather than a degraded one. The error's two
30
+ * counts are **rows**, not batches — rows deleted and rows attempted, summed
31
+ * across every flush of the pass, with `details.succeededCount` repeating the first
32
+ * and `details.failedChunks` holding each failing row's own error — and its message says so,
33
+ * because a pass that sends one request per row is not a batch that did not
34
+ * drain. Refused rows are in neither count; they are reported at `warn` with
35
+ * their sort keys and counted as skipped. The remedy for a refusal is the same
36
+ * as for a row written after the read: re-run once the thread is quiescent.
37
+ *
38
+ * Guarantees: a row this adapter did not write is left in place and logged, so
39
+ * a shared-table partition is never collaterally wiped. A row written or
40
+ * rewritten after the read is left in place and reported too: every delete is
41
+ * pinned on the id of the write that produced the row it names, so a checkpoint
42
+ * re-put while this runs keeps both its rows and the objects they name, and its
43
+ * pending writes are then left alone with them. A row written before that id
44
+ * existed carries none and is deleted as it always was. A row written at a key
45
+ * the read never saw still survives the pass, which is why the thread should be
46
+ * quiescent.
7
47
  */
8
- export declare function deleteThread(context: CheckpointerContext, threadId: string): Promise<void>;
9
- //# sourceMappingURL=delete-thread.d.ts.map
48
+ export declare function deleteThread(context: CheckpointerContext, threadId: string, options?: {
49
+ signal?: AbortSignal;
50
+ }): Promise<void>;