@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,593 @@
1
+ "use strict";
2
+ /**
3
+ * Hides how a row write whose outcome matters is issued and settled.
4
+ *
5
+ * A write can lose its acknowledgement, be re-sent by the retry layer, race a
6
+ * concurrent writer, or leave an S3 object that only its row names. Three
7
+ * things answer that, and they are decided together here: a guard that admits
8
+ * the write only while the row still holds what the caller observed; a client
9
+ * request token, drawn once per logical write with a deadline inside the
10
+ * window the service honours it for, so a re-send of a committed write is
11
+ * discarded (record 6); and a strongly consistent read-back that turns a write
12
+ * whose outcome was lost into one of three verdicts. Whether a write needs the
13
+ * token is the payload descriptor's question, answered here once.
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.WRITE_ID_ATTRIBUTE = exports.OVERWRITE_CAS_MAX_ATTEMPTS = void 0;
17
+ exports.referencesS3Object = referencesS3Object;
18
+ exports.transactIdempotently = transactIdempotently;
19
+ exports.putIdempotently = putIdempotently;
20
+ exports.deleteIdempotently = deleteIdempotently;
21
+ exports.commitRow = commitRow;
22
+ exports.revisionGuard = revisionGuard;
23
+ exports.writeIdGuard = writeIdGuard;
24
+ exports.isConditionalCheckFailed = isConditionalCheckFailed;
25
+ exports.rejectedRow = rejectedRow;
26
+ exports.offloadedKey = offloadedKey;
27
+ exports.identityOf = identityOf;
28
+ exports.verdictFor = verdictFor;
29
+ exports.readRow = readRow;
30
+ exports.verifyRow = verifyRow;
31
+ exports.isRowAbsent = isRowAbsent;
32
+ const node_crypto_1 = require("node:crypto");
33
+ const util_dynamodb_1 = require("@aws-sdk/util-dynamodb");
34
+ const clock_1 = require("../clock");
35
+ const codec_1 = require("../codec/codec");
36
+ const classify_1 = require("../errors/classify");
37
+ const error_code_1 = require("../errors/error-code");
38
+ const cancellation_1 = require("./cancellation");
39
+ const retry_1 = require("./retry");
40
+ const table_schema_1 = require("./table-schema");
41
+ /**
42
+ * Whether a payload descriptor names an S3 object, and so whether the write
43
+ * carrying it can strand one.
44
+ *
45
+ * An inline payload references nothing outside its own row: a re-landed copy
46
+ * of such a write is an ordinary last-write-wins outcome, not a lost object.
47
+ * Only the offloaded write is worth the extra write capacity a transaction
48
+ * costs, which is why the question is asked of the descriptor rather than of
49
+ * the adapter — an adapter with an offloader configured still writes inline
50
+ * whenever the payload is under its threshold.
51
+ *
52
+ * Accepts: `descriptor` — a full payload descriptor, or the projection a
53
+ * pre-write read returns without the inline bytes.
54
+ *
55
+ * Returns: true when the payload was offloaded to S3.
56
+ *
57
+ * Throws: nothing.
58
+ */
59
+ function referencesS3Object(descriptor) {
60
+ return descriptor.location === codec_1.PayloadLocation.S3;
61
+ }
62
+ /**
63
+ * Commit `actions` as one
64
+ * {@link https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html | TransactWriteItems}
65
+ * under a client request token, so a re-send DynamoDB already applied lands as
66
+ * a no-op instead of as a second write.
67
+ *
68
+ * A write that offloads its payload uploads the object first and commits the
69
+ * row second. Lose the row's acknowledgement and the retry can commit it
70
+ * twice; the cleanup that follows then releases an object the other attempt's
71
+ * row still names, leaving a live row pointing at nothing. A delete has the
72
+ * mirror problem: its retry, re-evaluated rather than deduplicated, meets a row
73
+ * a competitor wrote after the first attempt landed and erases it. `PutItem`
74
+ * and `DeleteItem` take no token and cannot be made to; a one-item transaction
75
+ * can, and inside the service's 10-minute window the re-send is discarded
76
+ * rather than applied.
77
+ *
78
+ * **What the token guarantees, and what it does not.** A write whose first
79
+ * attempt **committed** is applied exactly once, at that moment — so a later
80
+ * writer supersedes it normally and a concurrent delete stands. A write whose
81
+ * first attempt was **rejected by its condition** carries no idempotency at
82
+ * all: a cancelled transaction never completes, so DynamoDB caches no result
83
+ * for its token, and a retry with the same token is a **fresh evaluation**
84
+ * against the table as it stands at retry time. The short version — "a retried
85
+ * write lands once" — is therefore false, and every caller that reasons about a
86
+ * rejection must reason about the table, not about the token.
87
+ *
88
+ * Two readings that sentence must not be given, because the shorter version of
89
+ * it invites both. It is about writes **this library sends with a token**: it
90
+ * says nothing about a `BatchWriteItem`, which can carry no token at all, and
91
+ * nothing about a first request that was already wrong, which no token can
92
+ * help — a token makes a *re-sent* request harmless and has nothing to say
93
+ * about a race that needs no retry to go wrong. And "exactly once" is about
94
+ * **application, not ordering**: a cancelled-then-retried write applies later
95
+ * than its first attempt, or not at all. What a cancellation does still
96
+ * reserve is the token's *parameters*, which is why a re-pin must draw a fresh
97
+ * one rather than re-present this one.
98
+ *
99
+ * **Stable across a re-send, fresh across a re-pin.** The input — token
100
+ * included — is built once here, outside the retry closure, so every attempt
101
+ * of one budget re-sends the identical request and the token deduplicates it.
102
+ * A compare-and-swap that loses and re-pins calls this again and draws a new
103
+ * token, which is required rather than merely tidy: the re-pinned request
104
+ * carries a different `ConditionExpression`, and the same token presented with
105
+ * changed parameters inside the window is refused with
106
+ * `IdempotentParameterMismatchException` — a name that appears in no retry
107
+ * list and in no handler in this package, so reusing a token would surface a
108
+ * raw SDK error to a caller. That refusal is only observable against real
109
+ * DynamoDB: the local image does not reserve a cancelled token's parameters
110
+ * and simply re-evaluates the changed body, so the unit and integration tiers
111
+ * can assert only that two re-pins carry different tokens, and the refusal
112
+ * itself belongs to the tier that runs against AWS.
113
+ *
114
+ * **At most one guarded action, and only ever as many actions as must land
115
+ * together.** A cancellation is read as a guard rejection only while exactly
116
+ * one cause remains once the items along for the ride are set aside, so a
117
+ * second *guarded* action whose condition fails in the same race would turn
118
+ * that race into an unrecognised non-retryable error — which is exactly what a
119
+ * competing writer of the same checkpoint id would produce, since it fails
120
+ * both rows at once. Every row-at-a-time caller here
121
+ * passes a single action for a second reason as well: a transaction cancels
122
+ * whole, so one item per transaction keeps each write's outcome independent of
123
+ * its neighbours', which is what the fan-out writers rely on. More than one
124
+ * action is for the callers whose rows are atomic by contract and carry no
125
+ * condition between them.
126
+ *
127
+ * Accepts: `deps` — the adapter's client, table and retry policy. `actions` —
128
+ * the `Put`, `Delete`, `Update` or `ConditionCheck` entries to commit
129
+ * together, captured by reference and re-sent unchanged on every attempt of
130
+ * the budget, so a caller must mutate neither the array nor an entry of it while this call is in flight.
131
+ * `options.signal` — aborts between attempts. `options.rng` — the jitter
132
+ * source, replacing the default one for a caller whose tests need the backoff
133
+ * to take no time. `options.minAttempts` — the fewest attempts the write is
134
+ * given: the budget is the larger of it and the adapter's own `maxAttempts`,
135
+ * so a caller policy may raise it, never lower it. Without `rng` and
136
+ * `minAttempts` the retry receives the adapter's policy, the signal and the
137
+ * deadline, and nothing else.
138
+ *
139
+ * Returns: nothing. The transaction committed, or it threw.
140
+ *
141
+ * Throws: whatever the transaction throws.
142
+ *
143
+ * Guarantees: the retrying stops while the token is still honoured. The budget
144
+ * carries a deadline of {@link MAX_WRITE_LIFETIME_MS} from now, half the
145
+ * window the service deduplicates over, so the wait that would carry this
146
+ * write past it is never started.
147
+ *
148
+ * Nothing in the token enforces that window — the service honours a token for
149
+ * `TOKEN_IDEMPOTENCY_WINDOW_MS` whatever the caller's policy says, and a
150
+ * re-send arriving after it closes is a new request that is applied. The
151
+ * deadline is what keeps the budget inside it, and it bounds only the waits
152
+ * *between* attempts: it is tested before each backoff and cannot shorten an
153
+ * attempt already in flight. On a client this library builds the per-attempt
154
+ * `DEFAULT_REQUEST_TIMEOUT_MS` bounds that attempt as well; on an **injected**
155
+ * client, which is used exactly as given and may carry no request timeout at
156
+ * all, a single hung request can still carry the budget past the window, and
157
+ * nothing here prevents it.
158
+ *
159
+ * That deadline is spread onto a copy of the policy and never assigned onto
160
+ * it: `retryFor` hands back the adapter's own options object when there is no
161
+ * signal, and stamping a deadline onto that object would bound every later
162
+ * call of the same adapter by this call's clock.
163
+ */
164
+ async function transactIdempotently(deps, actions, options = {}) {
165
+ const input = { TransactItems: actions, ClientRequestToken: (0, node_crypto_1.randomUUID)() };
166
+ const deadlineAt = (0, clock_1.nowMs)() + retry_1.MAX_WRITE_LIFETIME_MS;
167
+ await (0, retry_1.withDynamoDBRetry)((request) => deps.client.transactWrite(input, request), {
168
+ ...(0, retry_1.retryFor)(deps, options.signal),
169
+ ...(options.minAttempts === undefined
170
+ ? {}
171
+ : { maxAttempts: Math.max(options.minAttempts, deps.retry?.maxAttempts ?? 0) }),
172
+ ...(options.rng === undefined ? {} : { rng: options.rng }),
173
+ deadlineAt,
174
+ });
175
+ }
176
+ /**
177
+ * Commit one row under a request token; see {@link transactIdempotently} for
178
+ * why the write takes a transaction's shape and what the token buys.
179
+ *
180
+ * Accepts: `deps` — the adapter's client, table and retry policy. `item` — the
181
+ * row to commit. It is captured by reference and re-sent unchanged on every
182
+ * attempt of the budget, so a caller must not mutate it while this call is in
183
+ * flight: the re-send would carry the same token with different parameters,
184
+ * which the service refuses with `IdempotentParameterMismatchException`.
185
+ * `guard` — the condition fragments from `revisionGuard`, or a caller's own;
186
+ * omitted writes unconditionally, which is the case a token helps most, since
187
+ * nothing else stops a re-send from landing. `signal` — aborts between
188
+ * attempts.
189
+ *
190
+ * Returns: nothing. The write committed, or it threw.
191
+ *
192
+ * Throws: whatever the transaction throws. A guard rejection now arrives as a
193
+ * `TransactionCanceledException` whose single reason is `ConditionalCheckFailed`
194
+ * rather than as a `ConditionalCheckFailedException`; both answer
195
+ * `isConditionalCheckFailed` and both carry the rejected row to
196
+ * `rejectedRow`, so a caller reads them the same way. A spent budget
197
+ * throws `RETRY_EXHAUSTED` as any other call does.
198
+ */
199
+ async function putIdempotently(deps, item, guard, signal) {
200
+ await transactIdempotently(deps, [{ Put: { TableName: deps.tableName, Item: item, ...guard } }], {
201
+ signal,
202
+ });
203
+ }
204
+ /**
205
+ * Remove one row under a request token; see {@link transactIdempotently} for
206
+ * why the delete takes a transaction's shape and what the token buys.
207
+ *
208
+ * It buys more here than a put's token does. An unconditional `DeleteItem`
209
+ * cannot be turned away, so a retry that arrives after the first attempt
210
+ * already committed removes whatever a competitor has written since. Under a
211
+ * token that replay is answered from the idempotency cache and never reaches
212
+ * the row, which is what makes a condition failure *informative*: it now
213
+ * proves a genuine race rather than possibly reporting this call's own
214
+ * landed attempt.
215
+ *
216
+ * Accepts: `deps` — the adapter's client, table and retry policy. `key` — the
217
+ * row's key, captured by reference and re-sent unchanged for the same reason a
218
+ * put's item is. `guard` — the condition fragments pinning what the caller
219
+ * observed; omitted deletes unconditionally. `signal` — aborts between
220
+ * attempts.
221
+ *
222
+ * Returns: nothing. The delete committed, or it threw.
223
+ *
224
+ * Throws: as {@link putIdempotently} does. A rejection carries the row that
225
+ * turned it away only while there is one — an absent row cancels with no
226
+ * `Item` at all, which is how a caller tells "someone rewrote it" from "it was
227
+ * already gone". **That reading is only sound while the guard asks for the
228
+ * row.** Every guard `revisionGuard` builds carries
229
+ * `ReturnValuesOnConditionCheckFailure: 'ALL_OLD'`; a caller passing its own
230
+ * guard without it, or no guard at all, gets an empty rejection for a row that
231
+ * is very much still there — and a caller that then releases what that row
232
+ * names has deleted an object a live row points at.
233
+ */
234
+ async function deleteIdempotently(deps, key, guard, signal) {
235
+ await transactIdempotently(deps, [{ Delete: { TableName: deps.tableName, Key: key, ...guard } }], { signal });
236
+ }
237
+ /**
238
+ * Commit one row: as a tokened one-item transaction when it names an S3
239
+ * object, and as a plain `PutItem` otherwise.
240
+ *
241
+ * The descriptor decides, not the adapter. An adapter with an offloader still
242
+ * writes inline whenever a payload is under its threshold, and a row that names
243
+ * no object has nothing a re-sent write could strand, so a transaction would
244
+ * charge twice the write capacity to buy nothing.
245
+ *
246
+ * Accepts: `row` — the item to write. `payload` — its payload descriptor, which
247
+ * decides the shape. `options.guard` — the condition the write carries, if any.
248
+ * `options.signal` — cancels the retries.
249
+ *
250
+ * Returns: nothing, once the write committed.
251
+ *
252
+ * Throws: the guard's rejection — a rejection that `isConditionalCheckFailed`
253
+ * answers true for, with the row that turned the write away readable through
254
+ * `rejectedRow`; whatever the write throws once its retries are spent.
255
+ */
256
+ async function commitRow(deps, row, payload, options = {}) {
257
+ if (referencesS3Object(payload)) {
258
+ await putIdempotently(deps, row, options.guard, options.signal);
259
+ return;
260
+ }
261
+ await (0, retry_1.withDynamoDBRetry)((request) => deps.client.put({ TableName: deps.tableName, Item: row, ...options.guard }, request), (0, retry_1.retryFor)(deps, options.signal));
262
+ }
263
+ /**
264
+ * Compare-and-swap attempts before a caller gives up and overwrites
265
+ * unconditionally. Kept small on purpose: DynamoDB charges write capacity for a
266
+ * *failed* conditional write too, sized on the existing item, so an aggressive
267
+ * loop turns contention into cost. Three attempts settle every realistic race,
268
+ * and the fallback is exactly the pre-0.9.0 behaviour rather than an error.
269
+ */
270
+ exports.OVERWRITE_CAS_MAX_ATTEMPTS = 3;
271
+ const RETURN_REJECTED_ROW = { ReturnValuesOnConditionCheckFailure: 'ALL_OLD' };
272
+ /**
273
+ * Build the condition admitting a write only while the row still holds the
274
+ * revision this caller observed.
275
+ *
276
+ * Without it, two concurrent overwrites both read the same previous payload
277
+ * descriptor, both commit their own nonced upload, and both delete that same
278
+ * previous object — leaving the loser's upload orphaned with nothing left
279
+ * recording that it ever existed. A post-commit read-back cannot repair that,
280
+ * because neither writer can learn of an object it never saw; only refusing the
281
+ * second write until it re-reads can.
282
+ *
283
+ * A row with no revision attribute was written before 0.9.0. Pinning its
284
+ * *absence* is what makes the swap correct across an upgrade: the first writer
285
+ * to touch such a row stamps one, and any racer still holding the pre-upgrade
286
+ * observation is turned away.
287
+ *
288
+ * Accepts: `attribute` — the revision attribute's name, since the checkpointer
289
+ * reuses its `writeGroup` rather than carrying a second one. `observed` — the
290
+ * three states a caller can have seen: no row, a row with no revision, a row
291
+ * with one.
292
+ *
293
+ * Returns: the condition fragments for a `PutCommand`, one per state —
294
+ * `attribute_not_exists(PK)`, `attribute_not_exists(<attribute>)`, and
295
+ * equality. Every one asks DynamoDB to attach the existing row to a rejection,
296
+ * so a swap that loses re-pins from the exception instead of spending a second
297
+ * strongly-consistent read.
298
+ *
299
+ * Throws: nothing.
300
+ *
301
+ * Guarantees: it pins the revision the caller observed — a value, its absence,
302
+ * or the row's own absence — and nothing else about the row. A revision is
303
+ * drawn afresh by every write that replaces the row (`randomUUID()` for a
304
+ * store record, the call's own `writeGroup` for a special row) and nothing
305
+ * restores a spent one, so a **satisfied** guard proves that nothing replaced
306
+ * the row between the caller's read and this write: the row overwritten is the
307
+ * row observed, still naming the descriptor the caller read off it. That is
308
+ * what makes it safe to release the payload this write superseded — the
309
+ * caller is holding the descriptor the row really named, not a stale copy of
310
+ * one a racer has already replaced and released. An update that leaves the
311
+ * revision alone can still have touched the row in between — the recency-index
312
+ * backfill is the one such write in this package, and it adds index keys and
313
+ * nothing else — so what the guard pins is the row's identity, not every byte
314
+ * of it.
315
+ *
316
+ * A **rejected** guard proves the mirror and no more: the row is not the one
317
+ * observed. It is never evidence that a competitor won, because a write whose
318
+ * acknowledgement was lost can be turned away by the row it committed itself
319
+ * — see {@link isConditionalCheckFailed} — and it carries no idempotency for a
320
+ * retry either, since a rejected attempt commits nothing for a token to be
321
+ * answered from.
322
+ */
323
+ function revisionGuard(attribute, observed) {
324
+ if (!observed.exists)
325
+ return {
326
+ ...RETURN_REJECTED_ROW,
327
+ ConditionExpression: `attribute_not_exists(${table_schema_1.PARTITION_KEY_ATTRIBUTE})`,
328
+ };
329
+ if (observed.revision === undefined) {
330
+ return {
331
+ ...RETURN_REJECTED_ROW,
332
+ ConditionExpression: 'attribute_not_exists(#rev)',
333
+ ExpressionAttributeNames: { '#rev': attribute },
334
+ };
335
+ }
336
+ return {
337
+ ...RETURN_REJECTED_ROW,
338
+ ConditionExpression: '#rev = :rev',
339
+ ExpressionAttributeNames: { '#rev': attribute },
340
+ ExpressionAttributeValues: { ':rev': observed.revision },
341
+ };
342
+ }
343
+ /** The field a payload descriptor carries the id of the write that produced it in. */
344
+ exports.WRITE_ID_ATTRIBUTE = 'writeId';
345
+ /**
346
+ * Build the condition admitting a delete only while the row still carries the
347
+ * per-write id the reader observed on it.
348
+ *
349
+ * A partition-wide delete reads a partition and then deletes what it saw. A row
350
+ * rewritten in between was acknowledged to its writer and is erased anyway, and
351
+ * the object it named is released — which this turns into a refusal the pass
352
+ * reports instead. The id is the write's own, never recomputed from the row's
353
+ * state, so nothing can restore it and no second writer can arrive at it.
354
+ *
355
+ * Accepts: `attribute` — the attribute the id lives on, top-level for a row
356
+ * that carries one (a pending write's `writeGroup`, a session row's own id) and
357
+ * the payload attribute otherwise. `id` — the id the read observed; a row
358
+ * observed *without* one is deleted unconditionally rather than pinned, so this
359
+ * is never called for it. `field` — the field inside the attribute, which turns
360
+ * the condition into a document path over a descriptor; omitted for a
361
+ * top-level pin.
362
+ *
363
+ * Returns: the condition fragments for a `DeleteCommand`, asking DynamoDB to
364
+ * attach the existing row to a rejection so the refusal can be told from a row
365
+ * that was already gone with no second read.
366
+ *
367
+ * Throws: nothing.
368
+ *
369
+ * Guarantees: one equality and nothing else. A document path over an attribute
370
+ * that is absent, or present without the field, evaluates false rather than
371
+ * failing the request, so one shape covers an offloaded row, an inline one and
372
+ * a row a racer has rewritten into either.
373
+ *
374
+ * What a satisfied guard proves is the delete's counterpart of
375
+ * {@link revisionGuard}'s: the row removed is the row the partition read saw,
376
+ * not a replacement a later write left at the same key — which is what makes
377
+ * the object that read recorded against it the right one to release. A
378
+ * rejection means the row now carries some other write's id, and this pass
379
+ * leaves it in place and reports it rather than re-pinning, because a row it
380
+ * never read is not its to delete.
381
+ */
382
+ function writeIdGuard(attribute, id, field) {
383
+ const names = { '#pin': attribute };
384
+ if (field !== undefined)
385
+ names['#field'] = field;
386
+ return {
387
+ ...RETURN_REJECTED_ROW,
388
+ ConditionExpression: field === undefined ? '#pin = :pin' : '#pin.#field = :pin',
389
+ ExpressionAttributeNames: names,
390
+ ExpressionAttributeValues: { ':pin': id },
391
+ };
392
+ }
393
+ /**
394
+ * Whether a conditional write was turned away by its guard.
395
+ *
396
+ * The same rejection has two shapes, because a `PutItem` reports it as an
397
+ * exception of its own while a `TransactWriteItems` reports it as one
398
+ * cancellation reason among one per item. Both are the same event to a caller,
399
+ * so both answer true here and neither is a caller's business to tell apart.
400
+ *
401
+ * Accepts: `error` — any error; the exception's name and, for a cancelled
402
+ * transaction, its reasons are read.
403
+ *
404
+ * Returns: true for `ConditionalCheckFailedException`, and for a cancellation
405
+ * whose one cause is a `ConditionalCheckFailed` reason, as the classifier
406
+ * decides both.
407
+ *
408
+ * Throws: nothing.
409
+ *
410
+ * Guarantees: **not** evidence that a competitor won. A `PutCommand` retried
411
+ * after its response was lost can re-hit the row it wrote itself and fail
412
+ * identically, and the two are indistinguishable from the rejection alone —
413
+ * which is why every caller reads the row back before deleting anything.
414
+ */
415
+ function isConditionalCheckFailed(error) {
416
+ return (0, classify_1.classifyAwsError)(error) === error_code_1.ErrorCode.CONDITION_CONFLICT;
417
+ }
418
+ /**
419
+ * The row that turned a conditional write away, when DynamoDB attached it
420
+ * (`ReturnValuesOnConditionCheckFailure: 'ALL_OLD'`). Verified against real
421
+ * DynamoDB: the document client does not unmarshall an *error* payload the way
422
+ * it unmarshalls a response, so the item arrives in raw AttributeValue form and
423
+ * is unmarshalled here. Undefined when the rejection carries no item — the row
424
+ * was deleted between the observation and the write — in which case the caller
425
+ * falls back to a read.
426
+ *
427
+ * A cancelled transaction attaches the same row to the cancellation reason of
428
+ * the item whose condition failed, rather than to the error itself, and leaves
429
+ * it in the same raw form — so there is one place more to look and still one
430
+ * unmarshalling.
431
+ *
432
+ * Accepts: `error` — any error; only a rejection from a guard built by
433
+ * {@link revisionGuard} carries the item.
434
+ *
435
+ * Returns: the row as a plain document, or undefined.
436
+ *
437
+ * Throws: whatever `unmarshall` rejects for an item that is not in
438
+ * AttributeValue form.
439
+ */
440
+ function rejectedRow(error) {
441
+ const attached = error.Item;
442
+ const raw = attached ?? (0, cancellation_1.conditionalCheckFailure)(error)?.Item;
443
+ return raw === undefined ? undefined : (0, util_dynamodb_1.unmarshall)(raw);
444
+ }
445
+ /**
446
+ * The S3 key an offloaded descriptor points at.
447
+ *
448
+ * Accepts: any descriptor, or none.
449
+ *
450
+ * Returns: the key, or undefined for an inline or absent payload — "this row
451
+ * names no object", which is what a caller comparing two writes needs.
452
+ *
453
+ * Throws: nothing.
454
+ */
455
+ function offloadedKey(descriptor) {
456
+ return descriptor?.location === codec_1.PayloadLocation.S3 ? descriptor.s3Key : undefined;
457
+ }
458
+ /**
459
+ * The identity `row` carries under `probe`.
460
+ *
461
+ * Accepts: `probe.kind` — `'attribute'` reads the identity straight out of the
462
+ * attribute, `'descriptor'` reads the S3 key of the descriptor stored there.
463
+ * `row` — as read, or undefined when there is none.
464
+ *
465
+ * Returns: the identity, or undefined when the row is absent or carries none.
466
+ *
467
+ * Throws: nothing.
468
+ */
469
+ function identityOf(probe, row) {
470
+ const stored = row?.[probe.attribute];
471
+ if (probe.kind === 'attribute')
472
+ return stored;
473
+ return offloadedKey(stored);
474
+ }
475
+ /**
476
+ * The verdict for a row already in hand.
477
+ *
478
+ * Accepts: `row` — the row a conditional-write rejection carried back, which
479
+ * makes this verdict cost no read at all.
480
+ *
481
+ * Returns: `'landed'` when the row's identity is this write's, `'not-landed'`
482
+ * otherwise. Never `'unverified'`: the row was seen.
483
+ *
484
+ * Throws: nothing.
485
+ */
486
+ function verdictFor(probe, row) {
487
+ return identityOf(probe, row) === probe.expected ? 'landed' : 'not-landed';
488
+ }
489
+ /**
490
+ * The projection for `read`, with no attribute name left unused, which DynamoDB
491
+ * also refuses.
492
+ */
493
+ function projectionOf(read) {
494
+ const nested = read.descriptors ?? [];
495
+ const whole = [read.attribute, ...(read.also ?? [])].filter((name) => !nested.includes(name));
496
+ const names = {};
497
+ const paths = [];
498
+ whole.forEach((name, index) => {
499
+ names[`#a${index}`] = name;
500
+ paths.push(`#a${index}`);
501
+ });
502
+ nested.forEach((name, index) => {
503
+ names[`#d${index}`] = name;
504
+ paths.push(`#d${index}.#loc`, `#d${index}.#s3k`);
505
+ });
506
+ if (nested.length > 0)
507
+ Object.assign(names, { '#loc': 'location', '#s3k': 's3Key' });
508
+ return { expression: paths.join(', '), names };
509
+ }
510
+ /**
511
+ * Read the row a probe names, strongly consistently.
512
+ *
513
+ * Accepts: `read.attribute` — always projected. `read.also` — further
514
+ * attributes, for a caller that needs the row itself back rather than only its
515
+ * identity. `read.descriptors` — descriptor attributes, projected as their
516
+ * `location` and `s3Key` only; each still comes back under its own name, as a
517
+ * map holding those two.
518
+ *
519
+ * Returns: the projected row, or undefined when there is none.
520
+ *
521
+ * Throws: the underlying error, which {@link verifyRow} turns into a verdict
522
+ * and a caller that wants the cause keeps. The two are separate functions
523
+ * because a synthetic error built from a caught one lost the original cause.
524
+ *
525
+ * Guarantees: strongly consistent — a read that may lag is no evidence at all
526
+ * about a write that may have landed.
527
+ */
528
+ async function readRow(deps, read) {
529
+ const { expression, names } = projectionOf(read);
530
+ const result = await (0, retry_1.withDynamoDBRetry)((request) => deps.client.get({
531
+ TableName: deps.tableName,
532
+ Key: read.key,
533
+ ConsistentRead: true,
534
+ ProjectionExpression: expression,
535
+ ExpressionAttributeNames: names,
536
+ }, request), deps.retry);
537
+ return result.Item;
538
+ }
539
+ /**
540
+ * Read one row back to establish what an ambiguous write actually did.
541
+ *
542
+ * No failure is proof of a non-commit: `withDynamoDBRetry` re-issues a write
543
+ * whose response was lost, and those re-issues can time out at the transport
544
+ * without reaching DynamoDB, so the budget is spent on a `RETRY_EXHAUSTED` error
545
+ * while the row is live. Every caller that is about to delete something on the
546
+ * strength of a failure reads the row first, through here.
547
+ *
548
+ * Accepts: `probe.expected` — the identity that would prove the write landed.
549
+ * `undefined` means there is nothing at stake — a record with no revision, a
550
+ * checkpoint with nothing offloaded — and no read is spent.
551
+ *
552
+ * Returns: the verdict and, when one was read, the row. See
553
+ * {@link WriteVerdict} for what each answer licenses the caller to do.
554
+ *
555
+ * Throws: nothing. A failed read is the `'unverified'` answer, not an error:
556
+ * the caller is already handling a failure and needs a decision, not a second
557
+ * one.
558
+ */
559
+ async function verifyRow(deps, probe) {
560
+ if (probe.expected === undefined)
561
+ return { verdict: 'not-landed' };
562
+ try {
563
+ const row = await readRow(deps, probe);
564
+ return { verdict: verdictFor(probe, row), row };
565
+ }
566
+ catch {
567
+ return { verdict: 'unverified' };
568
+ }
569
+ }
570
+ /**
571
+ * Whether a row is confirmed absent right now — what resolves an ambiguous
572
+ * retry-exhausted *delete*, where the delete may well have landed server-side
573
+ * and only its acknowledgement was lost. Only the partition key is projected:
574
+ * existence is the whole question.
575
+ *
576
+ * Accepts: `key` — the row's.
577
+ *
578
+ * Returns: `true` only when a strongly consistent read found no row; `false`
579
+ * when it found one or when the read itself failed, because a failed read
580
+ * confirms nothing — "not confirmed", never "still there": the caller only
581
+ * rethrows on `false`, so nothing is deleted on the strength of a read that
582
+ * did not happen.
583
+ *
584
+ * Throws: nothing.
585
+ */
586
+ async function isRowAbsent(deps, key) {
587
+ try {
588
+ return (await readRow(deps, { key, attribute: table_schema_1.PARTITION_KEY_ATTRIBUTE })) === undefined;
589
+ }
590
+ catch {
591
+ return false;
592
+ }
593
+ }