@farukada/aws-langgraph-dynamodb-ts 0.8.0 → 1.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (482) hide show
  1. package/README.md +282 -49
  2. package/dist/checkpointer/actions/delete-thread.d.ts +3 -2
  3. package/dist/checkpointer/actions/delete-thread.js +5 -2
  4. package/dist/checkpointer/actions/get-tuple.d.ts +3 -2
  5. package/dist/checkpointer/actions/get-tuple.js +10 -4
  6. package/dist/checkpointer/actions/list.d.ts +14 -4
  7. package/dist/checkpointer/actions/list.js +94 -61
  8. package/dist/checkpointer/actions/put-writes.d.ts +5 -5
  9. package/dist/checkpointer/actions/put-writes.js +12 -40
  10. package/dist/checkpointer/actions/put.d.ts +10 -3
  11. package/dist/checkpointer/actions/put.js +42 -12
  12. package/dist/checkpointer/internal/assemble.d.ts +10 -3
  13. package/dist/checkpointer/internal/assemble.js +7 -6
  14. package/dist/checkpointer/internal/checkpoint-write-verify.d.ts +24 -0
  15. package/dist/checkpointer/internal/checkpoint-write-verify.js +67 -0
  16. package/dist/checkpointer/internal/configurable.d.ts +0 -1
  17. package/dist/checkpointer/internal/configurable.js +10 -9
  18. package/dist/checkpointer/internal/fetch.d.ts +14 -5
  19. package/dist/checkpointer/internal/fetch.js +56 -14
  20. package/dist/checkpointer/internal/filter-match.d.ts +3 -2
  21. package/dist/checkpointer/internal/filter-match.js +4 -3
  22. package/dist/checkpointer/internal/item-reader.d.ts +31 -6
  23. package/dist/checkpointer/internal/item-reader.js +54 -15
  24. package/dist/checkpointer/internal/item-writer.d.ts +12 -3
  25. package/dist/checkpointer/internal/item-writer.js +26 -10
  26. package/dist/checkpointer/internal/keys.d.ts +11 -1
  27. package/dist/checkpointer/internal/keys.js +33 -3
  28. package/dist/checkpointer/internal/list-scope.d.ts +61 -0
  29. package/dist/checkpointer/internal/list-scope.js +108 -0
  30. package/dist/checkpointer/internal/pending-sends.d.ts +13 -0
  31. package/dist/checkpointer/internal/pending-sends.js +29 -0
  32. package/dist/checkpointer/internal/query.d.ts +2 -1
  33. package/dist/checkpointer/internal/query.js +9 -3
  34. package/dist/checkpointer/internal/regular-write.d.ts +28 -0
  35. package/dist/checkpointer/internal/regular-write.js +66 -0
  36. package/dist/checkpointer/internal/setup.d.ts +3 -1
  37. package/dist/checkpointer/internal/setup.js +10 -8
  38. package/dist/checkpointer/internal/special-write-cas.d.ts +29 -0
  39. package/dist/checkpointer/internal/special-write-cas.js +104 -0
  40. package/dist/checkpointer/internal/special-write-cleanup.d.ts +19 -14
  41. package/dist/checkpointer/internal/special-write-cleanup.js +35 -87
  42. package/dist/checkpointer/internal/special-write-verify.d.ts +53 -0
  43. package/dist/checkpointer/internal/special-write-verify.js +80 -0
  44. package/dist/checkpointer/internal/stored-channels.d.ts +31 -0
  45. package/dist/checkpointer/internal/stored-channels.js +70 -0
  46. package/dist/checkpointer/internal/validation.d.ts +11 -6
  47. package/dist/checkpointer/internal/validation.js +19 -9
  48. package/dist/checkpointer/internal/write-guard.d.ts +8 -9
  49. package/dist/checkpointer/internal/write-guard.js +16 -16
  50. package/dist/checkpointer/internal/write-index.d.ts +8 -1
  51. package/dist/checkpointer/internal/write-index.js +6 -3
  52. package/dist/checkpointer/saver.d.ts +50 -10
  53. package/dist/checkpointer/saver.js +59 -17
  54. package/dist/checkpointer/types.d.ts +14 -1
  55. package/dist/checkpointer/types.js +0 -1
  56. package/dist/factory/factory.d.ts +22 -25
  57. package/dist/factory/factory.js +58 -18
  58. package/dist/factory/types.d.ts +57 -0
  59. package/dist/factory/types.js +2 -0
  60. package/dist/history/actions/add-messages.d.ts +1 -2
  61. package/dist/history/actions/add-messages.js +4 -4
  62. package/dist/history/actions/clear.d.ts +3 -2
  63. package/dist/history/actions/clear.js +5 -2
  64. package/dist/history/actions/get-messages.d.ts +13 -6
  65. package/dist/history/actions/get-messages.js +63 -42
  66. package/dist/history/actions/list-sessions.d.ts +1 -1
  67. package/dist/history/actions/list-sessions.js +8 -12
  68. package/dist/history/actions/reconcile-count.d.ts +1 -2
  69. package/dist/history/actions/reconcile-count.js +20 -7
  70. package/dist/history/chat-message-history.d.ts +51 -26
  71. package/dist/history/chat-message-history.js +60 -30
  72. package/dist/history/internal/append-saga.d.ts +7 -2
  73. package/dist/history/internal/append-saga.js +58 -14
  74. package/dist/history/internal/compensation.d.ts +6 -2
  75. package/dist/history/internal/compensation.js +14 -6
  76. package/dist/history/internal/item-mapper.d.ts +0 -3
  77. package/dist/history/internal/item-mapper.js +2 -8
  78. package/dist/history/internal/keys.d.ts +0 -1
  79. package/dist/history/internal/keys.js +0 -1
  80. package/dist/history/internal/message-chunker.d.ts +0 -1
  81. package/dist/history/internal/message-chunker.js +0 -1
  82. package/dist/history/internal/message-transaction.d.ts +0 -1
  83. package/dist/history/internal/message-transaction.js +3 -2
  84. package/dist/history/internal/message-window.d.ts +17 -0
  85. package/dist/history/internal/message-window.js +49 -0
  86. package/dist/history/internal/query.d.ts +16 -3
  87. package/dist/history/internal/query.js +13 -5
  88. package/dist/history/internal/session-count.d.ts +8 -2
  89. package/dist/history/internal/session-count.js +14 -8
  90. package/dist/history/internal/session-title.d.ts +0 -1
  91. package/dist/history/internal/session-title.js +1 -2
  92. package/dist/history/internal/session-update.d.ts +0 -1
  93. package/dist/history/internal/session-update.js +0 -1
  94. package/dist/history/internal/setup.d.ts +3 -1
  95. package/dist/history/internal/setup.js +16 -8
  96. package/dist/history/internal/title-generator.d.ts +0 -1
  97. package/dist/history/internal/title-generator.js +19 -3
  98. package/dist/history/internal/ttl-anchor.d.ts +1 -2
  99. package/dist/history/internal/ttl-anchor.js +5 -5
  100. package/dist/history/internal/validation.d.ts +19 -3
  101. package/dist/history/internal/validation.js +41 -4
  102. package/dist/history/session-adapter.d.ts +9 -3
  103. package/dist/history/session-adapter.js +6 -3
  104. package/dist/history/types.d.ts +23 -2
  105. package/dist/history/types.js +0 -1
  106. package/dist/index.d.ts +12 -5
  107. package/dist/index.js +5 -3
  108. package/dist/shared/clock.d.ts +6 -1
  109. package/dist/shared/clock.js +9 -1
  110. package/dist/shared/codec/codec.d.ts +26 -17
  111. package/dist/shared/codec/codec.js +46 -24
  112. package/dist/shared/codec/compression.d.ts +1 -2
  113. package/dist/shared/codec/compression.js +2 -3
  114. package/dist/shared/codec/descriptor-keys.d.ts +11 -3
  115. package/dist/shared/codec/descriptor-keys.js +2 -2
  116. package/dist/shared/codec/encode.d.ts +13 -0
  117. package/dist/shared/codec/encode.js +43 -0
  118. package/dist/shared/codec/json-serde.d.ts +0 -1
  119. package/dist/shared/codec/json-serde.js +0 -1
  120. package/dist/shared/codec/payload-loss.d.ts +12 -0
  121. package/dist/shared/codec/payload-loss.js +38 -0
  122. package/dist/shared/codec/s3/adapter-config.d.ts +13 -0
  123. package/dist/shared/codec/s3/adapter-config.js +22 -0
  124. package/dist/shared/codec/s3/bounded-body.d.ts +14 -0
  125. package/dist/shared/codec/s3/bounded-body.js +47 -0
  126. package/dist/shared/codec/s3/client-types.d.ts +34 -0
  127. package/dist/shared/codec/s3/client-types.js +7 -0
  128. package/dist/shared/codec/s3/client.d.ts +11 -5
  129. package/dist/shared/codec/s3/client.js +25 -3
  130. package/dist/shared/codec/s3/config.d.ts +32 -5
  131. package/dist/shared/codec/s3/config.js +37 -5
  132. package/dist/shared/codec/s3/delete.d.ts +0 -1
  133. package/dist/shared/codec/s3/delete.js +0 -1
  134. package/dist/shared/codec/s3/key-scope.d.ts +23 -0
  135. package/dist/shared/codec/s3/key-scope.js +44 -0
  136. package/dist/shared/codec/s3/lifecycle.d.ts +11 -5
  137. package/dist/shared/codec/s3/lifecycle.js +32 -16
  138. package/dist/shared/codec/s3/offloader.d.ts +6 -2
  139. package/dist/shared/codec/s3/offloader.js +21 -3
  140. package/dist/shared/codec/s3/orphans.d.ts +6 -1
  141. package/dist/shared/codec/s3/orphans.js +15 -2
  142. package/dist/shared/codec/s3/read-write.d.ts +7 -3
  143. package/dist/shared/codec/s3/read-write.js +16 -8
  144. package/dist/shared/codec/s3/retry.d.ts +4 -4
  145. package/dist/shared/codec/s3/retry.js +13 -16
  146. package/dist/shared/concurrency.d.ts +6 -0
  147. package/dist/shared/concurrency.js +30 -0
  148. package/dist/shared/constants.d.ts +68 -5
  149. package/dist/shared/constants.js +70 -7
  150. package/dist/shared/dynamodb/abort.d.ts +9 -0
  151. package/dist/shared/dynamodb/abort.js +27 -0
  152. package/dist/shared/dynamodb/backoff.d.ts +4 -4
  153. package/dist/shared/dynamodb/backoff.js +7 -7
  154. package/dist/shared/dynamodb/batch-write.d.ts +0 -1
  155. package/dist/shared/dynamodb/batch-write.js +0 -1
  156. package/dist/shared/dynamodb/cancellation.d.ts +0 -1
  157. package/dist/shared/dynamodb/cancellation.js +0 -1
  158. package/dist/shared/dynamodb/client.d.ts +9 -2
  159. package/dist/shared/dynamodb/client.js +24 -1
  160. package/dist/shared/dynamodb/conditional-put.d.ts +67 -0
  161. package/dist/shared/dynamodb/conditional-put.js +76 -0
  162. package/dist/shared/dynamodb/drain-unprocessed.d.ts +3 -1
  163. package/dist/shared/dynamodb/drain-unprocessed.js +1 -2
  164. package/dist/shared/dynamodb/expiry.d.ts +16 -0
  165. package/dist/shared/dynamodb/expiry.js +29 -0
  166. package/dist/shared/dynamodb/paginate-core.d.ts +5 -3
  167. package/dist/shared/dynamodb/paginate-core.js +47 -17
  168. package/dist/shared/dynamodb/paginate.d.ts +0 -1
  169. package/dist/shared/dynamodb/paginate.js +1 -2
  170. package/dist/shared/dynamodb/partition-delete.d.ts +7 -1
  171. package/dist/shared/dynamodb/partition-delete.js +4 -3
  172. package/dist/shared/dynamodb/retry-classifier.d.ts +10 -2
  173. package/dist/shared/dynamodb/retry-classifier.js +42 -11
  174. package/dist/shared/dynamodb/retry-policy.d.ts +26 -0
  175. package/dist/shared/dynamodb/retry-policy.js +22 -0
  176. package/dist/shared/dynamodb/retry.d.ts +14 -1
  177. package/dist/shared/dynamodb/retry.js +11 -7
  178. package/dist/shared/dynamodb/scan.d.ts +0 -1
  179. package/dist/shared/dynamodb/scan.js +1 -2
  180. package/dist/shared/dynamodb/types.d.ts +1 -2
  181. package/dist/shared/dynamodb/types.js +0 -1
  182. package/dist/shared/errors/base-error.d.ts +14 -6
  183. package/dist/shared/errors/base-error.js +8 -9
  184. package/dist/shared/errors/boundary.d.ts +18 -0
  185. package/dist/shared/errors/boundary.js +46 -0
  186. package/dist/shared/errors/error-code.d.ts +2 -2
  187. package/dist/shared/errors/error-code.js +1 -1
  188. package/dist/shared/errors/errors.d.ts +13 -13
  189. package/dist/shared/errors/errors.js +18 -16
  190. package/dist/shared/errors/upstream-error.d.ts +16 -0
  191. package/dist/shared/errors/upstream-error.js +27 -0
  192. package/dist/shared/errors/wrap-error.d.ts +0 -9
  193. package/dist/shared/errors/wrap-error.js +0 -15
  194. package/dist/shared/logging/logger.d.ts +6 -2
  195. package/dist/shared/logging/logger.js +0 -1
  196. package/dist/shared/logging/redaction-walk.d.ts +2 -2
  197. package/dist/shared/logging/redaction-walk.js +38 -18
  198. package/dist/shared/logging/redaction.d.ts +14 -6
  199. package/dist/shared/logging/redaction.js +19 -4
  200. package/dist/shared/logging/secret-patterns.d.ts +54 -3
  201. package/dist/shared/logging/secret-patterns.js +67 -8
  202. package/dist/shared/options.d.ts +9 -4
  203. package/dist/shared/options.js +0 -1
  204. package/dist/shared/ulid.d.ts +15 -2
  205. package/dist/shared/ulid.js +35 -3
  206. package/dist/shared/validation/options.d.ts +8 -0
  207. package/dist/shared/validation/options.js +90 -0
  208. package/dist/shared/validation/primitives.d.ts +14 -10
  209. package/dist/shared/validation/primitives.js +23 -25
  210. package/dist/shared/validation/ttl.d.ts +14 -7
  211. package/dist/shared/validation/ttl.js +29 -11
  212. package/dist/store/actions/get.d.ts +11 -3
  213. package/dist/store/actions/get.js +52 -14
  214. package/dist/store/actions/list-namespaces.d.ts +0 -1
  215. package/dist/store/actions/list-namespaces.js +10 -6
  216. package/dist/store/actions/put.d.ts +0 -1
  217. package/dist/store/actions/put.js +27 -28
  218. package/dist/store/actions/reconcile-vector-index.d.ts +3 -2
  219. package/dist/store/actions/reconcile-vector-index.js +2 -3
  220. package/dist/store/actions/search.d.ts +1 -2
  221. package/dist/store/actions/search.js +11 -38
  222. package/dist/store/internal/backend-search.d.ts +1 -2
  223. package/dist/store/internal/backend-search.js +14 -7
  224. package/dist/store/internal/batch-plan.d.ts +11 -0
  225. package/dist/store/internal/batch-plan.js +52 -0
  226. package/dist/store/internal/candidates.d.ts +23 -0
  227. package/dist/store/internal/candidates.js +94 -0
  228. package/dist/store/internal/filter.d.ts +0 -1
  229. package/dist/store/internal/filter.js +25 -6
  230. package/dist/store/internal/index-reconcile.d.ts +5 -6
  231. package/dist/store/internal/index-reconcile.js +32 -13
  232. package/dist/store/internal/index-sync.d.ts +0 -1
  233. package/dist/store/internal/index-sync.js +0 -1
  234. package/dist/store/internal/item-mapper.d.ts +6 -3
  235. package/dist/store/internal/item-mapper.js +16 -6
  236. package/dist/store/internal/keys.d.ts +0 -1
  237. package/dist/store/internal/keys.js +0 -1
  238. package/dist/store/internal/namespace-match.d.ts +0 -1
  239. package/dist/store/internal/namespace-match.js +0 -1
  240. package/dist/store/internal/option-validation.d.ts +13 -0
  241. package/dist/store/internal/option-validation.js +77 -0
  242. package/dist/store/internal/overwrite-swap.d.ts +32 -0
  243. package/dist/store/internal/overwrite-swap.js +68 -0
  244. package/dist/store/internal/persist.d.ts +24 -7
  245. package/dist/store/internal/persist.js +49 -19
  246. package/dist/store/internal/query.d.ts +6 -1
  247. package/dist/store/internal/query.js +17 -1
  248. package/dist/store/internal/ranker.d.ts +7 -2
  249. package/dist/store/internal/ranker.js +10 -2
  250. package/dist/store/internal/read-existing.d.ts +23 -0
  251. package/dist/store/internal/read-existing.js +41 -0
  252. package/dist/store/internal/score-direction.d.ts +31 -0
  253. package/dist/store/internal/score-direction.js +38 -0
  254. package/dist/store/internal/search-filter.d.ts +0 -1
  255. package/dist/store/internal/search-filter.js +0 -1
  256. package/dist/store/internal/semantic-search.d.ts +26 -5
  257. package/dist/store/internal/semantic-search.js +59 -19
  258. package/dist/store/internal/setup.d.ts +6 -12
  259. package/dist/store/internal/setup.js +12 -24
  260. package/dist/store/internal/text-path.d.ts +17 -0
  261. package/dist/store/internal/text-path.js +147 -0
  262. package/dist/store/internal/validation.d.ts +8 -3
  263. package/dist/store/internal/validation.js +21 -5
  264. package/dist/store/internal/write-verify.d.ts +27 -9
  265. package/dist/store/internal/write-verify.js +35 -19
  266. package/dist/store/store.d.ts +37 -9
  267. package/dist/store/store.js +52 -17
  268. package/dist/store/types.d.ts +22 -2
  269. package/dist/store/types.js +0 -1
  270. package/dist/store/vector-backend.d.ts +6 -7
  271. package/dist/store/vector-backend.js +0 -1
  272. package/package.json +21 -15
  273. package/dist/checkpointer/actions/delete-thread.d.ts.map +0 -1
  274. package/dist/checkpointer/actions/delete-thread.js.map +0 -1
  275. package/dist/checkpointer/actions/get-tuple.d.ts.map +0 -1
  276. package/dist/checkpointer/actions/get-tuple.js.map +0 -1
  277. package/dist/checkpointer/actions/list.d.ts.map +0 -1
  278. package/dist/checkpointer/actions/list.js.map +0 -1
  279. package/dist/checkpointer/actions/put-writes.d.ts.map +0 -1
  280. package/dist/checkpointer/actions/put-writes.js.map +0 -1
  281. package/dist/checkpointer/actions/put.d.ts.map +0 -1
  282. package/dist/checkpointer/actions/put.js.map +0 -1
  283. package/dist/checkpointer/internal/assemble.d.ts.map +0 -1
  284. package/dist/checkpointer/internal/assemble.js.map +0 -1
  285. package/dist/checkpointer/internal/configurable.d.ts.map +0 -1
  286. package/dist/checkpointer/internal/configurable.js.map +0 -1
  287. package/dist/checkpointer/internal/fetch.d.ts.map +0 -1
  288. package/dist/checkpointer/internal/fetch.js.map +0 -1
  289. package/dist/checkpointer/internal/filter-match.d.ts.map +0 -1
  290. package/dist/checkpointer/internal/filter-match.js.map +0 -1
  291. package/dist/checkpointer/internal/item-reader.d.ts.map +0 -1
  292. package/dist/checkpointer/internal/item-reader.js.map +0 -1
  293. package/dist/checkpointer/internal/item-writer.d.ts.map +0 -1
  294. package/dist/checkpointer/internal/item-writer.js.map +0 -1
  295. package/dist/checkpointer/internal/keys.d.ts.map +0 -1
  296. package/dist/checkpointer/internal/keys.js.map +0 -1
  297. package/dist/checkpointer/internal/query.d.ts.map +0 -1
  298. package/dist/checkpointer/internal/query.js.map +0 -1
  299. package/dist/checkpointer/internal/setup.d.ts.map +0 -1
  300. package/dist/checkpointer/internal/setup.js.map +0 -1
  301. package/dist/checkpointer/internal/special-write-cleanup.d.ts.map +0 -1
  302. package/dist/checkpointer/internal/special-write-cleanup.js.map +0 -1
  303. package/dist/checkpointer/internal/validation.d.ts.map +0 -1
  304. package/dist/checkpointer/internal/validation.js.map +0 -1
  305. package/dist/checkpointer/internal/write-guard.d.ts.map +0 -1
  306. package/dist/checkpointer/internal/write-guard.js.map +0 -1
  307. package/dist/checkpointer/internal/write-index.d.ts.map +0 -1
  308. package/dist/checkpointer/internal/write-index.js.map +0 -1
  309. package/dist/checkpointer/saver.d.ts.map +0 -1
  310. package/dist/checkpointer/saver.js.map +0 -1
  311. package/dist/checkpointer/types.d.ts.map +0 -1
  312. package/dist/checkpointer/types.js.map +0 -1
  313. package/dist/factory/factory.d.ts.map +0 -1
  314. package/dist/factory/factory.js.map +0 -1
  315. package/dist/history/actions/add-messages.d.ts.map +0 -1
  316. package/dist/history/actions/add-messages.js.map +0 -1
  317. package/dist/history/actions/clear.d.ts.map +0 -1
  318. package/dist/history/actions/clear.js.map +0 -1
  319. package/dist/history/actions/get-messages.d.ts.map +0 -1
  320. package/dist/history/actions/get-messages.js.map +0 -1
  321. package/dist/history/actions/list-sessions.d.ts.map +0 -1
  322. package/dist/history/actions/list-sessions.js.map +0 -1
  323. package/dist/history/actions/reconcile-count.d.ts.map +0 -1
  324. package/dist/history/actions/reconcile-count.js.map +0 -1
  325. package/dist/history/chat-message-history.d.ts.map +0 -1
  326. package/dist/history/chat-message-history.js.map +0 -1
  327. package/dist/history/internal/append-saga.d.ts.map +0 -1
  328. package/dist/history/internal/append-saga.js.map +0 -1
  329. package/dist/history/internal/compensation.d.ts.map +0 -1
  330. package/dist/history/internal/compensation.js.map +0 -1
  331. package/dist/history/internal/item-mapper.d.ts.map +0 -1
  332. package/dist/history/internal/item-mapper.js.map +0 -1
  333. package/dist/history/internal/keys.d.ts.map +0 -1
  334. package/dist/history/internal/keys.js.map +0 -1
  335. package/dist/history/internal/message-chunker.d.ts.map +0 -1
  336. package/dist/history/internal/message-chunker.js.map +0 -1
  337. package/dist/history/internal/message-transaction.d.ts.map +0 -1
  338. package/dist/history/internal/message-transaction.js.map +0 -1
  339. package/dist/history/internal/query.d.ts.map +0 -1
  340. package/dist/history/internal/query.js.map +0 -1
  341. package/dist/history/internal/session-count.d.ts.map +0 -1
  342. package/dist/history/internal/session-count.js.map +0 -1
  343. package/dist/history/internal/session-title.d.ts.map +0 -1
  344. package/dist/history/internal/session-title.js.map +0 -1
  345. package/dist/history/internal/session-update.d.ts.map +0 -1
  346. package/dist/history/internal/session-update.js.map +0 -1
  347. package/dist/history/internal/setup.d.ts.map +0 -1
  348. package/dist/history/internal/setup.js.map +0 -1
  349. package/dist/history/internal/title-generator.d.ts.map +0 -1
  350. package/dist/history/internal/title-generator.js.map +0 -1
  351. package/dist/history/internal/ttl-anchor.d.ts.map +0 -1
  352. package/dist/history/internal/ttl-anchor.js.map +0 -1
  353. package/dist/history/internal/validation.d.ts.map +0 -1
  354. package/dist/history/internal/validation.js.map +0 -1
  355. package/dist/history/session-adapter.d.ts.map +0 -1
  356. package/dist/history/session-adapter.js.map +0 -1
  357. package/dist/history/types.d.ts.map +0 -1
  358. package/dist/history/types.js.map +0 -1
  359. package/dist/index.d.ts.map +0 -1
  360. package/dist/index.js.map +0 -1
  361. package/dist/shared/clock.d.ts.map +0 -1
  362. package/dist/shared/clock.js.map +0 -1
  363. package/dist/shared/codec/codec.d.ts.map +0 -1
  364. package/dist/shared/codec/codec.js.map +0 -1
  365. package/dist/shared/codec/compression.d.ts.map +0 -1
  366. package/dist/shared/codec/compression.js.map +0 -1
  367. package/dist/shared/codec/descriptor-keys.d.ts.map +0 -1
  368. package/dist/shared/codec/descriptor-keys.js.map +0 -1
  369. package/dist/shared/codec/json-serde.d.ts.map +0 -1
  370. package/dist/shared/codec/json-serde.js.map +0 -1
  371. package/dist/shared/codec/s3/client.d.ts.map +0 -1
  372. package/dist/shared/codec/s3/client.js.map +0 -1
  373. package/dist/shared/codec/s3/config.d.ts.map +0 -1
  374. package/dist/shared/codec/s3/config.js.map +0 -1
  375. package/dist/shared/codec/s3/delete.d.ts.map +0 -1
  376. package/dist/shared/codec/s3/delete.js.map +0 -1
  377. package/dist/shared/codec/s3/lifecycle.d.ts.map +0 -1
  378. package/dist/shared/codec/s3/lifecycle.js.map +0 -1
  379. package/dist/shared/codec/s3/offloader.d.ts.map +0 -1
  380. package/dist/shared/codec/s3/offloader.js.map +0 -1
  381. package/dist/shared/codec/s3/orphans.d.ts.map +0 -1
  382. package/dist/shared/codec/s3/orphans.js.map +0 -1
  383. package/dist/shared/codec/s3/read-write.d.ts.map +0 -1
  384. package/dist/shared/codec/s3/read-write.js.map +0 -1
  385. package/dist/shared/codec/s3/retry.d.ts.map +0 -1
  386. package/dist/shared/codec/s3/retry.js.map +0 -1
  387. package/dist/shared/constants.d.ts.map +0 -1
  388. package/dist/shared/constants.js.map +0 -1
  389. package/dist/shared/dynamodb/backoff.d.ts.map +0 -1
  390. package/dist/shared/dynamodb/backoff.js.map +0 -1
  391. package/dist/shared/dynamodb/batch-write.d.ts.map +0 -1
  392. package/dist/shared/dynamodb/batch-write.js.map +0 -1
  393. package/dist/shared/dynamodb/cancellation.d.ts.map +0 -1
  394. package/dist/shared/dynamodb/cancellation.js.map +0 -1
  395. package/dist/shared/dynamodb/client.d.ts.map +0 -1
  396. package/dist/shared/dynamodb/client.js.map +0 -1
  397. package/dist/shared/dynamodb/drain-unprocessed.d.ts.map +0 -1
  398. package/dist/shared/dynamodb/drain-unprocessed.js.map +0 -1
  399. package/dist/shared/dynamodb/paginate-core.d.ts.map +0 -1
  400. package/dist/shared/dynamodb/paginate-core.js.map +0 -1
  401. package/dist/shared/dynamodb/paginate.d.ts.map +0 -1
  402. package/dist/shared/dynamodb/paginate.js.map +0 -1
  403. package/dist/shared/dynamodb/partition-delete.d.ts.map +0 -1
  404. package/dist/shared/dynamodb/partition-delete.js.map +0 -1
  405. package/dist/shared/dynamodb/retry-classifier.d.ts.map +0 -1
  406. package/dist/shared/dynamodb/retry-classifier.js.map +0 -1
  407. package/dist/shared/dynamodb/retry.d.ts.map +0 -1
  408. package/dist/shared/dynamodb/retry.js.map +0 -1
  409. package/dist/shared/dynamodb/scan.d.ts.map +0 -1
  410. package/dist/shared/dynamodb/scan.js.map +0 -1
  411. package/dist/shared/dynamodb/types.d.ts.map +0 -1
  412. package/dist/shared/dynamodb/types.js.map +0 -1
  413. package/dist/shared/errors/base-error.d.ts.map +0 -1
  414. package/dist/shared/errors/base-error.js.map +0 -1
  415. package/dist/shared/errors/error-code.d.ts.map +0 -1
  416. package/dist/shared/errors/error-code.js.map +0 -1
  417. package/dist/shared/errors/errors.d.ts.map +0 -1
  418. package/dist/shared/errors/errors.js.map +0 -1
  419. package/dist/shared/errors/wrap-error.d.ts.map +0 -1
  420. package/dist/shared/errors/wrap-error.js.map +0 -1
  421. package/dist/shared/logging/logger.d.ts.map +0 -1
  422. package/dist/shared/logging/logger.js.map +0 -1
  423. package/dist/shared/logging/redaction-walk.d.ts.map +0 -1
  424. package/dist/shared/logging/redaction-walk.js.map +0 -1
  425. package/dist/shared/logging/redaction.d.ts.map +0 -1
  426. package/dist/shared/logging/redaction.js.map +0 -1
  427. package/dist/shared/logging/secret-patterns.d.ts.map +0 -1
  428. package/dist/shared/logging/secret-patterns.js.map +0 -1
  429. package/dist/shared/options.d.ts.map +0 -1
  430. package/dist/shared/options.js.map +0 -1
  431. package/dist/shared/ulid.d.ts.map +0 -1
  432. package/dist/shared/ulid.js.map +0 -1
  433. package/dist/shared/validation/primitives.d.ts.map +0 -1
  434. package/dist/shared/validation/primitives.js.map +0 -1
  435. package/dist/shared/validation/ttl.d.ts.map +0 -1
  436. package/dist/shared/validation/ttl.js.map +0 -1
  437. package/dist/store/actions/get.d.ts.map +0 -1
  438. package/dist/store/actions/get.js.map +0 -1
  439. package/dist/store/actions/list-namespaces.d.ts.map +0 -1
  440. package/dist/store/actions/list-namespaces.js.map +0 -1
  441. package/dist/store/actions/put.d.ts.map +0 -1
  442. package/dist/store/actions/put.js.map +0 -1
  443. package/dist/store/actions/reconcile-vector-index.d.ts.map +0 -1
  444. package/dist/store/actions/reconcile-vector-index.js.map +0 -1
  445. package/dist/store/actions/search.d.ts.map +0 -1
  446. package/dist/store/actions/search.js.map +0 -1
  447. package/dist/store/internal/backend-search.d.ts.map +0 -1
  448. package/dist/store/internal/backend-search.js.map +0 -1
  449. package/dist/store/internal/filter.d.ts.map +0 -1
  450. package/dist/store/internal/filter.js.map +0 -1
  451. package/dist/store/internal/index-reconcile.d.ts.map +0 -1
  452. package/dist/store/internal/index-reconcile.js.map +0 -1
  453. package/dist/store/internal/index-sync.d.ts.map +0 -1
  454. package/dist/store/internal/index-sync.js.map +0 -1
  455. package/dist/store/internal/item-mapper.d.ts.map +0 -1
  456. package/dist/store/internal/item-mapper.js.map +0 -1
  457. package/dist/store/internal/keys.d.ts.map +0 -1
  458. package/dist/store/internal/keys.js.map +0 -1
  459. package/dist/store/internal/namespace-match.d.ts.map +0 -1
  460. package/dist/store/internal/namespace-match.js.map +0 -1
  461. package/dist/store/internal/persist.d.ts.map +0 -1
  462. package/dist/store/internal/persist.js.map +0 -1
  463. package/dist/store/internal/query.d.ts.map +0 -1
  464. package/dist/store/internal/query.js.map +0 -1
  465. package/dist/store/internal/ranker.d.ts.map +0 -1
  466. package/dist/store/internal/ranker.js.map +0 -1
  467. package/dist/store/internal/search-filter.d.ts.map +0 -1
  468. package/dist/store/internal/search-filter.js.map +0 -1
  469. package/dist/store/internal/semantic-search.d.ts.map +0 -1
  470. package/dist/store/internal/semantic-search.js.map +0 -1
  471. package/dist/store/internal/setup.d.ts.map +0 -1
  472. package/dist/store/internal/setup.js.map +0 -1
  473. package/dist/store/internal/validation.d.ts.map +0 -1
  474. package/dist/store/internal/validation.js.map +0 -1
  475. package/dist/store/internal/write-verify.d.ts.map +0 -1
  476. package/dist/store/internal/write-verify.js.map +0 -1
  477. package/dist/store/store.d.ts.map +0 -1
  478. package/dist/store/store.js.map +0 -1
  479. package/dist/store/types.d.ts.map +0 -1
  480. package/dist/store/types.js.map +0 -1
  481. package/dist/store/vector-backend.d.ts.map +0 -1
  482. package/dist/store/vector-backend.js.map +0 -1
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.oversizedObjectError = oversizedObjectError;
4
+ exports.readBodyBounded = readBodyBounded;
5
+ const base_error_1 = require("../../errors/base-error");
6
+ const error_code_1 = require("../../errors/error-code");
7
+ /** The typed error for an object over the download cap. */
8
+ function oversizedObjectError(key, bytes, maxBytes) {
9
+ return new base_error_1.DynamoDBLangGraphError(`S3 object ${key} exceeds the ${maxBytes}-byte maxDownloadBytes cap ` +
10
+ `(${bytes} bytes declared or read)`, error_code_1.ErrorCode.S3_OFFLOAD_FAILED, { operation: 'download', key });
11
+ }
12
+ function concat(chunks, total) {
13
+ const out = new Uint8Array(total);
14
+ let offset = 0;
15
+ for (const chunk of chunks) {
16
+ out.set(chunk, offset);
17
+ offset += chunk.length;
18
+ }
19
+ return out;
20
+ }
21
+ /**
22
+ * Buffer an S3 body without ever holding more than `maxBytes` of it. A
23
+ * streaming body is consumed chunk by chunk and abandoned the moment the
24
+ * running total passes the cap; a body that only offers
25
+ * `transformToByteArray()` is read whole and then checked.
26
+ */
27
+ async function readBodyBounded(body, key, maxBytes) {
28
+ const streaming = body;
29
+ const iterate = streaming[Symbol.asyncIterator];
30
+ if (typeof iterate !== 'function') {
31
+ const whole = new Uint8Array(await body.transformToByteArray());
32
+ if (whole.length > maxBytes)
33
+ throw oversizedObjectError(key, whole.length, maxBytes);
34
+ return whole;
35
+ }
36
+ const chunks = [];
37
+ let total = 0;
38
+ for await (const chunk of { [Symbol.asyncIterator]: iterate.bind(streaming) }) {
39
+ total += chunk.length;
40
+ if (total > maxBytes) {
41
+ streaming.destroy?.();
42
+ throw oversizedObjectError(key, total, maxBytes);
43
+ }
44
+ chunks.push(chunk);
45
+ }
46
+ return concat(chunks, total);
47
+ }
@@ -0,0 +1,34 @@
1
+ /** A region as the SDK accepts it: a string or a provider resolving to one. */
2
+ export type S3RegionLike = string | (() => Promise<string>);
3
+ /** A value an S3 client option can hold. */
4
+ export type S3ClientOption = string | number | boolean | object | null | undefined;
5
+ /**
6
+ * The S3 client options this library reads (`region`) or sets (`maxAttempts`),
7
+ * open to every other `S3ClientConfig` key.
8
+ */
9
+ export interface S3ClientOptions {
10
+ region?: S3RegionLike;
11
+ maxAttempts?: number;
12
+ [option: string]: S3ClientOption;
13
+ }
14
+ /**
15
+ * Structural stand-in for `S3ClientConfig`, so the shipped declarations compile
16
+ * without the optional `@aws-sdk/client-s3` peer installed. A literal gets
17
+ * completion for the options the library uses; a typed `S3ClientConfig`
18
+ * variable is accepted as it is.
19
+ */
20
+ export type S3ClientConfigLike = S3ClientOptions | object;
21
+ /** The options of a config, read through the structural type. */
22
+ export declare function s3ClientOptions(config: S3ClientConfigLike | undefined): S3ClientOptions;
23
+ /** What every SDK command object carries: its `input`. */
24
+ export interface S3CommandLike {
25
+ input: object;
26
+ }
27
+ /**
28
+ * The S3 client surface this library calls, typed structurally for the same
29
+ * reason. `S3Client` from `@aws-sdk/client-s3` satisfies it.
30
+ */
31
+ export interface S3ClientLike {
32
+ send(command: S3CommandLike, options?: object): Promise<object>;
33
+ destroy(): void;
34
+ }
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.s3ClientOptions = s3ClientOptions;
4
+ /** The options of a config, read through the structural type. */
5
+ function s3ClientOptions(config) {
6
+ return (config ?? {});
7
+ }
@@ -1,6 +1,12 @@
1
- import type { S3Client, S3ClientConfig } from '@aws-sdk/client-s3';
2
- /** Lazily import the optional `@aws-sdk/client-s3` peer, caching the module. */
3
- export declare function loadS3Sdk(): Promise<typeof import('@aws-sdk/client-s3')>;
1
+ import type { S3Client } from '@aws-sdk/client-s3';
2
+ import type { S3ClientConfigLike } from './client-types';
3
+ type S3Sdk = typeof import('@aws-sdk/client-s3');
4
+ /**
5
+ * Lazily import the optional `@aws-sdk/client-s3` peer, caching the module. A
6
+ * failed import is not cached, so an install or a fixed bundle can succeed on
7
+ * a later call.
8
+ */
9
+ export declare function loadS3Sdk(): Promise<S3Sdk>;
4
10
  /**
5
11
  * Construct an `S3Client` from `config` using the lazily-loaded SDK. Defaults
6
12
  * `maxAttempts: 1` so the SDK's own internal retries are disabled and this
@@ -8,5 +14,5 @@ export declare function loadS3Sdk(): Promise<typeof import('@aws-sdk/client-s3')
8
14
  * matching {@link resolveDynamoDBClient}'s equivalent default; an explicit
9
15
  * `maxAttempts` in `config` still wins.
10
16
  */
11
- export declare function createDefaultS3Client(config: S3ClientConfig): Promise<S3Client>;
12
- //# sourceMappingURL=client.d.ts.map
17
+ export declare function createDefaultS3Client(config: S3ClientConfigLike): Promise<S3Client>;
18
+ export {};
@@ -2,11 +2,34 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadS3Sdk = loadS3Sdk;
4
4
  exports.createDefaultS3Client = createDefaultS3Client;
5
+ const errors_1 = require("../../errors/errors");
6
+ /** Codes Node and bundlers use for an import that cannot be resolved. */
7
+ const MISSING_MODULE_CODES = ['ERR_MODULE_NOT_FOUND', 'MODULE_NOT_FOUND'];
5
8
  let sdkPromise;
6
- /** Lazily import the optional `@aws-sdk/client-s3` peer, caching the module. */
9
+ /**
10
+ * Convert a failed import of the optional peer into a typed error that names
11
+ * the remedy. Any other failure (a broken build, a syntax error inside the
12
+ * package) passes through unchanged.
13
+ */
14
+ function wrapMissingPeer(error) {
15
+ const code = error.code;
16
+ if (code !== undefined && MISSING_MODULE_CODES.includes(code)) {
17
+ throw new errors_1.ValidationError('S3 offload requires the optional peer @aws-sdk/client-s3 (npm install @aws-sdk/client-s3); ' +
18
+ 'bundlers must keep it installed or external', 's3', error);
19
+ }
20
+ throw error;
21
+ }
22
+ /**
23
+ * Lazily import the optional `@aws-sdk/client-s3` peer, caching the module. A
24
+ * failed import is not cached, so an install or a fixed bundle can succeed on
25
+ * a later call.
26
+ */
7
27
  async function loadS3Sdk() {
8
28
  if (!sdkPromise) {
9
- sdkPromise = import('@aws-sdk/client-s3');
29
+ sdkPromise = import('@aws-sdk/client-s3').catch((error) => {
30
+ sdkPromise = undefined;
31
+ return wrapMissingPeer(error);
32
+ });
10
33
  }
11
34
  return sdkPromise;
12
35
  }
@@ -21,4 +44,3 @@ async function createDefaultS3Client(config) {
21
44
  const { S3Client: S3ClientCtor } = await loadS3Sdk();
22
45
  return new S3ClientCtor({ maxAttempts: 1, ...config });
23
46
  }
24
- //# sourceMappingURL=client.js.map
@@ -1,13 +1,26 @@
1
- import type { S3Client, S3ClientConfig } from '@aws-sdk/client-s3';
1
+ import type { S3ClientConfigLike } from './client-types';
2
2
  /** Configuration for offloading large payloads to S3. */
3
3
  export interface S3OffloadConfig {
4
4
  bucketName: string;
5
5
  keyPrefix?: string;
6
+ /**
7
+ * Serialized payloads at or above this size are offloaded (default 350 KB).
8
+ * Only the payload counts: the store's inline embedding (about 10 bytes per
9
+ * dimension, so ~10 KB at 1024 dims and ~45 KB at 4096) lives on the same
10
+ * item and is not part of it, so keep `thresholdBytes` plus the embedding
11
+ * under DynamoDB's 400 KB item limit or the put fails with a raw
12
+ * `ValidationException`.
13
+ */
6
14
  thresholdBytes?: number;
7
15
  serverSideEncryption?: string;
8
16
  sseKmsKeyId?: string;
9
- clientConfig?: S3ClientConfig;
10
- createS3Client?: (config: S3ClientConfig) => S3Client;
17
+ /** Largest object this adapter will buffer from S3 (default 50 MiB). */
18
+ maxDownloadBytes?: number;
19
+ /**
20
+ * S3 client configuration (an `S3ClientConfig`). `region` defaults to the
21
+ * adapter's DynamoDB region.
22
+ */
23
+ clientConfig?: S3ClientConfigLike;
11
24
  }
12
25
  /**
13
26
  * Build a fully-qualified S3 key: `${prefix}${parts, each base64url-encoded,
@@ -15,10 +28,24 @@ export interface S3OffloadConfig {
15
28
  * `parts` arrays never collide, since a namespace element or key is allowed
16
29
  * to contain '/' (only the DynamoDB '#' separator is forbidden at the
17
30
  * validation layer) and base64url's output alphabet never contains '/'.
31
+ *
32
+ * The produced key is checked against S3's 1024-byte object-key cap: the
33
+ * encoding grows every part by a third, so identifiers that each pass their
34
+ * own length rule can still compose a key S3 would reject with a raw error.
18
35
  */
19
36
  export declare function buildS3Key(prefix: string, parts: readonly string[]): string;
20
- /** Build a deterministic, TTL-independent lifecycle rule id from the prefix. */
37
+ /**
38
+ * The key prefix doubles as the S3 lifecycle rule's `Filter.Prefix`. An empty
39
+ * or root prefix would make that rule expire the whole bucket, and a prefix
40
+ * without a trailing `/` (`app/langgraph`) would also match every sibling
41
+ * object that merely starts with the same characters (`app/langgraph-other/`).
42
+ */
43
+ export declare function assertScopedKeyPrefix(keyPrefix: string): void;
44
+ /**
45
+ * Build a deterministic, TTL-independent lifecycle rule id from the prefix.
46
+ * Trailing slashes are trimmed with a loop rather than `/\/+$/`, whose
47
+ * backtracking is quadratic in the number of slashes.
48
+ */
21
49
  export declare function buildLifecycleRuleId(prefix: string): string;
22
50
  /** An adapter's default S3 key prefix: the shared base plus its own segment. */
23
51
  export declare function defaultAdapterKeyPrefix(base: string, adapter: string): string;
24
- //# sourceMappingURL=config.d.ts.map
@@ -1,26 +1,58 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildS3Key = buildS3Key;
4
+ exports.assertScopedKeyPrefix = assertScopedKeyPrefix;
4
5
  exports.buildLifecycleRuleId = buildLifecycleRuleId;
5
6
  exports.defaultAdapterKeyPrefix = defaultAdapterKeyPrefix;
7
+ const constants_1 = require("../../constants");
8
+ const errors_1 = require("../../errors/errors");
9
+ const key_scope_1 = require("./key-scope");
6
10
  /**
7
11
  * Build a fully-qualified S3 key: `${prefix}${parts, each base64url-encoded,
8
12
  * joined with '/'}.bin`. Encoding (not rejecting) is what makes two distinct
9
13
  * `parts` arrays never collide, since a namespace element or key is allowed
10
14
  * to contain '/' (only the DynamoDB '#' separator is forbidden at the
11
15
  * validation layer) and base64url's output alphabet never contains '/'.
16
+ *
17
+ * The produced key is checked against S3's 1024-byte object-key cap: the
18
+ * encoding grows every part by a third, so identifiers that each pass their
19
+ * own length rule can still compose a key S3 would reject with a raw error.
12
20
  */
13
21
  function buildS3Key(prefix, parts) {
14
- const encoded = parts.map((part) => Buffer.from(part, 'utf8').toString('base64url'));
15
- return `${prefix}${encoded.join('/')}.bin`;
22
+ const encoded = parts.map(key_scope_1.encodeKeyPart);
23
+ const key = `${prefix}${encoded.join('/')}.bin`;
24
+ const bytes = Buffer.byteLength(key, 'utf8');
25
+ if (bytes > constants_1.MAX_S3_KEY_BYTES) {
26
+ throw new errors_1.ValidationError(`the offloaded S3 object key would be ${bytes} bytes; S3 caps keys at ` +
27
+ `${constants_1.MAX_S3_KEY_BYTES} — shorten the identifiers or the keyPrefix`, 's3Key');
28
+ }
29
+ return key;
16
30
  }
17
- /** Build a deterministic, TTL-independent lifecycle rule id from the prefix. */
31
+ /**
32
+ * The key prefix doubles as the S3 lifecycle rule's `Filter.Prefix`. An empty
33
+ * or root prefix would make that rule expire the whole bucket, and a prefix
34
+ * without a trailing `/` (`app/langgraph`) would also match every sibling
35
+ * object that merely starts with the same characters (`app/langgraph-other/`).
36
+ */
37
+ function assertScopedKeyPrefix(keyPrefix) {
38
+ if (keyPrefix === '' || keyPrefix === '/' || !keyPrefix.endsWith('/')) {
39
+ throw new errors_1.ValidationError('s3.keyPrefix must be a non-empty path that ends with "/" (for example "langgraph/"): ' +
40
+ 'it scopes both the offloaded objects and the S3 lifecycle rule', 's3.keyPrefix');
41
+ }
42
+ }
43
+ /**
44
+ * Build a deterministic, TTL-independent lifecycle rule id from the prefix.
45
+ * Trailing slashes are trimmed with a loop rather than `/\/+$/`, whose
46
+ * backtracking is quadratic in the number of slashes.
47
+ */
18
48
  function buildLifecycleRuleId(prefix) {
19
- const slug = prefix.replace(/\/+$/, '').replace(/[^a-zA-Z0-9-]/g, '-') || 'default';
49
+ let trimmed = prefix;
50
+ while (trimmed.endsWith('/'))
51
+ trimmed = trimmed.slice(0, -1);
52
+ const slug = trimmed.replace(/[^a-zA-Z0-9-]/g, '-') || 'default';
20
53
  return `langgraph-ttl-${slug}`;
21
54
  }
22
55
  /** An adapter's default S3 key prefix: the shared base plus its own segment. */
23
56
  function defaultAdapterKeyPrefix(base, adapter) {
24
57
  return `${base}${adapter}/`;
25
58
  }
26
- //# sourceMappingURL=config.js.map
@@ -5,4 +5,3 @@ import type { S3Client } from '@aws-sdk/client-s3';
5
5
  * callers (orphan cleanup) can decide how loudly to react.
6
6
  */
7
7
  export declare function deleteObjects(client: S3Client, bucket: string, keys: string[]): Promise<string[]>;
8
- //# sourceMappingURL=delete.d.ts.map
@@ -26,4 +26,3 @@ async function deleteObjects(client, bucket, keys) {
26
26
  }
27
27
  return failed;
28
28
  }
29
- //# sourceMappingURL=delete.js.map
@@ -0,0 +1,23 @@
1
+ /** base64url-encode one key part; the output alphabet never contains `/` or `.`. */
2
+ export declare function encodeKeyPart(part: string): string;
3
+ /**
4
+ * The path every key `buildS3Key(prefix, [...parts, ...more])` shares: the
5
+ * prefix plus the encoded `parts` joined by `/`, with neither `.bin` nor a
6
+ * trailing `/`.
7
+ */
8
+ export declare function s3KeyScope(prefix: string, parts: readonly string[]): string;
9
+ /**
10
+ * True when `key` was produced by `buildS3Key` from exactly `parts`
11
+ * (`<scope>.bin`) or from `parts` plus further parts (`<scope>/…`). An empty
12
+ * `parts` degrades to a prefix-only check. Because parts are base64url-encoded
13
+ * and joined by `/`, an identifier sharing a leading substring with another
14
+ * (`t` and `t1`) never matches its scope.
15
+ */
16
+ export declare function isKeyInScope(key: string, prefix: string, parts: readonly string[]): boolean;
17
+ /**
18
+ * Refuse a row-sourced `s3Key` that lies outside the path the row's own
19
+ * identifiers produce. A row is trusted for its shape, not for the object it
20
+ * points at: a writer able to place one row in a partition must not be able
21
+ * to make this library download or delete another tenant's object.
22
+ */
23
+ export declare function assertKeyInScope(key: string, prefix: string, parts: readonly string[]): void;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.encodeKeyPart = encodeKeyPart;
4
+ exports.s3KeyScope = s3KeyScope;
5
+ exports.isKeyInScope = isKeyInScope;
6
+ exports.assertKeyInScope = assertKeyInScope;
7
+ const errors_1 = require("../../errors/errors");
8
+ /** base64url-encode one key part; the output alphabet never contains `/` or `.`. */
9
+ function encodeKeyPart(part) {
10
+ return Buffer.from(part, 'utf8').toString('base64url');
11
+ }
12
+ /**
13
+ * The path every key `buildS3Key(prefix, [...parts, ...more])` shares: the
14
+ * prefix plus the encoded `parts` joined by `/`, with neither `.bin` nor a
15
+ * trailing `/`.
16
+ */
17
+ function s3KeyScope(prefix, parts) {
18
+ return `${prefix}${parts.map(encodeKeyPart).join('/')}`;
19
+ }
20
+ /**
21
+ * True when `key` was produced by `buildS3Key` from exactly `parts`
22
+ * (`<scope>.bin`) or from `parts` plus further parts (`<scope>/…`). An empty
23
+ * `parts` degrades to a prefix-only check. Because parts are base64url-encoded
24
+ * and joined by `/`, an identifier sharing a leading substring with another
25
+ * (`t` and `t1`) never matches its scope.
26
+ */
27
+ function isKeyInScope(key, prefix, parts) {
28
+ const scope = s3KeyScope(prefix, parts);
29
+ if (parts.length === 0)
30
+ return key.startsWith(scope);
31
+ return key === `${scope}.bin` || key.startsWith(`${scope}/`);
32
+ }
33
+ /**
34
+ * Refuse a row-sourced `s3Key` that lies outside the path the row's own
35
+ * identifiers produce. A row is trusted for its shape, not for the object it
36
+ * points at: a writer able to place one row in a partition must not be able
37
+ * to make this library download or delete another tenant's object.
38
+ */
39
+ function assertKeyInScope(key, prefix, parts) {
40
+ if (isKeyInScope(key, prefix, parts))
41
+ return;
42
+ throw new errors_1.ValidationError(`s3Key "${key}" lies outside the S3 path this row may reference ` +
43
+ `("${s3KeyScope(prefix, parts)}"); refusing to touch an object the row does not own`, 's3Key');
44
+ }
@@ -1,8 +1,14 @@
1
1
  import type { S3Client } from '@aws-sdk/client-s3';
2
2
  /**
3
- * Idempotently ensure a `${ttlDays}`-day expiration lifecycle rule exists for
4
- * `prefix`. Reads existing rules, preserves user-defined ones, and only
5
- * adds/updates the library's prefix-scoped rule.
3
+ * Idempotently ensure a `days`-day expiration lifecycle rule exists for
4
+ * `prefix`. Reads existing rules, preserves user-defined ones and the
5
+ * bucket-level `TransitionDefaultMinimumObjectSize` (a Put replaces the whole
6
+ * configuration, so dropping it would reset the bucket to the default), and
7
+ * only adds/updates the library's prefix-scoped rule.
8
+ *
9
+ * Noncurrent versions expire after the same number of days, so a versioned
10
+ * bucket does not retain every superseded payload forever; the field is inert
11
+ * on an unversioned bucket. The prefix is re-checked here because this rule is
12
+ * the one place an unscoped prefix would destroy data outside this library's.
6
13
  */
7
- export declare function ensureLifecycleRule(client: S3Client, bucket: string, prefix: string, ttlDays: number): Promise<void>;
8
- //# sourceMappingURL=lifecycle.d.ts.map
14
+ export declare function ensureLifecycleRule(client: S3Client, bucket: string, prefix: string, days: number): Promise<void>;
@@ -3,45 +3,61 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ensureLifecycleRule = ensureLifecycleRule;
4
4
  const client_1 = require("./client");
5
5
  const config_1 = require("./config");
6
- async function readRules(client, bucket) {
6
+ async function readState(client, bucket) {
7
7
  const { GetBucketLifecycleConfigurationCommand } = await (0, client_1.loadS3Sdk)();
8
8
  try {
9
9
  const existing = await client.send(new GetBucketLifecycleConfigurationCommand({ Bucket: bucket }));
10
- return existing.Rules ?? [];
10
+ return {
11
+ rules: existing.Rules ?? [],
12
+ transitionDefaultMinimumObjectSize: existing.TransitionDefaultMinimumObjectSize,
13
+ };
11
14
  }
12
15
  catch (error) {
13
16
  if (error.name === 'NoSuchLifecycleConfiguration')
14
- return [];
17
+ return { rules: [] };
15
18
  throw error;
16
19
  }
17
20
  }
18
- function alreadyCorrect(rule, ttlDays) {
19
- return rule?.Status === 'Enabled' && rule.Expiration?.Days === ttlDays;
21
+ function alreadyCorrect(rule, days) {
22
+ return (rule?.Status === 'Enabled' &&
23
+ rule.Expiration?.Days === days &&
24
+ rule.NoncurrentVersionExpiration?.NoncurrentDays === days);
20
25
  }
21
26
  /**
22
- * Idempotently ensure a `${ttlDays}`-day expiration lifecycle rule exists for
23
- * `prefix`. Reads existing rules, preserves user-defined ones, and only
24
- * adds/updates the library's prefix-scoped rule.
27
+ * Idempotently ensure a `days`-day expiration lifecycle rule exists for
28
+ * `prefix`. Reads existing rules, preserves user-defined ones and the
29
+ * bucket-level `TransitionDefaultMinimumObjectSize` (a Put replaces the whole
30
+ * configuration, so dropping it would reset the bucket to the default), and
31
+ * only adds/updates the library's prefix-scoped rule.
32
+ *
33
+ * Noncurrent versions expire after the same number of days, so a versioned
34
+ * bucket does not retain every superseded payload forever; the field is inert
35
+ * on an unversioned bucket. The prefix is re-checked here because this rule is
36
+ * the one place an unscoped prefix would destroy data outside this library's.
25
37
  */
26
- async function ensureLifecycleRule(client, bucket, prefix, ttlDays) {
38
+ async function ensureLifecycleRule(client, bucket, prefix, days) {
39
+ (0, config_1.assertScopedKeyPrefix)(prefix);
27
40
  const ruleId = (0, config_1.buildLifecycleRuleId)(prefix);
28
- const rules = await readRules(client, bucket);
29
- const existing = rules.find((rule) => rule.ID === ruleId);
30
- if (alreadyCorrect(existing, ttlDays))
41
+ const state = await readState(client, bucket);
42
+ const existing = state.rules.find((rule) => rule.ID === ruleId);
43
+ if (alreadyCorrect(existing, days))
31
44
  return;
32
45
  const newRule = {
33
46
  ID: ruleId,
34
47
  Filter: { Prefix: prefix },
35
48
  Status: 'Enabled',
36
- Expiration: { Days: ttlDays },
49
+ Expiration: { Days: days },
50
+ NoncurrentVersionExpiration: { NoncurrentDays: days },
37
51
  };
38
52
  const merged = existing
39
- ? rules.map((rule) => (rule.ID === ruleId ? newRule : rule))
40
- : [...rules, newRule];
53
+ ? state.rules.map((rule) => (rule.ID === ruleId ? newRule : rule))
54
+ : [...state.rules, newRule];
41
55
  const { PutBucketLifecycleConfigurationCommand } = await (0, client_1.loadS3Sdk)();
42
56
  await client.send(new PutBucketLifecycleConfigurationCommand({
43
57
  Bucket: bucket,
44
58
  LifecycleConfiguration: { Rules: merged },
59
+ ...(state.transitionDefaultMinimumObjectSize === undefined
60
+ ? {}
61
+ : { TransitionDefaultMinimumObjectSize: state.transitionDefaultMinimumObjectSize }),
45
62
  }));
46
63
  }
47
- //# sourceMappingURL=lifecycle.js.map
@@ -12,6 +12,7 @@ export declare class S3Offloader {
12
12
  private readonly thresholdBytes;
13
13
  private readonly sse;
14
14
  private readonly sseKmsKeyId?;
15
+ private readonly maxDownloadBytes;
15
16
  private readonly config;
16
17
  constructor(config: S3OffloadConfig);
17
18
  private getClient;
@@ -21,9 +22,13 @@ export declare class S3Offloader {
21
22
  buildKey(parts: readonly string[]): string;
22
23
  /** The configured key prefix. */
23
24
  getKeyPrefix(): string;
25
+ /** True when `key` lies under this offloader's prefix and the `scope` parts' path. */
26
+ ownsKey(key: string, scope: readonly string[]): boolean;
27
+ /** Refuse a row-sourced key outside the row's own path (see {@link assertKeyInScope}). */
28
+ assertOwnedKey(key: string, scope: readonly string[]): void;
24
29
  /** Upload `data` under `key`, returning the key. */
25
30
  upload(key: string, data: Uint8Array): Promise<string>;
26
- /** Download the bytes stored under `key`. */
31
+ /** Download the bytes stored under `key`, refusing objects over `maxDownloadBytes`. */
27
32
  download(key: string): Promise<Uint8Array>;
28
33
  /** Delete `keys`, returning the keys S3 reported as failed. */
29
34
  deleteBatch(keys: string[]): Promise<string[]>;
@@ -37,4 +42,3 @@ export declare class S3Offloader {
37
42
  */
38
43
  destroy(): void;
39
44
  }
40
- //# sourceMappingURL=offloader.d.ts.map
@@ -5,6 +5,7 @@ const constants_1 = require("../../constants");
5
5
  const client_1 = require("./client");
6
6
  const config_1 = require("./config");
7
7
  const delete_1 = require("./delete");
8
+ const key_scope_1 = require("./key-scope");
8
9
  const lifecycle_1 = require("./lifecycle");
9
10
  const read_write_1 = require("./read-write");
10
11
  /**
@@ -20,6 +21,7 @@ class S3Offloader {
20
21
  thresholdBytes;
21
22
  sse;
22
23
  sseKmsKeyId;
24
+ maxDownloadBytes;
23
25
  config;
24
26
  constructor(config) {
25
27
  this.config = config;
@@ -28,10 +30,19 @@ class S3Offloader {
28
30
  this.thresholdBytes = config.thresholdBytes ?? constants_1.DEFAULT_S3_THRESHOLD_BYTES;
29
31
  this.sse = config.serverSideEncryption ?? constants_1.DEFAULT_S3_SSE;
30
32
  this.sseKmsKeyId = config.sseKmsKeyId;
33
+ this.maxDownloadBytes = config.maxDownloadBytes ?? constants_1.DEFAULT_MAX_S3_DOWNLOAD_BYTES;
34
+ /**
35
+ * Warm the optional peer's import so a missing `@aws-sdk/client-s3`
36
+ * surfaces on the very first S3 operation, typed, rather than on the first
37
+ * oversize payload days later. The rejection is handled here; whichever
38
+ * operation runs first re-raises it through its own `loadS3Sdk()` call.
39
+ */
40
+ void (0, client_1.loadS3Sdk)().catch(() => undefined);
31
41
  }
32
42
  getClient() {
33
43
  if (!this.clientPromise) {
34
44
  const cfg = this.config.clientConfig ?? {};
45
+ /** The hook is typed structurally for consumers; the runtime modules use the real SDK client. */
35
46
  this.clientPromise = (this.config.createS3Client
36
47
  ? Promise.resolve(this.config.createS3Client({ maxAttempts: 1, ...cfg }))
37
48
  : (0, client_1.createDefaultS3Client)(cfg)).then((client) => {
@@ -62,6 +73,14 @@ class S3Offloader {
62
73
  getKeyPrefix() {
63
74
  return this.keyPrefix;
64
75
  }
76
+ /** True when `key` lies under this offloader's prefix and the `scope` parts' path. */
77
+ ownsKey(key, scope) {
78
+ return (0, key_scope_1.isKeyInScope)(key, this.keyPrefix, scope);
79
+ }
80
+ /** Refuse a row-sourced key outside the row's own path (see {@link assertKeyInScope}). */
81
+ assertOwnedKey(key, scope) {
82
+ (0, key_scope_1.assertKeyInScope)(key, this.keyPrefix, scope);
83
+ }
65
84
  /** Upload `data` under `key`, returning the key. */
66
85
  async upload(key, data) {
67
86
  await (0, read_write_1.uploadObject)(await this.getClient(), {
@@ -73,9 +92,9 @@ class S3Offloader {
73
92
  });
74
93
  return key;
75
94
  }
76
- /** Download the bytes stored under `key`. */
95
+ /** Download the bytes stored under `key`, refusing objects over `maxDownloadBytes`. */
77
96
  async download(key) {
78
- return (0, read_write_1.downloadObject)(await this.getClient(), this.bucketName, key);
97
+ return (0, read_write_1.downloadObject)(await this.getClient(), this.bucketName, key, this.maxDownloadBytes);
79
98
  }
80
99
  /** Delete `keys`, returning the keys S3 reported as failed. */
81
100
  async deleteBatch(keys) {
@@ -97,4 +116,3 @@ class S3Offloader {
97
116
  }
98
117
  }
99
118
  exports.S3Offloader = S3Offloader;
100
- //# sourceMappingURL=offloader.js.map
@@ -5,6 +5,12 @@ export interface OrphanCleanupOptions {
5
5
  rng?: () => number;
6
6
  maxAttempts?: number;
7
7
  signal?: AbortSignal;
8
+ /**
9
+ * The row's own leading key parts when `keys` were read back from a row.
10
+ * A key outside the path they produce is never deleted, only reported; own
11
+ * uploads (built by this call) pass no scope.
12
+ */
13
+ scope?: readonly string[];
8
14
  }
9
15
  /**
10
16
  * Best-effort delete of S3 objects orphaned by a failed DynamoDB write. Retries
@@ -15,4 +21,3 @@ export interface OrphanCleanupOptions {
15
21
  * `ensureS3LifecycleRule()`, which is opt-in.
16
22
  */
17
23
  export declare function cleanUpS3Orphans(offloader: S3Offloader, keys: ReadonlyArray<string | undefined>, context: string, logger: Logger, options?: OrphanCleanupOptions): Promise<void>;
18
- //# sourceMappingURL=orphans.d.ts.map
@@ -19,6 +19,20 @@ async function backoffSleep(delayMs, options) {
19
19
  return true;
20
20
  }
21
21
  }
22
+ /** Drop every key outside the row's scope, reporting each one. */
23
+ function ownedOnly(offloader, keys, scope, context, logger) {
24
+ return keys.filter((key) => {
25
+ if (offloader.ownsKey(key, scope))
26
+ return true;
27
+ logger.warn(`${context}: refusing to delete an S3 object outside this row's scope`, { key });
28
+ return false;
29
+ });
30
+ }
31
+ /** The non-empty keys, restricted to the row's scope when one is given. */
32
+ function selectOrphans(offloader, keys, context, logger, options) {
33
+ const present = keys.filter((key) => typeof key === 'string' && key.length > 0);
34
+ return options.scope ? ownedOnly(offloader, present, options.scope, context, logger) : present;
35
+ }
22
36
  /**
23
37
  * Best-effort delete of S3 objects orphaned by a failed DynamoDB write. Retries
24
38
  * transient errors with full-jitter backoff; on persistent failure or when S3
@@ -28,7 +42,7 @@ async function backoffSleep(delayMs, options) {
28
42
  * `ensureS3LifecycleRule()`, which is opt-in.
29
43
  */
30
44
  async function cleanUpS3Orphans(offloader, keys, context, logger, options = {}) {
31
- const orphans = keys.filter((key) => typeof key === 'string' && key.length > 0);
45
+ const orphans = selectOrphans(offloader, keys, context, logger, options);
32
46
  if (orphans.length === 0)
33
47
  return;
34
48
  const maxAttempts = options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
@@ -55,4 +69,3 @@ async function cleanUpS3Orphans(offloader, keys, context, logger, options = {})
55
69
  message: lastError.message,
56
70
  });
57
71
  }
58
- //# sourceMappingURL=orphans.js.map
@@ -9,6 +9,10 @@ export interface UploadParams {
9
9
  }
10
10
  /** Upload `data` to S3, wrapping failures as `S3_OFFLOAD_FAILED`. */
11
11
  export declare function uploadObject(client: S3Client, params: UploadParams): Promise<void>;
12
- /** Download an object's bytes, wrapping failures/empty bodies as `S3_OFFLOAD_FAILED`. */
13
- export declare function downloadObject(client: S3Client, bucket: string, key: string): Promise<Uint8Array>;
14
- //# sourceMappingURL=read-write.d.ts.map
12
+ /**
13
+ * Download an object's bytes, wrapping failures/empty bodies as
14
+ * `S3_OFFLOAD_FAILED`. An object over `maxBytes` is refused from its declared
15
+ * `ContentLength` before the body is touched, or while streaming when the
16
+ * length is unknown, so a replaced or hostile object can never exhaust memory.
17
+ */
18
+ export declare function downloadObject(client: S3Client, bucket: string, key: string, maxBytes: number): Promise<Uint8Array>;