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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (409) hide show
  1. package/README.md +390 -193
  2. package/dist/{backfill → cjs/backfill}/backfill.d.ts +15 -12
  3. package/dist/cjs/backfill/backfill.js +177 -0
  4. package/dist/{checkpointer → cjs/checkpointer}/actions/delete-thread.d.ts +1 -1
  5. package/dist/cjs/checkpointer/actions/delete-thread.js +26 -0
  6. package/dist/{checkpointer → cjs/checkpointer}/actions/get-tuple.d.ts +4 -3
  7. package/dist/cjs/checkpointer/actions/get-tuple.js +22 -0
  8. package/dist/{checkpointer → cjs/checkpointer}/actions/list.d.ts +7 -4
  9. package/dist/cjs/checkpointer/actions/list.js +70 -0
  10. package/dist/{checkpointer → cjs/checkpointer}/actions/put-writes.d.ts +8 -6
  11. package/dist/cjs/checkpointer/actions/put-writes.js +21 -0
  12. package/dist/{checkpointer → cjs/checkpointer}/actions/put.d.ts +21 -15
  13. package/dist/cjs/checkpointer/actions/put.js +79 -0
  14. package/dist/{checkpointer → cjs/checkpointer}/internal/delta-history.d.ts +38 -26
  15. package/dist/cjs/checkpointer/internal/delta-history.js +131 -0
  16. package/dist/{checkpointer → cjs/checkpointer}/internal/listing.d.ts +4 -4
  17. package/dist/cjs/checkpointer/internal/listing.js +104 -0
  18. package/dist/{checkpointer → cjs/checkpointer}/internal/parse.d.ts +51 -15
  19. package/dist/cjs/checkpointer/internal/parse.js +184 -0
  20. package/dist/{checkpointer → cjs/checkpointer}/internal/pending-writes.d.ts +64 -25
  21. package/dist/cjs/checkpointer/internal/pending-writes.js +241 -0
  22. package/dist/{checkpointer → cjs/checkpointer}/internal/read.d.ts +15 -10
  23. package/dist/cjs/checkpointer/internal/read.js +132 -0
  24. package/dist/{checkpointer → cjs/checkpointer}/internal/rows.d.ts +94 -21
  25. package/dist/cjs/checkpointer/internal/rows.js +356 -0
  26. package/dist/{checkpointer → cjs/checkpointer}/internal/setup.d.ts +13 -20
  27. package/dist/cjs/checkpointer/internal/setup.js +25 -0
  28. package/dist/{checkpointer → cjs/checkpointer}/saver.d.ts +72 -36
  29. package/dist/cjs/checkpointer/saver.js +56 -0
  30. package/dist/{checkpointer → cjs/checkpointer}/types.d.ts +1 -1
  31. package/dist/cjs/checkpointer/types.js +2 -0
  32. package/dist/{factory → cjs/factory}/factory.d.ts +25 -20
  33. package/dist/cjs/factory/factory.js +137 -0
  34. package/dist/{factory → cjs/factory}/types.d.ts +12 -12
  35. package/dist/cjs/factory/types.js +2 -0
  36. package/dist/{history → cjs/history}/actions/add-messages.d.ts +18 -10
  37. package/dist/cjs/history/actions/add-messages.js +17 -0
  38. package/dist/{history → cjs/history}/actions/clear.d.ts +1 -1
  39. package/dist/cjs/history/actions/clear.js +29 -0
  40. package/dist/{history → cjs/history}/actions/get-messages.d.ts +11 -9
  41. package/dist/cjs/history/actions/get-messages.js +58 -0
  42. package/dist/{history → cjs/history}/actions/list-sessions.d.ts +3 -3
  43. package/dist/cjs/history/actions/list-sessions.js +67 -0
  44. package/dist/{history → cjs/history}/actions/reconcile-count.d.ts +13 -9
  45. package/dist/cjs/history/actions/reconcile-count.js +8 -0
  46. package/dist/{history → cjs/history}/chat-message-history.d.ts +62 -30
  47. package/dist/cjs/history/chat-message-history.js +61 -0
  48. package/dist/{history → cjs/history}/internal/append.d.ts +64 -32
  49. package/dist/cjs/history/internal/append.js +267 -0
  50. package/dist/{history → cjs/history}/internal/message-read.d.ts +3 -3
  51. package/dist/cjs/history/internal/message-read.js +93 -0
  52. package/dist/{history → cjs/history}/internal/parse.d.ts +2 -2
  53. package/dist/cjs/history/internal/parse.js +113 -0
  54. package/dist/{history → cjs/history}/internal/rows.d.ts +11 -10
  55. package/dist/cjs/history/internal/rows.js +96 -0
  56. package/dist/{history → cjs/history}/internal/session.d.ts +41 -22
  57. package/dist/cjs/history/internal/session.js +296 -0
  58. package/dist/{history → cjs/history}/internal/setup.d.ts +2 -2
  59. package/dist/cjs/history/internal/setup.js +60 -0
  60. package/dist/{history → cjs/history}/session-adapter.d.ts +0 -6
  61. package/dist/cjs/history/session-adapter.js +38 -0
  62. package/dist/{history → cjs/history}/types.d.ts +18 -15
  63. package/dist/cjs/history/types.js +2 -0
  64. package/dist/{index.d.ts → cjs/index.d.ts} +27 -27
  65. package/dist/cjs/index.js +25 -0
  66. package/dist/cjs/package.json +1 -0
  67. package/dist/{shared → cjs/shared}/adapter.d.ts +27 -16
  68. package/dist/cjs/shared/adapter.js +70 -0
  69. package/dist/cjs/shared/clock.js +14 -0
  70. package/dist/{shared → cjs/shared}/codec/codec.d.ts +37 -20
  71. package/dist/cjs/shared/codec/codec.js +162 -0
  72. package/dist/{shared → cjs/shared}/codec/compression.d.ts +9 -4
  73. package/dist/cjs/shared/codec/compression.js +45 -0
  74. package/dist/cjs/shared/codec/json-serde.js +58 -0
  75. package/dist/{shared → cjs/shared}/codec/s3/client-types.d.ts +2 -1
  76. package/dist/cjs/shared/codec/s3/client-types.js +6 -0
  77. package/dist/{shared → cjs/shared}/codec/s3/client.d.ts +25 -7
  78. package/dist/cjs/shared/codec/s3/client.js +78 -0
  79. package/dist/{shared → cjs/shared}/codec/s3/config.d.ts +12 -7
  80. package/dist/cjs/shared/codec/s3/config.js +92 -0
  81. package/dist/{shared → cjs/shared}/codec/s3/lifecycle.d.ts +71 -17
  82. package/dist/cjs/shared/codec/s3/lifecycle.js +223 -0
  83. package/dist/{shared → cjs/shared}/codec/s3/offloader.d.ts +42 -29
  84. package/dist/cjs/shared/codec/s3/offloader.js +289 -0
  85. package/dist/cjs/shared/concurrency.js +31 -0
  86. package/dist/{shared → cjs/shared}/dynamodb/abort.d.ts +2 -2
  87. package/dist/cjs/shared/dynamodb/abort.js +16 -0
  88. package/dist/{shared → cjs/shared}/dynamodb/batch-write.d.ts +2 -2
  89. package/dist/cjs/shared/dynamodb/batch-write.js +79 -0
  90. package/dist/cjs/shared/dynamodb/cancellation.js +37 -0
  91. package/dist/{shared → cjs/shared}/dynamodb/client.d.ts +24 -22
  92. package/dist/cjs/shared/dynamodb/client.js +40 -0
  93. package/dist/{shared → cjs/shared}/dynamodb/idempotent-write.d.ts +64 -19
  94. package/dist/cjs/shared/dynamodb/idempotent-write.js +173 -0
  95. package/dist/{shared → cjs/shared}/dynamodb/paginate.d.ts +2 -2
  96. package/dist/cjs/shared/dynamodb/paginate.js +90 -0
  97. package/dist/{shared → cjs/shared}/dynamodb/partition-delete.d.ts +6 -6
  98. package/dist/cjs/shared/dynamodb/partition-delete.js +177 -0
  99. package/dist/{shared → cjs/shared}/dynamodb/recency-index.d.ts +27 -15
  100. package/dist/cjs/shared/dynamodb/recency-index.js +146 -0
  101. package/dist/{shared → cjs/shared}/dynamodb/retry.d.ts +37 -6
  102. package/dist/cjs/shared/dynamodb/retry.js +193 -0
  103. package/dist/cjs/shared/dynamodb/row-size.d.ts +33 -0
  104. package/dist/cjs/shared/dynamodb/row-size.js +30 -0
  105. package/dist/{shared → cjs/shared}/dynamodb/table-schema.d.ts +27 -18
  106. package/dist/cjs/shared/dynamodb/table-schema.js +52 -0
  107. package/dist/{shared → cjs/shared}/errors/base-error.d.ts +42 -7
  108. package/dist/cjs/shared/errors/base-error.js +73 -0
  109. package/dist/{shared → cjs/shared}/errors/boundary.d.ts +29 -14
  110. package/dist/cjs/shared/errors/boundary.js +61 -0
  111. package/dist/cjs/shared/errors/classify.d.ts +206 -0
  112. package/dist/cjs/shared/errors/classify.js +232 -0
  113. package/dist/{shared → cjs/shared}/errors/error-code.d.ts +17 -10
  114. package/dist/cjs/shared/errors/error-code.js +27 -0
  115. package/dist/{shared → cjs/shared}/errors/errors.d.ts +75 -9
  116. package/dist/cjs/shared/errors/errors.js +123 -0
  117. package/dist/cjs/shared/logging/logger.js +30 -0
  118. package/dist/{shared → cjs/shared}/logging/redaction.d.ts +8 -4
  119. package/dist/cjs/shared/logging/redaction.js +145 -0
  120. package/dist/{shared → cjs/shared}/logging/secret-patterns.d.ts +30 -7
  121. package/dist/cjs/shared/logging/secret-patterns.js +93 -0
  122. package/dist/cjs/shared/logging/truncate.js +31 -0
  123. package/dist/{shared → cjs/shared}/options.d.ts +27 -11
  124. package/dist/cjs/shared/options.js +2 -0
  125. package/dist/cjs/shared/ulid.js +83 -0
  126. package/dist/{shared → cjs/shared}/validation/collaborators.d.ts +21 -2
  127. package/dist/cjs/shared/validation/collaborators.js +79 -0
  128. package/dist/{shared → cjs/shared}/validation/option-shape.d.ts +7 -5
  129. package/dist/cjs/shared/validation/option-shape.js +31 -0
  130. package/dist/{shared → cjs/shared}/validation/options.d.ts +4 -4
  131. package/dist/cjs/shared/validation/options.js +166 -0
  132. package/dist/cjs/shared/validation/primitives.js +114 -0
  133. package/dist/{shared → cjs/shared}/validation/ttl.d.ts +26 -9
  134. package/dist/cjs/shared/validation/ttl.js +52 -0
  135. package/dist/{store → cjs/store}/actions/list-namespaces.d.ts +5 -5
  136. package/dist/cjs/store/actions/list-namespaces.js +92 -0
  137. package/dist/{store → cjs/store}/actions/put.d.ts +11 -4
  138. package/dist/cjs/store/actions/put.js +49 -0
  139. package/dist/{store → cjs/store}/actions/reconcile-vector-index.d.ts +5 -5
  140. package/dist/cjs/store/actions/reconcile-vector-index.js +13 -0
  141. package/dist/{store → cjs/store}/actions/search.d.ts +2 -2
  142. package/dist/cjs/store/actions/search.js +26 -0
  143. package/dist/cjs/store/internal/batch-plan.d.ts +56 -0
  144. package/dist/cjs/store/internal/batch-plan.js +32 -0
  145. package/dist/{store → cjs/store}/internal/filter.d.ts +3 -3
  146. package/dist/cjs/store/internal/filter.js +64 -0
  147. package/dist/cjs/store/internal/get-item.d.ts +77 -0
  148. package/dist/cjs/store/internal/get-item.js +58 -0
  149. package/dist/{store → cjs/store}/internal/item-write.d.ts +72 -32
  150. package/dist/cjs/store/internal/item-write.js +181 -0
  151. package/dist/{store → cjs/store}/internal/parse.d.ts +15 -10
  152. package/dist/cjs/store/internal/parse.js +180 -0
  153. package/dist/{store → cjs/store}/internal/rows.d.ts +38 -34
  154. package/dist/cjs/store/internal/rows.js +166 -0
  155. package/dist/{store → cjs/store}/internal/semantic-search.d.ts +2 -2
  156. package/dist/cjs/store/internal/semantic-search.js +211 -0
  157. package/dist/{store → cjs/store}/internal/setup.d.ts +10 -15
  158. package/dist/cjs/store/internal/setup.js +103 -0
  159. package/dist/{store → cjs/store}/internal/table-search.d.ts +5 -5
  160. package/dist/cjs/store/internal/table-search.js +123 -0
  161. package/dist/{store → cjs/store}/internal/vector-index.d.ts +26 -15
  162. package/dist/cjs/store/internal/vector-index.js +269 -0
  163. package/dist/{store → cjs/store}/store.d.ts +82 -39
  164. package/dist/cjs/store/store.js +97 -0
  165. package/dist/{store → cjs/store}/types.d.ts +25 -10
  166. package/dist/cjs/store/types.js +2 -0
  167. package/dist/cjs/store/vector-backend.js +4 -0
  168. package/dist/esm/backfill/backfill.d.ts +171 -0
  169. package/dist/esm/backfill/backfill.js +170 -0
  170. package/dist/{checkpointer/actions/delete-thread.js → esm/checkpointer/actions/delete-thread.d.ts} +4 -26
  171. package/dist/esm/checkpointer/actions/delete-thread.js +23 -0
  172. package/dist/{checkpointer/actions/get-tuple.js → esm/checkpointer/actions/get-tuple.d.ts} +7 -24
  173. package/dist/esm/checkpointer/actions/get-tuple.js +19 -0
  174. package/dist/esm/checkpointer/actions/list.d.ts +55 -0
  175. package/dist/esm/checkpointer/actions/list.js +67 -0
  176. package/dist/{checkpointer/actions/put-writes.js → esm/checkpointer/actions/put-writes.d.ts} +10 -37
  177. package/dist/esm/checkpointer/actions/put-writes.js +18 -0
  178. package/dist/esm/checkpointer/actions/put.d.ts +95 -0
  179. package/dist/esm/checkpointer/actions/put.js +75 -0
  180. package/dist/esm/checkpointer/internal/delta-history.d.ts +124 -0
  181. package/dist/esm/checkpointer/internal/delta-history.js +126 -0
  182. package/dist/{checkpointer/internal/listing.js → esm/checkpointer/internal/listing.d.ts} +22 -118
  183. package/dist/esm/checkpointer/internal/listing.js +95 -0
  184. package/dist/esm/checkpointer/internal/parse.d.ts +298 -0
  185. package/dist/esm/checkpointer/internal/parse.js +169 -0
  186. package/dist/esm/checkpointer/internal/pending-writes.d.ts +314 -0
  187. package/dist/esm/checkpointer/internal/pending-writes.js +229 -0
  188. package/dist/esm/checkpointer/internal/read.d.ts +135 -0
  189. package/dist/esm/checkpointer/internal/read.js +125 -0
  190. package/dist/esm/checkpointer/internal/rows.d.ts +644 -0
  191. package/dist/esm/checkpointer/internal/rows.js +323 -0
  192. package/dist/esm/checkpointer/internal/setup.d.ts +47 -0
  193. package/dist/esm/checkpointer/internal/setup.js +21 -0
  194. package/dist/{checkpointer/saver.js → esm/checkpointer/saver.d.ts} +84 -87
  195. package/dist/esm/checkpointer/saver.js +52 -0
  196. package/dist/esm/checkpointer/types.d.ts +51 -0
  197. package/dist/esm/checkpointer/types.js +1 -0
  198. package/dist/esm/factory/factory.d.ts +154 -0
  199. package/dist/esm/factory/factory.js +133 -0
  200. package/dist/esm/factory/types.d.ts +76 -0
  201. package/dist/esm/factory/types.js +1 -0
  202. package/dist/{history/actions/add-messages.js → esm/history/actions/add-messages.d.ts} +20 -26
  203. package/dist/esm/history/actions/add-messages.js +14 -0
  204. package/dist/{history/actions/clear.js → esm/history/actions/clear.d.ts} +4 -35
  205. package/dist/esm/history/actions/clear.js +26 -0
  206. package/dist/esm/history/actions/get-messages.d.ts +60 -0
  207. package/dist/esm/history/actions/get-messages.js +55 -0
  208. package/dist/esm/history/actions/list-sessions.d.ts +55 -0
  209. package/dist/esm/history/actions/list-sessions.js +64 -0
  210. package/dist/{history/actions/reconcile-count.js → esm/history/actions/reconcile-count.d.ts} +14 -16
  211. package/dist/esm/history/actions/reconcile-count.js +5 -0
  212. package/dist/{history/chat-message-history.js → esm/history/chat-message-history.d.ts} +76 -87
  213. package/dist/esm/history/chat-message-history.js +57 -0
  214. package/dist/esm/history/internal/append.d.ts +244 -0
  215. package/dist/esm/history/internal/append.js +259 -0
  216. package/dist/esm/history/internal/message-read.d.ts +84 -0
  217. package/dist/esm/history/internal/message-read.js +89 -0
  218. package/dist/esm/history/internal/parse.d.ts +153 -0
  219. package/dist/esm/history/internal/parse.js +105 -0
  220. package/dist/{history/internal/rows.js → esm/history/internal/rows.d.ts} +58 -112
  221. package/dist/esm/history/internal/rows.js +83 -0
  222. package/dist/esm/history/internal/session.d.ts +350 -0
  223. package/dist/esm/history/internal/session.js +285 -0
  224. package/dist/esm/history/internal/setup.d.ts +64 -0
  225. package/dist/esm/history/internal/setup.js +56 -0
  226. package/dist/{history/session-adapter.js → esm/history/session-adapter.d.ts} +25 -39
  227. package/dist/esm/history/session-adapter.js +34 -0
  228. package/dist/esm/history/types.d.ts +102 -0
  229. package/dist/esm/history/types.js +1 -0
  230. package/dist/esm/index.d.ts +53 -0
  231. package/dist/esm/index.js +10 -0
  232. package/dist/esm/shared/adapter.d.ts +146 -0
  233. package/dist/esm/shared/adapter.js +65 -0
  234. package/dist/{shared/clock.js → esm/shared/clock.d.ts} +3 -14
  235. package/dist/esm/shared/clock.js +9 -0
  236. package/dist/esm/shared/codec/codec.d.ts +336 -0
  237. package/dist/esm/shared/codec/codec.js +150 -0
  238. package/dist/esm/shared/codec/compression.d.ts +66 -0
  239. package/dist/esm/shared/codec/compression.js +40 -0
  240. package/dist/esm/shared/codec/json-serde.d.ts +80 -0
  241. package/dist/esm/shared/codec/json-serde.js +54 -0
  242. package/dist/esm/shared/codec/s3/client-types.d.ts +54 -0
  243. package/dist/esm/shared/codec/s3/client-types.js +3 -0
  244. package/dist/esm/shared/codec/s3/client.d.ts +63 -0
  245. package/dist/esm/shared/codec/s3/client.js +40 -0
  246. package/dist/{shared/codec/s3/config.js → esm/shared/codec/s3/config.d.ts} +45 -93
  247. package/dist/esm/shared/codec/s3/config.js +79 -0
  248. package/dist/esm/shared/codec/s3/lifecycle.d.ts +220 -0
  249. package/dist/esm/shared/codec/s3/lifecycle.js +214 -0
  250. package/dist/esm/shared/codec/s3/offloader.d.ts +428 -0
  251. package/dist/esm/shared/codec/s3/offloader.js +278 -0
  252. package/dist/{shared/concurrency.js → esm/shared/concurrency.d.ts} +2 -37
  253. package/dist/esm/shared/concurrency.js +27 -0
  254. package/dist/{shared/dynamodb/abort.js → esm/shared/dynamodb/abort.d.ts} +4 -16
  255. package/dist/esm/shared/dynamodb/abort.js +12 -0
  256. package/dist/esm/shared/dynamodb/batch-write.d.ts +86 -0
  257. package/dist/esm/shared/dynamodb/batch-write.js +74 -0
  258. package/dist/{shared/dynamodb/cancellation.js → esm/shared/dynamodb/cancellation.d.ts} +25 -53
  259. package/dist/esm/shared/dynamodb/cancellation.js +30 -0
  260. package/dist/{shared/dynamodb/client.js → esm/shared/dynamodb/client.d.ts} +74 -64
  261. package/dist/esm/shared/dynamodb/client.js +35 -0
  262. package/dist/{shared/dynamodb/idempotent-write.js → esm/shared/dynamodb/idempotent-write.d.ts} +172 -169
  263. package/dist/esm/shared/dynamodb/idempotent-write.js +153 -0
  264. package/dist/esm/shared/dynamodb/paginate.d.ts +111 -0
  265. package/dist/esm/shared/dynamodb/paginate.js +84 -0
  266. package/dist/esm/shared/dynamodb/partition-delete.d.ts +204 -0
  267. package/dist/esm/shared/dynamodb/partition-delete.js +171 -0
  268. package/dist/esm/shared/dynamodb/recency-index.d.ts +243 -0
  269. package/dist/esm/shared/dynamodb/recency-index.js +136 -0
  270. package/dist/esm/shared/dynamodb/retry.d.ts +317 -0
  271. package/dist/esm/shared/dynamodb/retry.js +180 -0
  272. package/dist/esm/shared/dynamodb/row-size.d.ts +33 -0
  273. package/dist/esm/shared/dynamodb/row-size.js +26 -0
  274. package/dist/{shared/dynamodb/table-schema.js → esm/shared/dynamodb/table-schema.d.ts} +57 -67
  275. package/dist/esm/shared/dynamodb/table-schema.js +43 -0
  276. package/dist/esm/shared/errors/base-error.d.ts +231 -0
  277. package/dist/esm/shared/errors/base-error.js +64 -0
  278. package/dist/esm/shared/errors/boundary.d.ts +86 -0
  279. package/dist/esm/shared/errors/boundary.js +54 -0
  280. package/dist/esm/shared/errors/classify.d.ts +206 -0
  281. package/dist/esm/shared/errors/classify.js +220 -0
  282. package/dist/{shared/errors/error-code.js → esm/shared/errors/error-code.d.ts} +39 -43
  283. package/dist/esm/shared/errors/error-code.js +24 -0
  284. package/dist/{shared/errors/errors.js → esm/shared/errors/errors.d.ts} +92 -98
  285. package/dist/esm/shared/errors/errors.js +110 -0
  286. package/dist/{shared/logging/logger.js → esm/shared/logging/logger.d.ts} +22 -52
  287. package/dist/esm/shared/logging/logger.js +25 -0
  288. package/dist/esm/shared/logging/redaction.d.ts +123 -0
  289. package/dist/esm/shared/logging/redaction.js +140 -0
  290. package/dist/{shared/logging/secret-patterns.js → esm/shared/logging/secret-patterns.d.ts} +46 -87
  291. package/dist/esm/shared/logging/secret-patterns.js +83 -0
  292. package/dist/{shared/logging/truncate.js → esm/shared/logging/truncate.d.ts} +6 -40
  293. package/dist/esm/shared/logging/truncate.js +25 -0
  294. package/dist/esm/shared/options.d.ts +100 -0
  295. package/dist/esm/shared/options.js +1 -0
  296. package/dist/{shared/ulid.js → esm/shared/ulid.d.ts} +4 -84
  297. package/dist/esm/shared/ulid.js +77 -0
  298. package/dist/{shared/validation/collaborators.js → esm/shared/validation/collaborators.d.ts} +37 -65
  299. package/dist/esm/shared/validation/collaborators.js +70 -0
  300. package/dist/{shared/validation/option-shape.js → esm/shared/validation/option-shape.d.ts} +14 -36
  301. package/dist/esm/shared/validation/option-shape.js +24 -0
  302. package/dist/esm/shared/validation/options.d.ts +145 -0
  303. package/dist/esm/shared/validation/options.js +156 -0
  304. package/dist/{shared/validation/primitives.js → esm/shared/validation/primitives.d.ts} +30 -125
  305. package/dist/esm/shared/validation/primitives.js +100 -0
  306. package/dist/esm/shared/validation/ttl.d.ts +94 -0
  307. package/dist/esm/shared/validation/ttl.js +46 -0
  308. package/dist/esm/store/actions/list-namespaces.d.ts +79 -0
  309. package/dist/esm/store/actions/list-namespaces.js +86 -0
  310. package/dist/esm/store/actions/put.d.ts +43 -0
  311. package/dist/esm/store/actions/put.js +46 -0
  312. package/dist/{store/actions/reconcile-vector-index.js → esm/store/actions/reconcile-vector-index.d.ts} +8 -16
  313. package/dist/esm/store/actions/reconcile-vector-index.js +10 -0
  314. package/dist/esm/store/actions/search.d.ts +38 -0
  315. package/dist/esm/store/actions/search.js +23 -0
  316. package/dist/esm/store/internal/batch-plan.d.ts +56 -0
  317. package/dist/esm/store/internal/batch-plan.js +28 -0
  318. package/dist/esm/store/internal/filter.d.ts +43 -0
  319. package/dist/esm/store/internal/filter.js +60 -0
  320. package/dist/esm/store/internal/get-item.d.ts +77 -0
  321. package/dist/esm/store/internal/get-item.js +54 -0
  322. package/dist/esm/store/internal/item-write.d.ts +270 -0
  323. package/dist/esm/store/internal/item-write.js +173 -0
  324. package/dist/esm/store/internal/parse.d.ts +230 -0
  325. package/dist/esm/store/internal/parse.js +169 -0
  326. package/dist/{store/internal/rows.js → esm/store/internal/rows.d.ts} +111 -199
  327. package/dist/esm/store/internal/rows.js +147 -0
  328. package/dist/esm/store/internal/semantic-search.d.ts +168 -0
  329. package/dist/esm/store/internal/semantic-search.js +200 -0
  330. package/dist/esm/store/internal/setup.d.ts +96 -0
  331. package/dist/esm/store/internal/setup.js +98 -0
  332. package/dist/esm/store/internal/table-search.d.ts +100 -0
  333. package/dist/esm/store/internal/table-search.js +119 -0
  334. package/dist/esm/store/internal/vector-index.d.ts +258 -0
  335. package/dist/esm/store/internal/vector-index.js +256 -0
  336. package/dist/{store/store.js → esm/store/store.d.ts} +99 -133
  337. package/dist/esm/store/store.js +93 -0
  338. package/dist/esm/store/types.d.ts +111 -0
  339. package/dist/esm/store/types.js +1 -0
  340. package/dist/esm/store/vector-backend.d.ts +104 -0
  341. package/dist/esm/store/vector-backend.js +1 -0
  342. package/package.json +50 -44
  343. package/dist/backfill/backfill.js +0 -393
  344. package/dist/checkpointer/actions/list.js +0 -142
  345. package/dist/checkpointer/actions/put.js +0 -195
  346. package/dist/checkpointer/internal/delta-history.js +0 -252
  347. package/dist/checkpointer/internal/parse.js +0 -372
  348. package/dist/checkpointer/internal/pending-writes.js +0 -588
  349. package/dist/checkpointer/internal/read.js +0 -264
  350. package/dist/checkpointer/internal/rows.js +0 -834
  351. package/dist/checkpointer/internal/setup.js +0 -72
  352. package/dist/checkpointer/types.js +0 -12
  353. package/dist/factory/factory.js +0 -266
  354. package/dist/factory/types.js +0 -10
  355. package/dist/history/actions/get-messages.js +0 -141
  356. package/dist/history/actions/list-sessions.js +0 -156
  357. package/dist/history/internal/append.js +0 -500
  358. package/dist/history/internal/message-read.js +0 -204
  359. package/dist/history/internal/parse.js +0 -252
  360. package/dist/history/internal/session.js +0 -628
  361. package/dist/history/internal/setup.js +0 -106
  362. package/dist/history/types.js +0 -12
  363. package/dist/index.js +0 -51
  364. package/dist/shared/adapter.js +0 -143
  365. package/dist/shared/codec/codec.js +0 -441
  366. package/dist/shared/codec/compression.js +0 -89
  367. package/dist/shared/codec/json-serde.js +0 -191
  368. package/dist/shared/codec/s3/client-types.js +0 -26
  369. package/dist/shared/codec/s3/client.js +0 -97
  370. package/dist/shared/codec/s3/lifecycle.js +0 -355
  371. package/dist/shared/codec/s3/offloader.js +0 -658
  372. package/dist/shared/dynamodb/batch-write.js +0 -173
  373. package/dist/shared/dynamodb/paginate.js +0 -188
  374. package/dist/shared/dynamodb/partition-delete.js +0 -340
  375. package/dist/shared/dynamodb/recency-index.js +0 -377
  376. package/dist/shared/dynamodb/retry.js +0 -463
  377. package/dist/shared/errors/base-error.js +0 -174
  378. package/dist/shared/errors/boundary.js +0 -143
  379. package/dist/shared/errors/classify.d.ts +0 -97
  380. package/dist/shared/errors/classify.js +0 -257
  381. package/dist/shared/logging/redaction.js +0 -316
  382. package/dist/shared/options.js +0 -11
  383. package/dist/shared/validation/options.js +0 -328
  384. package/dist/shared/validation/ttl.js +0 -132
  385. package/dist/store/actions/list-namespaces.js +0 -197
  386. package/dist/store/actions/put.js +0 -78
  387. package/dist/store/actions/search.js +0 -66
  388. package/dist/store/internal/batch-plan.d.ts +0 -26
  389. package/dist/store/internal/batch-plan.js +0 -109
  390. package/dist/store/internal/filter.js +0 -137
  391. package/dist/store/internal/get-item.d.ts +0 -45
  392. package/dist/store/internal/get-item.js +0 -115
  393. package/dist/store/internal/item-write.js +0 -463
  394. package/dist/store/internal/parse.js +0 -350
  395. package/dist/store/internal/semantic-search.js +0 -389
  396. package/dist/store/internal/setup.js +0 -223
  397. package/dist/store/internal/table-search.js +0 -213
  398. package/dist/store/internal/vector-index.js +0 -546
  399. package/dist/store/types.js +0 -15
  400. package/dist/store/vector-backend.js +0 -17
  401. /package/dist/{shared → cjs/shared}/clock.d.ts +0 -0
  402. /package/dist/{shared → cjs/shared}/codec/json-serde.d.ts +0 -0
  403. /package/dist/{shared → cjs/shared}/concurrency.d.ts +0 -0
  404. /package/dist/{shared → cjs/shared}/dynamodb/cancellation.d.ts +0 -0
  405. /package/dist/{shared → cjs/shared}/logging/logger.d.ts +0 -0
  406. /package/dist/{shared → cjs/shared}/logging/truncate.d.ts +0 -0
  407. /package/dist/{shared → cjs/shared}/ulid.d.ts +0 -0
  408. /package/dist/{shared → cjs/shared}/validation/primitives.d.ts +0 -0
  409. /package/dist/{store → cjs/store}/vector-backend.d.ts +0 -0
@@ -1,191 +0,0 @@
1
- "use strict";
2
- /**
3
- * Hides the JSON form: writing it, reading it, and recognising it.
4
- *
5
- * The default serde writes a value as JSON under the `json` type and reads
6
- * back only that type; the codec also asks, when a serde refuses stored bytes,
7
- * whether those bytes are still JSON at all, which tells a corrupt payload from
8
- * a serde that would not reconstruct it.
9
- */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.JSON_SERDE = void 0;
12
- exports.bytesHoldDeclaredForm = bytesHoldDeclaredForm;
13
- const base_error_1 = require("../errors/base-error");
14
- const error_code_1 = require("../errors/error-code");
15
- const errors_1 = require("../errors/errors");
16
- const truncate_1 = require("../logging/truncate");
17
- /**
18
- * A plain JSON serializer implementing LangGraph's `SerializerProtocol`:
19
- * the default `serde` of `DynamoDBStore` and `DynamoDBChatMessageHistory`, and
20
- * the alternative a `DynamoDBSaver` can be given in place of LangGraph's
21
- * `JsonPlusSerializer`.
22
- *
23
- * It is exported so that choice is available. The checkpointer's default
24
- * revives a stored `{"lc": …}` record by instantiating the class the record
25
- * names, so the row selects which constructor runs on read; this serializer
26
- * runs `JSON.parse` and nothing else, and reconstructs no class at all.
27
- * Reading with it is the narrower trust boundary, and the price is stated
28
- * below: it stores the JSON projection of a value, not the value.
29
- *
30
- * `dumpsTyped` accepts any value `JSON.stringify` can represent and refuses the
31
- * rest. A value it cannot represent — `undefined`, a function, a symbol —
32
- * stringifies to `undefined` and would be stored as **zero bytes**, which reads
33
- * back as a parse error; a circular structure or a `BigInt` makes it throw. Both
34
- * are reported as `VALIDATION` naming `value`, at the write, rather than
35
- * as an unreadable row later — with the refusal attached as `cause` and never
36
- * quoted into the message, which for a circular structure names the caller's
37
- * own properties and classes.
38
- *
39
- * What it represents, it represents as JSON, which is lossy in ways nothing
40
- * records: a `Map` or `Set` stores as `{}`, an object key whose value is
41
- * `undefined` is dropped and an array element is stored as `null`, `NaN` and
42
- * `Infinity` store as `null`, `-0` as `0`, a `Uint8Array` as an index-keyed
43
- * object and a `Date` as an ISO string. The README's *Table schema* section
44
- * holds the whole table, against the checkpointer default column by column.
45
- *
46
- * `loadsTyped` reads only the `json` form it writes, and says
47
- * so before it looks at a byte. Any other declared form is a `VALIDATION` error
48
- * naming `serde`, because it says what *this* reader may rebuild and not that
49
- * the payload is damaged. Bytes of that form which do not parse are
50
- * `PAYLOAD_CORRUPT`, because they can never be read and the caller should
51
- * report rather than retry; a `data` that is not bytes at all is a
52
- * `VALIDATION` naming `data`, because that is the caller's mistake and
53
- * not a row's.
54
- *
55
- * Frozen for the reason {@link ErrorCode} is: one object, shared by every
56
- * adapter in the process that did not pass a `serde` of its own, and
57
- * reachable from the package root. An assignment to `dumpsTyped` by any one
58
- * consumer would silently change how every other one writes.
59
- */
60
- exports.JSON_SERDE = {
61
- async dumpsTyped(value) {
62
- let text;
63
- try {
64
- text = JSON.stringify(value);
65
- }
66
- catch (error) {
67
- // The refusal travels as `cause`, never as text. V8 writes the path it
68
- // walked into the message it throws for a circular structure, quoting
69
- // the caller's own property names and constructor names — and this
70
- // package does not compose a public `err.message` out of a caller's
71
- // identifiers, which an application may print, log or return in a
72
- // response. `redactedMessage` removes credential shapes, not names, so
73
- // it never covered this. A caller who wants the path reads `cause`.
74
- throw (0, errors_1.validationError)('value cannot be serialized as JSON — a circular structure, or a value JSON has no ' +
75
- 'encoding for such as a BigInt; the refusal itself is attached as `cause`', 'value', (0, base_error_1.toError)(error));
76
- }
77
- if (text === undefined) {
78
- throw (0, errors_1.validationError)('value has no JSON representation (undefined, a function or a symbol), so it cannot be ' +
79
- 'stored; store null instead to record an absent value', 'value');
80
- }
81
- // `dumpsTyped` stays `async` because the two throws above must reach a
82
- // caller as a rejection even when it is called without `await` (a bare
83
- // `.catch()`), which a plain synchronous throw would not do. Returning
84
- // `Promise.resolve(...)` here — rather than the bare tuple — is what
85
- // satisfies `require-await`: the rule accepts a `return` of a thenable
86
- // value in place of an explicit `await`, and needs no `await` to do it.
87
- return Promise.resolve([JSON_SERDE_TYPE, new TextEncoder().encode(text)]);
88
- },
89
- async loadsTyped(type, data) {
90
- // The declared form is honoured, and honoured first. Ignoring it left this
91
- // serializer answering for forms it has no grammar for: a row stamped
92
- // `bytes` by the checkpointer's default — what that serializer writes for a
93
- // raw `Uint8Array` — parsed here as JSON and returned a *different value*
94
- // whenever those bytes happened to be valid JSON, and returned this
95
- // serializer's own `PAYLOAD_CORRUPT` when they were not. The second reading
96
- // is the one that cost data: the codec passes an already-branded refusal
97
- // through untouched, so `bytesHoldDeclaredForm` never ran, the row was
98
- // filed as permanent loss, and history's default `onCorruptMessage: 'skip'`
99
- // dropped the message. The same row read through the checkpointer's own
100
- // default was reported as a refusal instead, so which serde an adapter
101
- // carried decided whether a turn survived the read.
102
- //
103
- // A form this serializer cannot rebuild a value from is a statement about
104
- // this reader, not about the payload, so it names `serde` — the same brand
105
- // the codec puts on `JsonPlusSerializer`'s `Unknown serialization type`,
106
- // which is what makes the two agree. The type is quoted from the row, so it
107
- // is bounded, for the reason `truncateForLog` states.
108
- if (type !== JSON_SERDE_TYPE) {
109
- throw (0, errors_1.validationError)(`this serializer reads only the \`${JSON_SERDE_TYPE}\` form it writes, and this payload ` +
110
- `declares ${(0, truncate_1.truncateForLog)(String(JSON.stringify(type)))}; read the row with the ` +
111
- 'serializer that wrote it, or rewrite the row', 'serde');
112
- }
113
- let text;
114
- // The decode is inside a guard of its own because it fails for a different
115
- // reason than the parse does, and names it separately. UTF-8 decoding is
116
- // lenient — a malformed byte becomes U+FFFD rather than an error — so the
117
- // only way `TextDecoder` refuses is a `data` that is not bytes at all,
118
- // which is the caller's mistake and not a corrupt row. The codec always
119
- // passes a `Uint8Array`; a direct caller passing anything else would
120
- // otherwise get a bare `TypeError` from Node naming an argument called
121
- // "list".
122
- try {
123
- text = typeof data === 'string' ? data : new TextDecoder().decode(data);
124
- }
125
- catch (error) {
126
- throw (0, errors_1.validationError)('data must be the bytes or text this serializer wrote, as a Uint8Array or a string', 'data', error);
127
- }
128
- try {
129
- // Same reasoning as `dumpsTyped`'s final return: see its comment.
130
- return Promise.resolve(JSON.parse(text));
131
- }
132
- catch (error) {
133
- throw new base_error_1.DynamoDBLangGraphError('the stored payload is not the JSON this serializer wrote, so it cannot be decoded', error_code_1.ErrorCode.PAYLOAD_CORRUPT, {}, error);
134
- }
135
- },
136
- };
137
- Object.freeze(exports.JSON_SERDE);
138
- /**
139
- * The one `serdeType` whose grammar this package can check for itself: the type
140
- * `JSON_SERDE` stamps on everything it writes, and the one LangGraph's
141
- * own `JsonPlusSerializer` stamps on every value but a raw `Uint8Array`, which
142
- * it stamps `bytes`.
143
- *
144
- * The one constant is shared by the serializer that writes this form and the
145
- * check that re-derives it, within this module. They had each decided
146
- * separately what they understood: the check took any other type at its
147
- * word, while `JSON_SERDE` ignored the declared type and ran `JSON.parse` on
148
- * whatever it was handed. A row declaring a form neither of them writes was
149
- * therefore classified one way through one serializer and the opposite way
150
- * through the other — and a row declaring `bytes`, which the checkpointer's
151
- * default writes for a raw `Uint8Array`, decoded to a *different value*
152
- * rather than failing at all when its bytes happened to parse as JSON.
153
- */
154
- const JSON_SERDE_TYPE = 'json';
155
- /**
156
- * Whether stored bytes are still the form the row that holds them declares.
157
- *
158
- * This is the structural question behind the two ways a decode fails —
159
- * `PAYLOAD_CORRUPT` for bytes no reader can decode, and the `serde` refusal for
160
- * bytes *this* reader will not rebuild a value from — and it is the only one
161
- * this package can answer on its own. `SerializerProtocol` offers no way to ask
162
- * a serde whether it parsed the bytes before deciding not to reconstruct what
163
- * they name, and the refusal it throws is a caller's object: its class, its
164
- * fields and its prose are all whatever that caller chose. Classifying a
165
- * payload by any of those would make the code mean "a third party said so",
166
- * which is exactly what neither code may mean.
167
- *
168
- * Accepts: `serdeType` — the type stamped on the row, as the descriptor carries
169
- * it. `bytes` — what the row stored, already decompressed.
170
- *
171
- * Returns: whether the bytes still parse as the declared form. A type this
172
- * package has no grammar for is taken at its word and answers `true`, so its
173
- * serde's refusal is reported rather than written off: dropping a payload this
174
- * reader merely cannot check would lose data on nothing but its own ignorance.
175
- *
176
- * Throws: **nothing**, for any bytes. It is called from inside the `catch` that
177
- * is classifying a decode failure, where a throw would replace the failure
178
- * being reported — and the value it is handed came off a row, so it may be
179
- * anything that row's writer stored.
180
- */
181
- function bytesHoldDeclaredForm(serdeType, bytes) {
182
- if (serdeType !== JSON_SERDE_TYPE)
183
- return true;
184
- try {
185
- JSON.parse(new TextDecoder().decode(bytes));
186
- return true;
187
- }
188
- catch {
189
- return false;
190
- }
191
- }
@@ -1,26 +0,0 @@
1
- "use strict";
2
- /**
3
- * Hides the S3 SDK's own types from this package's declarations.
4
- *
5
- * The S3 client, its config and a command are described by the members this
6
- * package touches, so no shipped declaration imports the optional
7
- * `@aws-sdk/client-s3` peer and a caller without it installed still compiles
8
- * (record 1). A real `S3Client` or `S3ClientConfig` satisfies these shapes as
9
- * it is, so a caller who has the SDK passes its own values unchanged.
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.s3ClientOptions = s3ClientOptions;
13
- /**
14
- * The options of a config, read through the structural type.
15
- *
16
- * Accepts: a config as the caller gave it, or nothing.
17
- *
18
- * Returns: the same object seen as {@link S3ClientOptions} so `region` and
19
- * `maxAttempts` can be read; an absent config reads as empty rather than
20
- * needing a guard at every call site.
21
- *
22
- * Throws: nothing.
23
- */
24
- function s3ClientOptions(config) {
25
- return (config ?? {});
26
- }
@@ -1,97 +0,0 @@
1
- "use strict";
2
- /**
3
- * Hides that the S3 SDK is loaded on first use, and how its client is set up.
4
- *
5
- * An adapter without offload never imports the optional peer; the first
6
- * offload does, once, and a missing install surfaces as `VALIDATION` naming
7
- * the remedy (record 1). The client built here defaults to no retries of its
8
- * own — `maxAttempts: 1` — so this package's retry is the only layer unless a
9
- * caller's own `maxAttempts` overrides it (record 14), and its idle timer
10
- * bounds a stalled transfer without bounding a slow one.
11
- */
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.loadS3Sdk = loadS3Sdk;
14
- exports.createDefaultS3Client = createDefaultS3Client;
15
- const client_1 = require("../../dynamodb/client");
16
- const errors_1 = require("../../errors/errors");
17
- /** Codes Node and bundlers use for an import that cannot be resolved. */
18
- const MISSING_MODULE_CODES = ['ERR_MODULE_NOT_FOUND', 'MODULE_NOT_FOUND'];
19
- let sdkPromise;
20
- /**
21
- * Convert a failed import of the optional peer into a typed error that names
22
- * the remedy. Any other failure (a broken build, a syntax error inside the
23
- * package) passes through unchanged.
24
- */
25
- function wrapMissingPeer(error) {
26
- const code = error.code;
27
- if (code !== undefined && MISSING_MODULE_CODES.includes(code)) {
28
- throw (0, errors_1.validationError)('S3 offload requires the optional peer @aws-sdk/client-s3 (npm install @aws-sdk/client-s3); ' +
29
- 'bundlers must keep it installed or external', 's3', error);
30
- }
31
- throw error;
32
- }
33
- /**
34
- * The optional `@aws-sdk/client-s3` peer, imported on first use.
35
- *
36
- * Accepts: nothing. Concurrent callers share one import.
37
- *
38
- * Returns: the module, cached for every later call.
39
- *
40
- * Throws: `VALIDATION` naming `s3` when the package is not installed,
41
- * carrying the install command; any other import failure — a broken build, a
42
- * syntax error inside the package — passes through unchanged. A failure is not
43
- * cached, so an install or a fixed bundle succeeds on a later call.
44
- */
45
- async function loadS3Sdk() {
46
- if (!sdkPromise) {
47
- sdkPromise = import('@aws-sdk/client-s3').catch((error) => {
48
- sdkPromise = undefined;
49
- return wrapMissingPeer(error);
50
- });
51
- }
52
- return sdkPromise;
53
- }
54
- /**
55
- * An `S3Client` built from `config` with the lazily-loaded SDK.
56
- *
57
- * Accepts: `config` — any `S3ClientConfig`; an explicit `maxAttempts` or
58
- * `requestHandler` wins over the defaults below.
59
- *
60
- * Returns: the client. The caller owns it and destroys it.
61
- *
62
- * Throws: whatever {@link loadS3Sdk} throws.
63
- *
64
- * Guarantees: `maxAttempts` defaults to 1, so the SDK performs no retries of
65
- * its own and this library's retry, backoff and classification are the only
66
- * retry layer — the same default `resolveDynamoDBClient` applies on the
67
- * DynamoDB side. A default request handler bounds a transfer that has
68
- * stalled, which `maxAttempts` alone does not; a `requestHandler` in `config`
69
- * replaces it whole rather than merging with it.
70
- */
71
- async function createDefaultS3Client(config) {
72
- const { S3Client: S3ClientCtor } = await loadS3Sdk();
73
- // One field, where the DynamoDB client gets three, and the asymmetry is
74
- // deliberate. `requestTimeout` bounds request creation until response
75
- // *headers* arrive, and a `PutObject`'s headers arrive only once the whole
76
- // body has been uploaded — so here it would be a bound on upload duration,
77
- // over payloads running from the offload threshold to the download cap, and
78
- // a legitimate large upload on a slow link would be destroyed for being
79
- // slow. `socketTimeout` is an idle timer that any activity in either
80
- // direction resets, so it separates a stalled transfer from a slow one.
81
- // `throwOnRequestTimeout` is absent because without a request timeout it has
82
- // nothing to act on, and `connectionTimeout` because its timer counts the
83
- // wait behind the agent's sockets, which this path fans out across.
84
- //
85
- // What this bounds is a transfer stalled after its socket was assigned, not
86
- // the whole attempt: nothing here bounds the time a request spends queued
87
- // for a socket, and an idle timer is not a deadline, so a large upload's
88
- // total duration stays unbounded. At or above 2 MiB the SDK sends
89
- // `Expect: 100-continue` and the handler then waits six seconds for the
90
- // continue on a throwaway agent, so the five-second idle timer is what
91
- // fires first — the one place the two timers race.
92
- return new S3ClientCtor({
93
- maxAttempts: 1,
94
- requestHandler: { socketTimeout: client_1.DEFAULT_SOCKET_TIMEOUT_MS },
95
- ...config,
96
- });
97
- }
@@ -1,355 +0,0 @@
1
- "use strict";
2
- /**
3
- * Hides the bucket lifecycle configuration this package maintains.
4
- *
5
- * Two rules per prefix — one expiring objects a day after the ttl plus the
6
- * sweep margin and keeping a released payload's noncurrent version for a grace
7
- * window, one reclaiming expired delete markers — are written without
8
- * disturbing any other rule on the bucket, rewritten only when they differ,
9
- * and followed by a report of whether the bucket keeps versions at all.
10
- */
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.S3_RELEASE_GRACE_DAYS = void 0;
13
- exports.ensureLifecycleRule = ensureLifecycleRule;
14
- exports.ttlRule = ttlRule;
15
- exports.markerRule = markerRule;
16
- exports.assertNoIdCollision = assertNoIdCollision;
17
- exports.alreadyCorrect = alreadyCorrect;
18
- exports.reportBucketVersioning = reportBucketVersioning;
19
- const classify_1 = require("../../errors/classify");
20
- const errors_1 = require("../../errors/errors");
21
- const truncate_1 = require("../../logging/truncate");
22
- const client_1 = require("./client");
23
- const config_1 = require("./config");
24
- /**
25
- * Days a released payload's noncurrent version survives behind its delete
26
- * marker before S3 reclaims it. One day is the smallest the lifecycle API
27
- * accepts and it rounds up to the next UTC midnight, so the window is 24-48 h:
28
- * long enough to restore a payload released in error, short enough that a
29
- * versioned bucket does not pay for every release it has ever made. It is a
30
- * floor and never a cap — a longer retention the bucket already carries is
31
- * kept, because this package has no business shortening someone else's
32
- * recovery window. Inert on an unversioned bucket, which has no noncurrent
33
- * versions to expire.
34
- */
35
- exports.S3_RELEASE_GRACE_DAYS = 1;
36
- async function readState(client, bucket) {
37
- const { GetBucketLifecycleConfigurationCommand } = await (0, client_1.loadS3Sdk)();
38
- try {
39
- const existing = await client.send(new GetBucketLifecycleConfigurationCommand({ Bucket: bucket }));
40
- return {
41
- rules: existing.Rules ?? [],
42
- transitionDefaultMinimumObjectSize: existing.TransitionDefaultMinimumObjectSize,
43
- };
44
- }
45
- catch (error) {
46
- if ((0, classify_1.isMissingLifecycleConfiguration)(error))
47
- return { rules: [] };
48
- throw error;
49
- }
50
- }
51
- /** `rules` with `rule` replacing the one holding its id, or appended when none does. */
52
- function upsert(rules, rule) {
53
- return rules.some((held) => held.ID === rule.ID)
54
- ? rules.map((held) => (held.ID === rule.ID ? rule : held))
55
- : [...rules, rule];
56
- }
57
- /** Replace the bucket's whole configuration with `rules`, carrying its own field back. */
58
- async function putRules(client, bucket, state, rules) {
59
- const { PutBucketLifecycleConfigurationCommand } = await (0, client_1.loadS3Sdk)();
60
- await client.send(new PutBucketLifecycleConfigurationCommand({
61
- Bucket: bucket,
62
- LifecycleConfiguration: { Rules: rules },
63
- ...(state.transitionDefaultMinimumObjectSize === undefined
64
- ? {}
65
- : { TransitionDefaultMinimumObjectSize: state.transitionDefaultMinimumObjectSize }),
66
- }));
67
- }
68
- /**
69
- * Ensure the two rules scoped to `target.prefix` exist on `target.bucket`: a
70
- * `target.days`-day expiration for current versions, and the reclaim that
71
- * removes the delete marker a released payload leaves behind.
72
- *
73
- * Accepts: `target.prefix` — re-checked for scoping here, because these rules
74
- * are the one place an unscoped prefix would destroy data outside this
75
- * library's. `target.days` — the current-version expiry only. Released
76
- * versions are governed by the release grace instead (see {@link ttlRule}),
77
- * which is a floor measured against every rule already governing these keys.
78
- * Both are inert on an unversioned bucket, which keeps no noncurrent version
79
- * and leaves no marker.
80
- *
81
- * Returns: nothing. Idempotent: when both rules already say this, no write is
82
- * issued. The bucket's versioning state is reported either way, because the
83
- * containment a released payload depends on is missing or present regardless
84
- * of whether this particular call had a rule to write.
85
- *
86
- * Throws: `VALIDATION` naming `s3.keyPrefix` for an unscoped prefix, or when
87
- * either rule id this prefix produces is already held by a different prefix
88
- * (see {@link assertNoIdCollision}); otherwise whatever the SDK rejects with. A
89
- * bucket with no lifecycle configuration at all is not an error — S3 reports
90
- * `NoSuchLifecycleConfiguration` and this starts from an empty rule set.
91
- *
92
- * Guarantees: rules this package did not write are preserved, and so is the
93
- * bucket-level `TransitionDefaultMinimumObjectSize` — a Put replaces the whole
94
- * configuration, so dropping it would silently reset the bucket to the default.
95
- */
96
- async function ensureLifecycleRule(client, target, logger) {
97
- (0, config_1.assertScopedKeyPrefix)(target.prefix);
98
- const ttlId = (0, config_1.buildLifecycleRuleId)(target.prefix);
99
- const markerId = (0, config_1.buildMarkerRuleId)(target.prefix);
100
- const state = await readState(client, target.bucket);
101
- const heldTtl = state.rules.find((rule) => rule.ID === ttlId);
102
- const heldMarker = state.rules.find((rule) => rule.ID === markerId);
103
- assertNoIdCollision(heldTtl, target.prefix, ttlId);
104
- assertNoIdCollision(heldMarker, target.prefix, markerId);
105
- const expiry = ttlRule({ id: ttlId, prefix: target.prefix, days: target.days }, state.rules, heldTtl);
106
- const reclaim = markerRule(markerId, target.prefix, heldMarker);
107
- if (!alreadyCorrect(heldTtl, expiry) || !alreadyCorrect(heldMarker, reclaim)) {
108
- await putRules(client, target.bucket, state, upsert(upsert(state.rules, expiry), reclaim));
109
- }
110
- await reportBucketVersioning(client, target.bucket, logger);
111
- }
112
- /**
113
- * The prefix a rule governs, wherever it names one: in its filter, nested
114
- * under the filter's `And` beside tags or size bounds, or in the top-level
115
- * `Prefix` of a rule written before `Filter` existed. `undefined` means the
116
- * rule names no prefix at all — it is bucket-wide, or filtered only by tags or
117
- * object size — and a rule like that governs every key here.
118
- */
119
- function scopeOf(rule) {
120
- return rule.Filter?.Prefix ?? rule.Filter?.And?.Prefix ?? rule.Prefix;
121
- }
122
- /**
123
- * Whether `rule` governs every key under `prefix`.
124
- *
125
- * Only an enabled rule does. A disabled one expires nothing, so it cannot
126
- * shorten anyone's window and must not lengthen this package's either: an
127
- * operator who disables their own retention rule to hand the job over would
128
- * otherwise pin this package at that rule's value for good. A rule scoped
129
- * beside this prefix governs none of its keys and one scoped beneath it only
130
- * some, so neither of them speaks for all of them.
131
- */
132
- function governs(rule, prefix) {
133
- const scope = scopeOf(rule);
134
- return rule.Status === 'Enabled' && (scope === undefined || prefix.startsWith(scope));
135
- }
136
- /**
137
- * The noncurrent retention to write: the longest one already governing these
138
- * keys, and never less than the release grace.
139
- *
140
- * S3 honours the **shorter** of two overlapping expirations, so a rule this
141
- * package does not own decides how long a released payload really survives
142
- * under its prefix. Writing the grace beside a bucket-wide 90-day retention
143
- * would cut that window to a day for every key here, which is the opposite of
144
- * what a floor is for.
145
- *
146
- * The rule being replaced counts whatever its status, unlike every other rule
147
- * here: that value is this package's own committed floor rather than a
148
- * constraint someone else placed on these keys, and `Status` has nothing to say
149
- * about it. An operator who disables the rule to pause expiry during an
150
- * incident would otherwise find the recovery window cut to the grace on the
151
- * next deploy — a second way down from the ratchet, and a silent one.
152
- *
153
- * The rule this package writes is itself in the set, so the floor ratchets: a
154
- * value written once outlives the rule that justified it, and the way back
155
- * down is to delete this package's rule and let it be written afresh.
156
- */
157
- function noncurrentDays(rules, prefix, existing) {
158
- const held = rules
159
- .filter((rule) => governs(rule, prefix))
160
- .map((rule) => rule.NoncurrentVersionExpiration?.NoncurrentDays ?? 0);
161
- return Math.max(...held, existing?.NoncurrentVersionExpiration?.NoncurrentDays ?? 0, exports.S3_RELEASE_GRACE_DAYS);
162
- }
163
- /**
164
- * What a rewrite carries over from the rule it replaces: everything this
165
- * package does not set itself, less the top-level `Prefix`.
166
- *
167
- * That `Prefix` is how a rule written before `Filter` existed names its scope,
168
- * and the two are alternatives rather than a pair — S3 refuses a rule carrying
169
- * both, which would fail the provisioning call this package documents as a
170
- * deployment step. Such a rule is upgraded to a filter, never merged with one.
171
- */
172
- function carried(existing) {
173
- const kept = { ...existing };
174
- delete kept.Prefix;
175
- return kept;
176
- }
177
- /**
178
- * The rule that expires current versions on the TTL's schedule and released
179
- * ones on the grace.
180
- *
181
- * Accepts: `rules` — everything the bucket holds, which is what the grace is
182
- * measured against. `existing` — the rule this one replaces, if any.
183
- *
184
- * Returns: the rule to write. Every field of `existing` this package does not
185
- * manage is carried through, because the rewrite a changed TTL triggers is
186
- * otherwise unrecoverable: the next call reads the rewritten rule as already
187
- * correct and never restores what it dropped.
188
- *
189
- * Throws: nothing.
190
- *
191
- * Guarantees: the `Expiration` is replaced rather than merged. Merging this
192
- * package's `Days` into a `Date` an operator set would change the expiry they
193
- * configured, whatever the service made of the pair.
194
- */
195
- function ttlRule(rule, rules, existing) {
196
- return {
197
- ...carried(existing),
198
- ID: rule.id,
199
- Filter: { Prefix: rule.prefix },
200
- Status: 'Enabled',
201
- Expiration: { Days: rule.days },
202
- NoncurrentVersionExpiration: {
203
- ...existing?.NoncurrentVersionExpiration,
204
- NoncurrentDays: noncurrentDays(rules, rule.prefix, existing),
205
- },
206
- };
207
- }
208
- /**
209
- * The rule that reclaims the delete marker a release leaves, once its last
210
- * noncurrent version has expired.
211
- *
212
- * Accepts: `existing` — the rule this one replaces, if any.
213
- *
214
- * Returns: the rule to write, a second one rather than a field on the TTL
215
- * rule: S3 refuses `ExpiredObjectDeleteMarker` inside an `Expiration` that
216
- * also carries `Days`, so each rule's `Expiration` holds its own half and
217
- * nothing of the other's. Fields this package does not manage are carried
218
- * through as they are on the TTL rule — this id is one this package invented,
219
- * but that is no reason to drop what an operator has since put on it.
220
- *
221
- * Throws: nothing.
222
- */
223
- function markerRule(id, prefix, existing) {
224
- return {
225
- ...carried(existing),
226
- ID: id,
227
- Filter: { Prefix: prefix },
228
- Status: 'Enabled',
229
- Expiration: { ExpiredObjectDeleteMarker: true },
230
- };
231
- }
232
- /**
233
- * Refuse to touch a rule that carries one of this prefix's ids but scopes a
234
- * different prefix. Three shapes reach here: slugging maps every
235
- * non-alphanumeric character to `-`, so `app/langgraph/` and `app-langgraph/`
236
- * produce one id; the marker rule appends `-markers`, so `app/`'s marker id is
237
- * the expiration id of `app-markers/`; and a rule written in the older schema
238
- * holds an id this package would take while naming its scope in the top-level
239
- * `Prefix`.
240
- *
241
- * Accepts: `rule` — the rule holding `id`, or nothing. `prefix` — the one this
242
- * call scopes rules to.
243
- *
244
- * Returns: nothing: `rule` is kept under its declared type, and this checks
245
- * it. A rule naming no scope anywhere is taken over, and so is one already
246
- * scoping this prefix — including in the older schema, which is then upgraded
247
- * to a filter.
248
- *
249
- * Throws: `VALIDATION` naming `s3.keyPrefix`. The id and the scope are
250
- * both bounded by {@link truncateForLog}: the scope is whatever the bucket's
251
- * lifecycle configuration holds, and the id is composed from an
252
- * `s3.keyPrefix` checked for shape and never for length.
253
- *
254
- * Guarantees: the scope is read wherever the rule names it, through the same
255
- * {@link scopeOf} the floor uses. Reading only `Filter.Prefix` would let a
256
- * rule in the older schema through, and the rewrite would then replace its
257
- * scope with this one's — so the objects that rule governs would silently
258
- * lose their expiration, and a bucket-wide rule would narrow to this prefix.
259
- */
260
- function assertNoIdCollision(rule, prefix, id) {
261
- if (rule === undefined)
262
- return;
263
- const found = scopeOf(rule);
264
- if (found === undefined || found === prefix)
265
- return;
266
- throw (0, errors_1.validationError)(`the S3 lifecycle rule id "${(0, truncate_1.truncateForLog)(id)}" is already used by the prefix ` +
267
- `"${(0, truncate_1.truncateForLog)(found)}"; an id is the key ` +
268
- 'prefix with every non-alphanumeric character replaced by "-", and the marker rule appends ' +
269
- '"-markers" to that, so "a/b/" takes the id of "a-b/" and "app/" takes the marker id of ' +
270
- '"app-markers/" — choose an s3.keyPrefix that produces neither id of any other prefix on ' +
271
- 'this bucket', 's3.keyPrefix');
272
- }
273
- /**
274
- * The fields this package manages on a rule, as one value two rules compare
275
- * by. Comparing whole rules would issue a write on every call over a field S3
276
- * reports and this package never sets.
277
- */
278
- function managedShape(rule) {
279
- return JSON.stringify([
280
- rule?.Status,
281
- rule?.Filter?.Prefix,
282
- rule?.Expiration?.Days,
283
- rule?.Expiration?.ExpiredObjectDeleteMarker,
284
- rule?.NoncurrentVersionExpiration?.NoncurrentDays,
285
- ]);
286
- }
287
- /**
288
- * Whether the rule the bucket carries already says what would be written.
289
- *
290
- * Accepts: `existing` — the held rule, or nothing. `desired` — what a write
291
- * would put there.
292
- *
293
- * Returns: whether a write can be skipped. A rule in the older schema never
294
- * matches, because it names its prefix somewhere this does not read, so it is
295
- * rewritten once into a filter and matches from then on.
296
- *
297
- * Throws: nothing.
298
- */
299
- function alreadyCorrect(existing, desired) {
300
- return managedShape(existing) === managedShape(desired);
301
- }
302
- /**
303
- * Report whether `bucket` keeps versions, which is the whole of the recovery
304
- * window behind a released payload.
305
- *
306
- * Accepts: `bucket` — the offload bucket. `logger` — the adapter's; silent by
307
- * default, like every other event this package emits.
308
- *
309
- * Returns: nothing. A versioned bucket is silent; the other two states warn
310
- * and name their own remedy, because those remedies differ — a bucket that
311
- * never had versioning needs it enabled, while a suspended one needs it
312
- * re-enabled *and* an accounting of what suspension has already destroyed.
313
- *
314
- * Throws: nothing, deliberately. A failure of the call itself is a `warn` too,
315
- * including the `AccessDenied` of a role that provisioned lifecycle rules
316
- * yesterday without this action: a permission the call did not need then must
317
- * not break it now. This runs after the rules are written for the same reason
318
- * — a bucket that cannot answer still gets them.
319
- *
320
- * Guarantees: a bucket that has never been versioned answers with an empty
321
- * body, so the absent state is `Status === undefined`. It is never the string
322
- * `'Disabled'`, which this API does not return, and testing for one would read
323
- * an unversioned bucket as a versioned one.
324
- */
325
- async function reportBucketVersioning(client, bucket, logger) {
326
- const { GetBucketVersioningCommand } = await (0, client_1.loadS3Sdk)();
327
- // `s3.bucketName` is checked for being a non-empty string and never for
328
- // length, so it reaches these three lines as whatever the caller's options
329
- // carried. It is quoted here as the identifier it is, cut at the log cap:
330
- // the line's job is to say which bucket to go and look at, and the bucket
331
- // holds the rest.
332
- const named = (0, truncate_1.truncateForLog)(bucket);
333
- let status;
334
- try {
335
- status = (await client.send(new GetBucketVersioningCommand({ Bucket: bucket }))).Status;
336
- }
337
- catch (error) {
338
- // The error's name, never its message, which can carry credential text —
339
- // and read off a shape rather than an Error, because a client seam can
340
- // reject with anything at all and this function promises not to throw. Cut
341
- // like the bucket beside it: a name is a string the SDK or a client seam
342
- // produced, `message` is already bounded where `redactedMessage` relays
343
- // it, and the two are one value.
344
- const reason = (0, truncate_1.truncateForLog)(error?.name ?? 'unknown');
345
- logger.warn('ensureS3LifecycleRule: could not read the offload bucket versioning state, so whether a released payload is recoverable is unknown; the lifecycle rules were written, and the role needs s3:GetBucketVersioning', { bucket: named, reason });
346
- return;
347
- }
348
- if (status === 'Enabled')
349
- return;
350
- if (status === undefined) {
351
- logger.warn('ensureS3LifecycleRule: versioning is off on the offload bucket, so releasing a payload deletes it outright with no recovery window; enable bucket versioning to gain one', { bucket: named });
352
- return;
353
- }
354
- logger.warn('ensureS3LifecycleRule: versioning is suspended on the offload bucket, so releasing a payload deletes it outright; re-enable versioning, and note that the payloads released while it was suspended are already gone', { bucket: named });
355
- }