@backblaze-labs/b2-sdk 0.3.0 → 0.4.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 (393) hide show
  1. package/CHANGELOG.md +45 -1
  2. package/README.md +18 -5
  3. package/dist/_virtual/_b2-sdk-version-json.cjs +1 -1
  4. package/dist/_virtual/_b2-sdk-version-json.js +1 -1
  5. package/dist/auth/reauth-coalescer.cjs +65 -0
  6. package/dist/auth/reauth-coalescer.cjs.map +1 -0
  7. package/dist/auth/reauth-coalescer.d.cts +34 -0
  8. package/dist/auth/reauth-coalescer.d.cts.map +1 -0
  9. package/dist/auth/reauth-coalescer.d.ts +34 -0
  10. package/dist/auth/reauth-coalescer.d.ts.map +1 -0
  11. package/dist/auth/reauth-coalescer.js +65 -0
  12. package/dist/auth/reauth-coalescer.js.map +1 -0
  13. package/dist/backup/raw.cjs +37 -15
  14. package/dist/backup/raw.cjs.map +1 -1
  15. package/dist/backup/raw.d.cts +2 -2
  16. package/dist/backup/raw.d.cts.map +1 -1
  17. package/dist/backup/raw.d.ts +2 -2
  18. package/dist/backup/raw.d.ts.map +1 -1
  19. package/dist/backup/raw.js +37 -15
  20. package/dist/backup/raw.js.map +1 -1
  21. package/dist/bucket-validation.cjs +111 -0
  22. package/dist/bucket-validation.cjs.map +1 -0
  23. package/dist/bucket-validation.d.cts +27 -0
  24. package/dist/bucket-validation.d.cts.map +1 -0
  25. package/dist/bucket-validation.d.ts +27 -0
  26. package/dist/bucket-validation.d.ts.map +1 -0
  27. package/dist/bucket-validation.js +109 -0
  28. package/dist/bucket-validation.js.map +1 -0
  29. package/dist/bucket.cjs +123 -73
  30. package/dist/bucket.cjs.map +1 -1
  31. package/dist/bucket.d.cts +156 -61
  32. package/dist/bucket.d.cts.map +1 -1
  33. package/dist/bucket.d.ts +156 -61
  34. package/dist/bucket.d.ts.map +1 -1
  35. package/dist/bucket.js +123 -73
  36. package/dist/bucket.js.map +1 -1
  37. package/dist/client.cjs +29 -8
  38. package/dist/client.cjs.map +1 -1
  39. package/dist/client.d.cts +30 -9
  40. package/dist/client.d.cts.map +1 -1
  41. package/dist/client.d.ts +30 -9
  42. package/dist/client.d.ts.map +1 -1
  43. package/dist/client.js +29 -8
  44. package/dist/client.js.map +1 -1
  45. package/dist/download/single.cjs +38 -13
  46. package/dist/download/single.cjs.map +1 -1
  47. package/dist/download/single.d.cts +10 -4
  48. package/dist/download/single.d.cts.map +1 -1
  49. package/dist/download/single.d.ts +10 -4
  50. package/dist/download/single.d.ts.map +1 -1
  51. package/dist/download/single.js +38 -13
  52. package/dist/download/single.js.map +1 -1
  53. package/dist/errors/index.cjs +27 -4
  54. package/dist/errors/index.cjs.map +1 -1
  55. package/dist/errors/index.d.cts +15 -0
  56. package/dist/errors/index.d.cts.map +1 -1
  57. package/dist/errors/index.d.ts +15 -0
  58. package/dist/errors/index.d.ts.map +1 -1
  59. package/dist/errors/index.js +27 -5
  60. package/dist/errors/index.js.map +1 -1
  61. package/dist/http/non-idempotent-mutations.cjs +38 -0
  62. package/dist/http/non-idempotent-mutations.cjs.map +1 -0
  63. package/dist/http/non-idempotent-mutations.d.cts +25 -0
  64. package/dist/http/non-idempotent-mutations.d.cts.map +1 -0
  65. package/dist/http/non-idempotent-mutations.d.ts +25 -0
  66. package/dist/http/non-idempotent-mutations.d.ts.map +1 -0
  67. package/dist/http/non-idempotent-mutations.js +35 -0
  68. package/dist/http/non-idempotent-mutations.js.map +1 -0
  69. package/dist/http/transport.cjs +9 -8
  70. package/dist/http/transport.cjs.map +1 -1
  71. package/dist/http/transport.d.cts +5 -0
  72. package/dist/http/transport.d.cts.map +1 -1
  73. package/dist/http/transport.d.ts +5 -0
  74. package/dist/http/transport.d.ts.map +1 -1
  75. package/dist/http/transport.js +9 -8
  76. package/dist/http/transport.js.map +1 -1
  77. package/dist/http/user-agent.cjs +12 -1
  78. package/dist/http/user-agent.cjs.map +1 -1
  79. package/dist/http/user-agent.d.cts +8 -0
  80. package/dist/http/user-agent.d.cts.map +1 -1
  81. package/dist/http/user-agent.d.ts +8 -0
  82. package/dist/http/user-agent.d.ts.map +1 -1
  83. package/dist/http/user-agent.js +13 -3
  84. package/dist/http/user-agent.js.map +1 -1
  85. package/dist/index.cjs +25 -0
  86. package/dist/index.d.cts +10 -9
  87. package/dist/index.d.cts.map +1 -1
  88. package/dist/index.d.ts +10 -9
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +7 -6
  91. package/dist/notifications/index.cjs +3 -0
  92. package/dist/notifications/index.d.cts +2 -0
  93. package/dist/notifications/index.d.cts.map +1 -1
  94. package/dist/notifications/index.d.ts +2 -0
  95. package/dist/notifications/index.d.ts.map +1 -1
  96. package/dist/notifications/index.js +2 -1
  97. package/dist/object.cjs +12 -1
  98. package/dist/object.cjs.map +1 -1
  99. package/dist/object.d.cts +7 -1
  100. package/dist/object.d.cts.map +1 -1
  101. package/dist/object.d.ts +7 -1
  102. package/dist/object.d.ts.map +1 -1
  103. package/dist/object.js +12 -1
  104. package/dist/object.js.map +1 -1
  105. package/dist/partner/auth-core.cjs +4 -23
  106. package/dist/partner/auth-core.cjs.map +1 -1
  107. package/dist/partner/auth-core.d.cts +1 -1
  108. package/dist/partner/auth-core.d.cts.map +1 -1
  109. package/dist/partner/auth-core.d.ts +1 -1
  110. package/dist/partner/auth-core.d.ts.map +1 -1
  111. package/dist/partner/auth-core.js +5 -24
  112. package/dist/partner/auth-core.js.map +1 -1
  113. package/dist/partner/client.cjs +25 -10
  114. package/dist/partner/client.cjs.map +1 -1
  115. package/dist/partner/client.d.cts +32 -10
  116. package/dist/partner/client.d.cts.map +1 -1
  117. package/dist/partner/client.d.ts +32 -10
  118. package/dist/partner/client.d.ts.map +1 -1
  119. package/dist/partner/client.js +25 -10
  120. package/dist/partner/client.js.map +1 -1
  121. package/dist/partner/endpoint-url.cjs +1 -0
  122. package/dist/partner/endpoint-url.cjs.map +1 -1
  123. package/dist/partner/endpoint-url.d.cts +2 -0
  124. package/dist/partner/endpoint-url.d.cts.map +1 -1
  125. package/dist/partner/endpoint-url.d.ts +2 -0
  126. package/dist/partner/endpoint-url.d.ts.map +1 -1
  127. package/dist/partner/endpoint-url.js +1 -0
  128. package/dist/partner/endpoint-url.js.map +1 -1
  129. package/dist/partner/in-memory.cjs.map +1 -1
  130. package/dist/partner/in-memory.js.map +1 -1
  131. package/dist/partner/index.cjs +9 -0
  132. package/dist/partner/index.d.cts +11 -2
  133. package/dist/partner/index.d.cts.map +1 -1
  134. package/dist/partner/index.d.ts +11 -2
  135. package/dist/partner/index.d.ts.map +1 -1
  136. package/dist/partner/index.js +3 -1
  137. package/dist/partner/raw.cjs +52 -44
  138. package/dist/partner/raw.cjs.map +1 -1
  139. package/dist/partner/raw.d.cts +16 -19
  140. package/dist/partner/raw.d.cts.map +1 -1
  141. package/dist/partner/raw.d.ts +16 -19
  142. package/dist/partner/raw.d.ts.map +1 -1
  143. package/dist/partner/raw.js +52 -44
  144. package/dist/partner/raw.js.map +1 -1
  145. package/dist/partner/redaction.cjs +133 -108
  146. package/dist/partner/redaction.cjs.map +1 -1
  147. package/dist/partner/redaction.d.cts +47 -13
  148. package/dist/partner/redaction.d.cts.map +1 -1
  149. package/dist/partner/redaction.d.ts +47 -13
  150. package/dist/partner/redaction.d.ts.map +1 -1
  151. package/dist/partner/redaction.js +133 -109
  152. package/dist/partner/redaction.js.map +1 -1
  153. package/dist/raw/encoding.cjs +29 -10
  154. package/dist/raw/encoding.cjs.map +1 -1
  155. package/dist/raw/encoding.d.cts +3 -2
  156. package/dist/raw/encoding.d.cts.map +1 -1
  157. package/dist/raw/encoding.d.ts +3 -2
  158. package/dist/raw/encoding.d.ts.map +1 -1
  159. package/dist/raw/encoding.js +29 -10
  160. package/dist/raw/encoding.js.map +1 -1
  161. package/dist/raw/index.cjs +64 -39
  162. package/dist/raw/index.cjs.map +1 -1
  163. package/dist/raw/index.d.cts +21 -19
  164. package/dist/raw/index.d.cts.map +1 -1
  165. package/dist/raw/index.d.ts +21 -19
  166. package/dist/raw/index.d.ts.map +1 -1
  167. package/dist/raw/index.js +47 -40
  168. package/dist/raw/index.js.map +1 -1
  169. package/dist/raw/url.cjs.map +1 -1
  170. package/dist/raw/url.d.cts +3 -3
  171. package/dist/raw/url.d.ts +3 -3
  172. package/dist/raw/url.js.map +1 -1
  173. package/dist/simulator/index.cjs +456 -125
  174. package/dist/simulator/index.cjs.map +1 -1
  175. package/dist/simulator/index.d.cts +16 -1
  176. package/dist/simulator/index.d.cts.map +1 -1
  177. package/dist/simulator/index.d.ts +16 -1
  178. package/dist/simulator/index.d.ts.map +1 -1
  179. package/dist/simulator/index.js +449 -130
  180. package/dist/simulator/index.js.map +1 -1
  181. package/dist/simulator/partner-capabilities.cjs +77 -0
  182. package/dist/simulator/partner-capabilities.cjs.map +1 -0
  183. package/dist/simulator/partner-capabilities.d.cts +53 -0
  184. package/dist/simulator/partner-capabilities.d.cts.map +1 -0
  185. package/dist/simulator/partner-capabilities.d.ts +53 -0
  186. package/dist/simulator/partner-capabilities.d.ts.map +1 -0
  187. package/dist/simulator/partner-capabilities.js +73 -0
  188. package/dist/simulator/partner-capabilities.js.map +1 -0
  189. package/dist/simulator/partner.cjs +55 -61
  190. package/dist/simulator/partner.cjs.map +1 -1
  191. package/dist/simulator/partner.d.cts +5 -2
  192. package/dist/simulator/partner.d.cts.map +1 -1
  193. package/dist/simulator/partner.d.ts +5 -2
  194. package/dist/simulator/partner.d.ts.map +1 -1
  195. package/dist/simulator/partner.js +56 -61
  196. package/dist/simulator/partner.js.map +1 -1
  197. package/dist/simulator/validation.cjs +160 -30
  198. package/dist/simulator/validation.cjs.map +1 -1
  199. package/dist/simulator/validation.d.cts +28 -6
  200. package/dist/simulator/validation.d.cts.map +1 -1
  201. package/dist/simulator/validation.d.ts +28 -6
  202. package/dist/simulator/validation.d.ts.map +1 -1
  203. package/dist/simulator/validation.js +148 -31
  204. package/dist/simulator/validation.js.map +1 -1
  205. package/dist/streams/file-source.cjs +1 -1
  206. package/dist/streams/file-source.cjs.map +1 -1
  207. package/dist/streams/file-source.js +1 -1
  208. package/dist/streams/file-source.js.map +1 -1
  209. package/dist/streams/hash.cjs +246 -13
  210. package/dist/streams/hash.cjs.map +1 -1
  211. package/dist/streams/hash.d.cts +37 -12
  212. package/dist/streams/hash.d.cts.map +1 -1
  213. package/dist/streams/hash.d.ts +37 -12
  214. package/dist/streams/hash.d.ts.map +1 -1
  215. package/dist/streams/hash.js +246 -15
  216. package/dist/streams/hash.js.map +1 -1
  217. package/dist/streams/index.cjs +2 -0
  218. package/dist/streams/index.d.cts +1 -1
  219. package/dist/streams/index.d.cts.map +1 -1
  220. package/dist/streams/index.d.ts +1 -1
  221. package/dist/streams/index.d.ts.map +1 -1
  222. package/dist/streams/index.js +2 -2
  223. package/dist/streams/progress.cjs +63 -4
  224. package/dist/streams/progress.cjs.map +1 -1
  225. package/dist/streams/progress.d.cts +28 -2
  226. package/dist/streams/progress.d.cts.map +1 -1
  227. package/dist/streams/progress.d.ts +28 -2
  228. package/dist/streams/progress.d.ts.map +1 -1
  229. package/dist/streams/progress.js +63 -4
  230. package/dist/streams/progress.js.map +1 -1
  231. package/dist/sync/download-staging.cjs +147 -35
  232. package/dist/sync/download-staging.cjs.map +1 -1
  233. package/dist/sync/download-staging.d.cts +25 -2
  234. package/dist/sync/download-staging.d.cts.map +1 -1
  235. package/dist/sync/download-staging.d.ts +25 -2
  236. package/dist/sync/download-staging.d.ts.map +1 -1
  237. package/dist/sync/download-staging.js +146 -36
  238. package/dist/sync/download-staging.js.map +1 -1
  239. package/dist/sync/index.d.cts +1 -1
  240. package/dist/sync/index.d.cts.map +1 -1
  241. package/dist/sync/index.d.ts +1 -1
  242. package/dist/sync/index.d.ts.map +1 -1
  243. package/dist/sync/local-file-io.cjs +5 -1
  244. package/dist/sync/local-file-io.cjs.map +1 -1
  245. package/dist/sync/local-file-io.d.cts +2 -0
  246. package/dist/sync/local-file-io.d.cts.map +1 -1
  247. package/dist/sync/local-file-io.d.ts +2 -0
  248. package/dist/sync/local-file-io.d.ts.map +1 -1
  249. package/dist/sync/local-file-io.js +5 -1
  250. package/dist/sync/local-file-io.js.map +1 -1
  251. package/dist/sync/pairing.cjs +1 -0
  252. package/dist/sync/pairing.cjs.map +1 -1
  253. package/dist/sync/pairing.js +1 -0
  254. package/dist/sync/pairing.js.map +1 -1
  255. package/dist/sync/scanners/b2.cjs +2 -0
  256. package/dist/sync/scanners/b2.cjs.map +1 -1
  257. package/dist/sync/scanners/b2.d.cts.map +1 -1
  258. package/dist/sync/scanners/b2.d.ts.map +1 -1
  259. package/dist/sync/scanners/b2.js +2 -0
  260. package/dist/sync/scanners/b2.js.map +1 -1
  261. package/dist/sync/scanners/local.cjs +150 -33
  262. package/dist/sync/scanners/local.cjs.map +1 -1
  263. package/dist/sync/scanners/local.d.cts +6 -0
  264. package/dist/sync/scanners/local.d.cts.map +1 -1
  265. package/dist/sync/scanners/local.d.ts +6 -0
  266. package/dist/sync/scanners/local.d.ts.map +1 -1
  267. package/dist/sync/scanners/local.js +150 -33
  268. package/dist/sync/scanners/local.js.map +1 -1
  269. package/dist/sync/synchronizer.cjs +76 -29
  270. package/dist/sync/synchronizer.cjs.map +1 -1
  271. package/dist/sync/synchronizer.d.cts +1 -0
  272. package/dist/sync/synchronizer.d.cts.map +1 -1
  273. package/dist/sync/synchronizer.d.ts +1 -0
  274. package/dist/sync/synchronizer.d.ts.map +1 -1
  275. package/dist/sync/synchronizer.js +76 -29
  276. package/dist/sync/synchronizer.js.map +1 -1
  277. package/dist/sync/types.d.cts +19 -3
  278. package/dist/sync/types.d.cts.map +1 -1
  279. package/dist/sync/types.d.ts +19 -3
  280. package/dist/sync/types.d.ts.map +1 -1
  281. package/dist/types/backup.d.cts +6 -1
  282. package/dist/types/backup.d.cts.map +1 -1
  283. package/dist/types/backup.d.ts +6 -1
  284. package/dist/types/backup.d.ts.map +1 -1
  285. package/dist/types/bucket.cjs +81 -11
  286. package/dist/types/bucket.cjs.map +1 -1
  287. package/dist/types/bucket.d.cts +190 -39
  288. package/dist/types/bucket.d.cts.map +1 -1
  289. package/dist/types/bucket.d.ts +190 -39
  290. package/dist/types/bucket.d.ts.map +1 -1
  291. package/dist/types/bucket.js +67 -12
  292. package/dist/types/bucket.js.map +1 -1
  293. package/dist/types/download.cjs.map +1 -1
  294. package/dist/types/download.d.cts +3 -17
  295. package/dist/types/download.d.cts.map +1 -1
  296. package/dist/types/download.d.ts +3 -17
  297. package/dist/types/download.d.ts.map +1 -1
  298. package/dist/types/download.js.map +1 -1
  299. package/dist/types/encryption.cjs +18 -0
  300. package/dist/types/encryption.cjs.map +1 -1
  301. package/dist/types/encryption.d.cts +21 -11
  302. package/dist/types/encryption.d.cts.map +1 -1
  303. package/dist/types/encryption.d.ts +21 -11
  304. package/dist/types/encryption.d.ts.map +1 -1
  305. package/dist/types/encryption.js +18 -0
  306. package/dist/types/encryption.js.map +1 -1
  307. package/dist/types/file.cjs +3 -0
  308. package/dist/types/file.cjs.map +1 -1
  309. package/dist/types/file.d.cts +125 -16
  310. package/dist/types/file.d.cts.map +1 -1
  311. package/dist/types/file.d.ts +125 -16
  312. package/dist/types/file.d.ts.map +1 -1
  313. package/dist/types/file.js +3 -1
  314. package/dist/types/file.js.map +1 -1
  315. package/dist/types/index.d.cts +7 -7
  316. package/dist/types/index.d.cts.map +1 -1
  317. package/dist/types/index.d.ts +7 -7
  318. package/dist/types/index.d.ts.map +1 -1
  319. package/dist/types/key.d.cts +4 -3
  320. package/dist/types/key.d.cts.map +1 -1
  321. package/dist/types/key.d.ts +4 -3
  322. package/dist/types/key.d.ts.map +1 -1
  323. package/dist/types/notifications.cjs +30 -0
  324. package/dist/types/notifications.cjs.map +1 -1
  325. package/dist/types/notifications.d.cts +26 -1
  326. package/dist/types/notifications.d.cts.map +1 -1
  327. package/dist/types/notifications.d.ts +26 -1
  328. package/dist/types/notifications.d.ts.map +1 -1
  329. package/dist/types/notifications.js +29 -1
  330. package/dist/types/notifications.js.map +1 -1
  331. package/dist/types/partner.cjs.map +1 -1
  332. package/dist/types/partner.d.cts +28 -36
  333. package/dist/types/partner.d.cts.map +1 -1
  334. package/dist/types/partner.d.ts +28 -36
  335. package/dist/types/partner.d.ts.map +1 -1
  336. package/dist/types/partner.js.map +1 -1
  337. package/dist/types/upload.d.cts +4 -0
  338. package/dist/types/upload.d.cts.map +1 -1
  339. package/dist/types/upload.d.ts +4 -0
  340. package/dist/types/upload.d.ts.map +1 -1
  341. package/dist/upload/large.cjs +10 -7
  342. package/dist/upload/large.cjs.map +1 -1
  343. package/dist/upload/large.d.cts +15 -6
  344. package/dist/upload/large.d.cts.map +1 -1
  345. package/dist/upload/large.d.ts +15 -6
  346. package/dist/upload/large.d.ts.map +1 -1
  347. package/dist/upload/large.js +10 -7
  348. package/dist/upload/large.js.map +1 -1
  349. package/dist/upload/options.cjs.map +1 -1
  350. package/dist/upload/options.d.cts +12 -0
  351. package/dist/upload/options.d.cts.map +1 -1
  352. package/dist/upload/options.d.ts +12 -0
  353. package/dist/upload/options.d.ts.map +1 -1
  354. package/dist/upload/options.js.map +1 -1
  355. package/dist/upload/resume.cjs +4 -3
  356. package/dist/upload/resume.cjs.map +1 -1
  357. package/dist/upload/resume.d.cts +6 -4
  358. package/dist/upload/resume.d.cts.map +1 -1
  359. package/dist/upload/resume.d.ts +6 -4
  360. package/dist/upload/resume.d.ts.map +1 -1
  361. package/dist/upload/resume.js +4 -3
  362. package/dist/upload/resume.js.map +1 -1
  363. package/dist/upload/retry.cjs +17 -10
  364. package/dist/upload/retry.cjs.map +1 -1
  365. package/dist/upload/retry.d.cts.map +1 -1
  366. package/dist/upload/retry.d.ts.map +1 -1
  367. package/dist/upload/retry.js +17 -10
  368. package/dist/upload/retry.js.map +1 -1
  369. package/dist/upload/single.cjs +35 -31
  370. package/dist/upload/single.cjs.map +1 -1
  371. package/dist/upload/single.d.cts +6 -0
  372. package/dist/upload/single.d.cts.map +1 -1
  373. package/dist/upload/single.d.ts +6 -0
  374. package/dist/upload/single.d.ts.map +1 -1
  375. package/dist/upload/single.js +35 -31
  376. package/dist/upload/single.js.map +1 -1
  377. package/dist/upload/stream.cjs +12 -1
  378. package/dist/upload/stream.cjs.map +1 -1
  379. package/dist/upload/stream.d.cts +6 -0
  380. package/dist/upload/stream.d.cts.map +1 -1
  381. package/dist/upload/stream.d.ts +6 -0
  382. package/dist/upload/stream.d.ts.map +1 -1
  383. package/dist/upload/stream.js +12 -1
  384. package/dist/upload/stream.js.map +1 -1
  385. package/dist/version.cjs +56 -4
  386. package/dist/version.cjs.map +1 -1
  387. package/dist/version.d.cts +53 -4
  388. package/dist/version.d.cts.map +1 -1
  389. package/dist/version.d.ts +53 -4
  390. package/dist/version.d.ts.map +1 -1
  391. package/dist/version.js +52 -5
  392. package/dist/version.js.map +1 -1
  393. package/package.json +11 -4
@@ -1 +1 @@
1
- {"version":3,"file":"bucket.js","names":[],"sources":["../src/bucket.ts"],"sourcesContent":["import type { B2Client } from './client.ts'\nimport { copyLargeFile } from './copy/large.ts'\nimport {\n type DownloadResult,\n downloadByName,\n type HeadResult,\n headByName,\n} from './download/single.ts'\nimport type { RetryOptions } from './http/retry.ts'\nimport { mergeUploadRetryOptions } from './internal/upload-retry-options.ts'\nimport { B2Object, type DownloadCallOptions, type HeadCallOptions } from './object.ts'\nimport type {\n BucketInfo,\n BucketRetentionPolicy,\n BucketType,\n CorsRule,\n LifecycleRule,\n} from './types/bucket.ts'\nimport type { DownloadAuthorizationResponse } from './types/download.ts'\nimport type { EncryptionSetting } from './types/encryption.ts'\nimport type {\n FileVersion,\n ListFileNamesResponse,\n ListFileVersionsResponse,\n MetadataDirective,\n} from './types/file.ts'\nimport type { ApplicationKeyId, BucketId, FileId, LargeFileId } from './types/ids.ts'\nimport { accountId } from './types/ids.ts'\nimport type { FileRetentionValue, LegalHoldValue } from './types/lock.ts'\nimport type {\n EventNotificationRule,\n GetBucketNotificationRulesResponse,\n} from './types/notifications.ts'\nimport type { ReplicationConfiguration, ReplicationRule } from './types/replication.ts'\nimport type { CancelLargeFileResponse, PartInfo, UnfinishedLargeFile } from './types/upload.ts'\nimport type { CleanupFailureListener } from './upload/cancel.ts'\nimport { Semaphore } from './upload/concurrency.ts'\nimport { uploadLargeFile } from './upload/large.ts'\nimport {\n type BucketUploadOptions,\n rejectSmallResumeFileId,\n stripResumeOnlyOptions,\n} from './upload/options.ts'\nimport { uploadSmallFile } from './upload/single.ts'\nimport { DEFAULT_BULK_CONCURRENCY, DEFAULT_PAGE_SIZE } from './util/defaults.ts'\nimport { type PaginatorOptions, paginateItems } from './util/paginator.ts'\nimport { toError } from './util/to-error.ts'\n\n/** A target for bulk deletion: a file name and its specific version ID. */\nexport interface DeleteTarget {\n /** File name (path) of the version to delete. */\n readonly fileName: string\n /** Unique identifier of the file version. */\n readonly fileId: FileId\n}\n\n/** Per-target error encountered during bulk deletion. */\nexport interface DeleteError {\n /** The target that failed. */\n readonly target: DeleteTarget\n /** The error thrown by the underlying `deleteFileVersion` call. */\n readonly error: Error\n}\n\n/** Aggregate result of a {@link Bucket.deleteMany} run. */\nexport interface DeleteManyResult {\n /** Number of file versions successfully deleted. */\n readonly deleted: number\n /** Per-target failures. Empty on full success. */\n readonly errors: readonly DeleteError[]\n}\n\n/** Emitted by {@link Bucket.deleteAll} once a file version has been successfully deleted. */\nexport interface DeleteAllDeleteEvent {\n /** Discriminant identifying a successful delete. */\n readonly type: 'delete'\n /** File name of the deleted version. */\n readonly fileName: string\n /** Unique identifier of the deleted version. */\n readonly fileId: FileId\n}\n\n/** Emitted by {@link Bucket.deleteAll} when a single delete call fails (other versions keep streaming). */\nexport interface DeleteAllErrorEvent {\n /** Discriminant identifying a per-version delete failure. */\n readonly type: 'error'\n /** File name of the version that failed to delete. */\n readonly fileName: string\n /** Unique identifier of the version that failed to delete. */\n readonly fileId: FileId\n /** Human-readable failure reason taken from the underlying error. */\n readonly message: string\n}\n\n/** Emitted by {@link Bucket.deleteAll} in `dryRun` mode for every version that would have been deleted. */\nexport interface DeleteAllSkipEvent {\n /** Discriminant identifying a dry-run skip. */\n readonly type: 'skip'\n /** File name of the version that would have been deleted. */\n readonly fileName: string\n /** Unique identifier of the version that would have been deleted. */\n readonly fileId: FileId\n}\n\n/** Event yielded by {@link Bucket.deleteAll} as it streams through file versions. */\nexport type DeleteAllEvent = DeleteAllDeleteEvent | DeleteAllErrorEvent | DeleteAllSkipEvent\n\ninterface BucketDefaultRetentionSnapshot {\n readonly retention?: BucketRetentionPolicy\n readonly unreadable: boolean\n}\n\nfunction bucketDefaultRetentionSnapshot(info: BucketInfo): BucketDefaultRetentionSnapshot {\n const fileLock = info.fileLockConfiguration\n if (!fileLock.isClientAuthorizedToRead) return { unreadable: true }\n if (fileLock.value === null) return { unreadable: false }\n return { retention: fileLock.value.defaultRetention, unreadable: false }\n}\n\nfunction resumeNeedsFreshBucketDefaults(options: BucketUploadOptions): boolean {\n const resumeRequested = options.resume === true || options.resumeFileId !== undefined\n return (\n resumeRequested &&\n (options.serverSideEncryption === undefined || options.fileRetention === undefined)\n )\n}\n\n/**\n * Handle to a B2 bucket providing upload, download, listing, and management operations.\n *\n * Obtained via {@link B2Client.createBucket}, {@link B2Client.listBuckets}, or {@link B2Client.getBucket}.\n *\n * @example\n * ```ts\n * const bucket = await client.getBucket('my-bucket')\n * await bucket.upload({ fileName: 'hello.txt', source: new BufferSource(data) })\n * ```\n */\nexport class Bucket {\n /** Unique identifier for this bucket. */\n readonly id: BucketId\n /** Human-readable bucket name. */\n readonly name: string\n /** Full bucket metadata as returned by the B2 API. */\n readonly info: BucketInfo\n private readonly client: B2Client\n private readonly uploadRetryOptions: RetryOptions\n\n /**\n * @param client - The parent B2Client instance.\n * @param info - The bucket metadata from the API.\n * @param uploadRetryOptions - Resolved client upload retry defaults.\n *\n * @internal\n */\n constructor(client: B2Client, info: BucketInfo, uploadRetryOptions: RetryOptions) {\n this.client = client\n this.info = info\n this.id = info.bucketId\n this.name = info.bucketName\n this.uploadRetryOptions = uploadRetryOptions\n }\n\n /**\n * Returns a {@link B2Object} handle for a specific file name in this bucket.\n * @param fileName - The file path within the bucket.\n *\n * @returns A B2Object handle bound to this bucket and file name.\n */\n file(fileName: string): B2Object {\n return new B2Object(this.client, this, fileName, this.uploadRetryOptions)\n }\n\n /**\n * Uploads a file to this bucket. Automatically uses multipart upload for files\n * larger than the recommended part size.\n * @param options - Upload configuration including file name, source data, and optional settings.\n *\n * @returns Metadata for the uploaded file version.\n */\n async upload(options: BucketUploadOptions): Promise<FileVersion> {\n const recommendedPartSize = this.client.accountInfo.getRecommendedPartSize()\n const isLarge = options.source.size > recommendedPartSize\n const uploadRetryOptions = mergeUploadRetryOptions(this.uploadRetryOptions, options.retry)\n\n if (isLarge) {\n const bucketInfo = resumeNeedsFreshBucketDefaults(options) ? await this.refresh() : this.info\n const bucketDefaultRetention = bucketDefaultRetentionSnapshot(bucketInfo)\n return uploadLargeFile(this.client.raw, this.client.accountInfo, {\n ...options,\n bucketId: this.id,\n retry: uploadRetryOptions,\n bucketDefaultServerSideEncryption: bucketInfo.defaultServerSideEncryption,\n ...(bucketDefaultRetention.retention !== undefined\n ? { bucketDefaultRetention: bucketDefaultRetention.retention }\n : {}),\n ...(bucketDefaultRetention.unreadable ? { bucketDefaultRetentionUnreadable: true } : {}),\n })\n }\n rejectSmallResumeFileId(options, 'Bucket.upload')\n const smallOptions = stripResumeOnlyOptions(options)\n return uploadSmallFile(this.client.raw, this.client.accountInfo, {\n ...smallOptions,\n bucketId: this.id,\n retry: uploadRetryOptions,\n })\n }\n\n /**\n * Downloads a file from this bucket by name. Pass `method: 'HEAD'` in\n * `options` to fetch only the response headers (file metadata) without\n * streaming the body.\n * @param fileName - The file name (path) to download.\n * @param options - Optional method, range, SSE-C decryption, response-header overrides, and abort signal.\n *\n * @returns The download result containing response headers and a readable body stream.\n */\n async download(fileName: string, options?: DownloadCallOptions): Promise<DownloadResult> {\n return downloadByName(this.client.raw, this.client.accountInfo, {\n bucketName: this.name,\n fileName,\n ...options,\n })\n }\n\n /**\n * Fetches the response headers (file metadata) for a file via HTTP\n * HEAD. Returns a body-less result so callers never have to drain\n * the (logically empty) HEAD body themselves.\n *\n * Use this for metadata-only checks like \"does this file exist\", \"what\n * is its current SHA-1\", \"what is its Content-Length\". For full file\n * retrieval use {@link Bucket.download}.\n *\n * @param fileName - The file name (path) to inspect.\n * @param options - Optional range, SSE-C decryption, response-header\n * overrides, and abort signal. Same shape as {@link Bucket.download}'s\n * options minus `method` (always HEAD) and `onProgress` (no body).\n *\n * @returns Parsed download headers (content type, SHA-1, file info, etc.).\n *\n * @example\n * ```ts\n * const { headers } = await bucket.head('photos/2026/sunset.jpg')\n * console.log(headers.contentLength, headers.contentSha1)\n * ```\n */\n async head(fileName: string, options?: HeadCallOptions): Promise<HeadResult> {\n return headByName(this.client.raw, this.client.accountInfo, {\n bucketName: this.name,\n fileName,\n ...options,\n })\n }\n\n /**\n * Lists file names in this bucket (most recent versions only).\n * @param options - Optional filtering and pagination settings.\n *\n * @returns A page of file versions with an optional continuation token.\n */\n async listFileNames(options?: {\n /** Start listing after this file name (for pagination). */\n startFileName?: string\n /**\n * Maximum number of files to return per request (1-10000).\n * Forwarded to the raw API's `maxFileCount` parameter.\n */\n pageSize?: number\n /** Only list files with names starting with this prefix. */\n prefix?: string\n /** Delimiter for virtual directory grouping (typically `\"/\"`). */\n delimiter?: string\n /** Optional abort signal for the listing request. */\n signal?: AbortSignal\n }): Promise<ListFileNamesResponse> {\n return this.client.raw.listFileNames(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n bucketId: this.id,\n ...(options?.startFileName !== undefined ? { startFileName: options.startFileName } : {}),\n ...(options?.pageSize !== undefined ? { maxFileCount: options.pageSize } : {}),\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options?.delimiter !== undefined ? { delimiter: options.delimiter } : {}),\n },\n {\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n },\n )\n }\n\n /**\n * Lists all file versions in this bucket, including hidden files.\n * @param options - Optional filtering and pagination settings.\n *\n * @returns A page of file versions with an optional continuation token.\n */\n async listFileVersions(options?: {\n /** Start listing after this file name (for pagination). */\n startFileName?: string\n /** Start listing after this file ID (for pagination within a file name). */\n startFileId?: FileId\n /**\n * Maximum number of file versions to return per request (1-10000).\n * Forwarded to the raw API's `maxFileCount` parameter.\n */\n pageSize?: number\n /** Only list files with names starting with this prefix. */\n prefix?: string\n /** Delimiter for virtual directory grouping. */\n delimiter?: string\n /** Optional abort signal for the listing request. */\n signal?: AbortSignal\n }): Promise<ListFileVersionsResponse> {\n return this.client.raw.listFileVersions(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n bucketId: this.id,\n ...(options?.startFileName !== undefined ? { startFileName: options.startFileName } : {}),\n ...(options?.startFileId !== undefined ? { startFileId: options.startFileId } : {}),\n ...(options?.pageSize !== undefined ? { maxFileCount: options.pageSize } : {}),\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options?.delimiter !== undefined ? { delimiter: options.delimiter } : {}),\n },\n {\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n },\n )\n }\n\n /**\n * Async iterator that yields the latest visible version of every file in\n * the bucket, automatically handling pagination via `listFileNames`.\n *\n * Hidden files (those whose latest version is a hide marker) are NOT\n * yielded by this iterator. Use {@link paginateFileVersions} when you\n * need full version history.\n *\n * @param options - Filter + pagination + abort options. `pageSize` is\n * forwarded to `b2_list_file_names`'s `maxFileCount` (default 1000,\n * B2-capped at 10000).\n *\n * @returns An async iterable of {@link FileVersion} entries.\n *\n * @example\n * ```ts\n * for await (const file of bucket.paginateFileNames({ prefix: 'photos/' })) {\n * console.log(file.fileName, file.contentLength)\n * }\n * ```\n */\n paginateFileNames(\n options?: {\n /** Only yield files whose names start with this prefix. */\n prefix?: string\n /** Delimiter for virtual directory grouping (typically `'/'`). */\n delimiter?: string\n } & PaginatorOptions,\n ): AsyncIterableIterator<FileVersion> {\n return paginateItems(\n async (cursor: string | undefined) => {\n const resp = await this.listFileNames({\n pageSize: options?.pageSize ?? DEFAULT_PAGE_SIZE,\n ...(cursor !== undefined ? { startFileName: cursor } : {}),\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options?.delimiter !== undefined ? { delimiter: options.delimiter } : {}),\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n })\n return { page: resp, nextCursor: resp.nextFileName ?? undefined }\n },\n // Real B2 surfaces hide markers as rows in `b2_list_file_names`. This\n // iterator's documented contract is \"latest VISIBLE version\", so we\n // drop hide-action rows here. Callers who need full history should\n // use `paginateFileVersions`.\n (page) => page.files.filter((f) => f.action !== 'hide'),\n options?.signal,\n )\n }\n\n /**\n * Async iterator that yields every version of every file in the bucket,\n * including hidden files and historical versions, automatically handling\n * pagination via `listFileVersions`.\n *\n * The two-cursor `(nextFileName, nextFileId)` continuation that the raw\n * endpoint exposes is threaded internally; callers iterate flat.\n *\n * @param options - Filter + pagination + abort options.\n *\n * @returns An async iterable of {@link FileVersion} entries.\n */\n paginateFileVersions(\n options?: {\n /** Only yield versions whose names start with this prefix. */\n prefix?: string\n /** Delimiter for virtual directory grouping. */\n delimiter?: string\n } & PaginatorOptions,\n ): AsyncIterableIterator<FileVersion> {\n type Cursor = { fileName: string; fileId: FileId | undefined }\n return paginateItems(\n async (cursor: Cursor | undefined) => {\n const resp = await this.listFileVersions({\n pageSize: options?.pageSize ?? DEFAULT_PAGE_SIZE,\n ...(cursor !== undefined ? { startFileName: cursor.fileName } : {}),\n ...(cursor?.fileId !== undefined ? { startFileId: cursor.fileId } : {}),\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options?.delimiter !== undefined ? { delimiter: options.delimiter } : {}),\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n })\n const nextCursor: Cursor | undefined =\n resp.nextFileName !== null\n ? { fileName: resp.nextFileName, fileId: resp.nextFileId ?? undefined }\n : undefined\n return { page: resp, nextCursor }\n },\n (page) => page.files,\n options?.signal,\n )\n }\n\n /**\n * Async iterator that yields every unfinished large file in the bucket,\n * automatically handling pagination via `listUnfinishedLargeFiles`.\n *\n * Useful for janitorial scripts that want to inspect or cancel abandoned\n * multipart uploads (typically followed by {@link cancelLargeFile} on\n * the underlying raw client).\n *\n * @param options - Filter + pagination + abort options. `pageSize` is\n * B2-capped at 100 for this endpoint.\n *\n * @returns An async iterable of unfinished-large-file metadata entries.\n */\n paginateUnfinishedLargeFiles(\n options?: {\n /** Only yield large files whose names start with this prefix. */\n namePrefix?: string\n } & PaginatorOptions,\n ): AsyncIterableIterator<UnfinishedLargeFile> {\n return paginateItems(\n async (cursor: LargeFileId | undefined) => {\n const resp = await this.listUnfinishedLargeFiles({\n pageSize: options?.pageSize ?? 100,\n ...(cursor !== undefined ? { startFileId: cursor } : {}),\n ...(options?.namePrefix !== undefined ? { namePrefix: options.namePrefix } : {}),\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n })\n return { page: resp, nextCursor: resp.nextFileId ?? undefined }\n },\n (page) => page.files,\n options?.signal,\n )\n }\n\n /**\n * Async iterator that yields every uploaded part for a specific large\n * file, automatically handling pagination via `listParts`.\n *\n * @param largeFileId - The unfinished large file to enumerate parts of.\n * @param options - Pagination + abort options. `pageSize` is B2-capped\n * at 1000 for this endpoint; the default is 1000.\n *\n * @returns An async iterable of {@link PartInfo} entries.\n */\n paginateParts(\n largeFileId: LargeFileId,\n options?: PaginatorOptions,\n ): AsyncIterableIterator<PartInfo> {\n return paginateItems(\n async (cursor: number | undefined) => {\n const resp = await this.client.raw.listParts(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n fileId: largeFileId,\n maxPartCount: options?.pageSize ?? DEFAULT_PAGE_SIZE,\n ...(cursor !== undefined ? { startPartNumber: cursor } : {}),\n },\n options?.signal !== undefined ? { signal: options.signal } : undefined,\n )\n return { page: resp, nextCursor: resp.nextPartNumber ?? undefined }\n },\n (page) => page.parts,\n options?.signal,\n )\n }\n\n /**\n * Looks up the latest visible version of a file by name.\n * Uses `listFileNames` under the hood; returns `null` when the file does not\n * exist or its latest version is a hide marker.\n * @param fileName - The exact file path to look up.\n *\n * @returns The latest {@link FileVersion}, or `null` if not found.\n */\n async getFileInfoByName(fileName: string): Promise<FileVersion | null> {\n // `listFileNames` returns the most recent version per file name,\n // which may be a hide marker (real B2: `action: 'hide'`,\n // `contentLength: 0`). This helper's contract is \"latest LIVE\n // version\", so we treat a hide-action match as \"not found\".\n const resp = await this.listFileNames({ prefix: fileName, pageSize: 1 })\n const match = resp.files.find((f) => f.fileName === fileName)\n if (!match || match.action === 'hide') return null\n return match\n }\n\n /**\n * Removes the latest hide marker for a file, restoring visibility of the\n * previous upload. Returns the deleted hide marker, or `null` if there was\n * no hide marker to remove (file is already visible or does not exist).\n * @param fileName - The file path to unhide.\n *\n * @returns The deleted hide marker version, or `null` if nothing was hidden.\n */\n async unhideFile(fileName: string): Promise<FileVersion | null> {\n // The latest version of a hidden file appears in listFileVersions but not\n // in listFileNames. Walk versions until we find the hide marker on top.\n const resp = await this.listFileVersions({ prefix: fileName, pageSize: 100 })\n const versions = resp.files.filter((f) => f.fileName === fileName)\n if (versions.length === 0) return null\n // listFileVersions sorts by name asc then upload timestamp desc, so the\n // first entry is the latest version.\n const latest = versions[0]\n if (latest?.action !== 'hide') return null\n await this.deleteFileVersion(fileName, latest.fileId)\n return latest\n }\n\n /**\n * Hides a file by creating a hide marker. The file remains in version history but is no longer visible in `listFileNames`.\n * @param fileName - The file path to hide.\n * @param options - Optional request controls such as an abort signal.\n *\n * @returns Metadata for the newly created hide marker.\n */\n async hideFile(fileName: string, options?: { signal?: AbortSignal }): Promise<FileVersion> {\n return this.client.raw.hideFile(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { bucketId: this.id, fileName },\n options,\n )\n }\n\n /**\n * Permanently deletes a specific file version. Both file name and file ID are required.\n *\n * If the file is under Object Lock retention, B2 will reject the\n * delete: compliance-mode files cannot be deleted until the retention\n * expires; governance-mode files require `bypassGovernance: true`\n * AND a calling key with the `bypassGovernance` capability. Files on\n * legal hold cannot be deleted by anyone until the hold is removed.\n *\n * @param fileName - The file path of the version to delete.\n * @param fileId - The unique identifier of the file version to delete.\n * @param options - Optional governance and abort controls.\n */\n async deleteFileVersion(\n fileName: string,\n fileId: FileId,\n options?: { bypassGovernance?: boolean; signal?: AbortSignal },\n ): Promise<void> {\n await this.client.raw.deleteFileVersion(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n fileName,\n fileId,\n ...(options?.bypassGovernance !== undefined\n ? { bypassGovernance: options.bypassGovernance }\n : {}),\n },\n options?.signal !== undefined ? { signal: options.signal } : undefined,\n )\n }\n\n /**\n * Cancels an in-progress large file upload so the partial parts are not\n * retained or billed. The most common reason to call this is to clean up\n * abandoned multipart uploads surfaced by {@link listUnfinishedLargeFiles}.\n * @param fileId - The unique identifier of the unfinished large file to cancel.\n *\n * @returns Metadata about the cancelled large file.\n */\n async cancelLargeFile(fileId: LargeFileId): Promise<CancelLargeFileResponse> {\n return this.client.raw.cancelLargeFile(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { fileId },\n )\n }\n\n /**\n * Lists large files in this bucket that were started but never finished or\n * cancelled. Wraps `b2_list_unfinished_large_files`.\n * @param options - Optional pagination filters.\n *\n * @returns The page of unfinished large files plus a continuation token.\n */\n async listUnfinishedLargeFiles(options?: {\n /** Restrict results to files whose name starts with this prefix. */\n namePrefix?: string\n /** Start listing at this file ID, inclusive (for pagination). */\n startFileId?: LargeFileId\n /**\n * Maximum number of files to return per request (1-100). Forwarded\n * to the raw API's `maxFileCount` parameter.\n */\n pageSize?: number\n /** Abort signal for cancelling the list request. */\n signal?: AbortSignal\n }) {\n return this.client.raw.listUnfinishedLargeFiles(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n bucketId: this.id,\n ...(options?.namePrefix !== undefined ? { namePrefix: options.namePrefix } : {}),\n ...(options?.startFileId !== undefined ? { startFileId: options.startFileId } : {}),\n ...(options?.pageSize !== undefined ? { maxFileCount: options.pageSize } : {}),\n },\n options?.signal !== undefined ? { signal: options.signal } : undefined,\n )\n }\n\n /**\n * Deletes many file versions with bounded concurrency. Errors from individual\n * deletes are collected and returned rather than thrown, so partial success\n * does not abort the run.\n *\n * When `options.signal` is supplied and aborted, in-flight deletes\n * complete (they're already on the wire), but no new deletes start\n * after the abort fires. Subsequent targets are short-circuited to an\n * error entry so the result tally reflects what actually happened.\n * @param targets - File versions to delete.\n * @param options - Optional concurrency override and abort signal.\n * Concurrency defaults to the SDK-wide bulk-metadata setting\n * (currently 10, higher than transfer concurrency because each\n * task is a single tiny API round-trip).\n *\n * @returns A summary of successes and per-target errors.\n */\n async deleteMany(\n targets: readonly DeleteTarget[],\n options?: { concurrency?: number; signal?: AbortSignal },\n ): Promise<DeleteManyResult> {\n const concurrency = options?.concurrency ?? DEFAULT_BULK_CONCURRENCY\n const sem = new Semaphore(concurrency)\n const signal = options?.signal\n let deleted = 0\n const errors: DeleteError[] = []\n\n await Promise.all(\n targets.map(async (target) => {\n await sem.acquire()\n try {\n // Honour abort BETWEEN acquisitions: in-flight deletes\n // complete (they're already on the wire), but new tasks don't\n // start once the signal fires. Without this gate, aborting a\n // 1000-item deleteMany would still let the next `concurrency`\n // tasks dispatch before the caller's await returned.\n if (signal?.aborted) {\n errors.push({\n target,\n error: toError(signal.reason ?? 'aborted'),\n })\n return\n }\n await this.deleteFileVersion(target.fileName, target.fileId)\n deleted++\n } catch (err) {\n errors.push({\n target,\n error: toError(err),\n })\n } finally {\n sem.release()\n }\n }),\n )\n\n return { deleted, errors }\n }\n\n /**\n * Async generator that streams every file version in the bucket (optionally\n * filtered by prefix) and deletes each one. Yields a {@link DeleteAllEvent}\n * per file version. With `dryRun: true`, no deletes are performed but `skip`\n * events are still emitted.\n * @param options - Optional prefix filter, page size, and dry-run flag.\n *\n * @returns An async generator of per-file events.\n */\n async *deleteAll(options?: {\n /** Only delete file versions whose names start with this prefix. */\n prefix?: string\n /** Number of file versions fetched per API page (default 1000). */\n pageSize?: number\n /** If true, yield `skip` events without actually deleting anything. */\n dryRun?: boolean\n }): AsyncGenerator<DeleteAllEvent> {\n const dryRun = options?.dryRun ?? false\n const pageSize = options?.pageSize ?? DEFAULT_PAGE_SIZE\n\n let startFileName: string | undefined\n let startFileId: FileId | undefined\n while (true) {\n const page = await this.listFileVersions({\n pageSize,\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(startFileName !== undefined ? { startFileName } : {}),\n ...(startFileId !== undefined ? { startFileId } : {}),\n })\n\n for (const version of page.files) {\n if (dryRun) {\n yield { type: 'skip', fileName: version.fileName, fileId: version.fileId }\n continue\n }\n try {\n await this.deleteFileVersion(version.fileName, version.fileId)\n yield { type: 'delete', fileName: version.fileName, fileId: version.fileId }\n } catch (err) {\n yield {\n type: 'error',\n fileName: version.fileName,\n fileId: version.fileId,\n message: toError(err).message,\n }\n }\n }\n\n if (!page.nextFileName) break\n startFileName = page.nextFileName\n startFileId = page.nextFileId ?? undefined\n }\n }\n\n /**\n * Creates a server-side copy of a file within or across buckets.\n * @param options - Copy configuration including source file ID and destination name.\n *\n * @returns Metadata for the newly created file version.\n */\n async copyFile(options: {\n /** File ID of the source file to copy. */\n sourceFileId: FileId\n /** Destination file name in the target bucket. */\n fileName: string\n /** Target bucket ID. Defaults to this bucket if omitted. */\n destinationBucketId?: BucketId\n /** Whether to copy or replace file metadata. */\n metadataDirective?: MetadataDirective\n /** Override content type (only with `REPLACE` metadata directive). */\n contentType?: string\n /** Override file info (only with `REPLACE` metadata directive). */\n fileInfo?: Record<string, string>\n /**\n * @deprecated Renamed to `destinationServerSideEncryption` for consistency with\n * multipart copy. Still honored as a fallback when the new field is absent.\n */\n serverSideEncryption?: EncryptionSetting\n /** Server-side encryption for the destination file. Preferred over `serverSideEncryption`. */\n destinationServerSideEncryption?: EncryptionSetting\n /** SSE-C settings for the source if it was uploaded with SSE-C. */\n sourceServerSideEncryption?: EncryptionSetting\n /** Optional abort signal for cancelling the copy request. */\n signal?: AbortSignal\n }): Promise<FileVersion> {\n const { serverSideEncryption, destinationServerSideEncryption, signal, ...copyOptions } =\n options\n const destinationEncryption = destinationServerSideEncryption ?? serverSideEncryption\n return this.client.raw.copyFile(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n ...copyOptions,\n ...(destinationEncryption !== undefined\n ? { destinationServerSideEncryption: destinationEncryption }\n : {}),\n },\n signal !== undefined ? { signal } : undefined,\n )\n }\n\n /**\n * Copies a file via the server-side multipart protocol. Each part is copied\n * by reference through `b2_copy_part`; data never traverses the client. Falls\n * back to a single `copyFile` call when the source fits within a single part.\n * @param options - Copy parameters including source file ID, destination name, part size, and concurrency.\n *\n * @returns Metadata for the newly created destination file version.\n */\n async copyLargeFile(options: {\n /** File ID of the source file to copy. */\n sourceFileId: FileId\n /** Destination file name in the target bucket. */\n fileName: string\n /** Target bucket ID. Defaults to this bucket if omitted. */\n destinationBucketId?: BucketId\n /** Override content type for the destination. */\n contentType?: string\n /** Custom file info for the destination. */\n fileInfo?: Record<string, string>\n /** Server-side encryption for the destination file. */\n destinationServerSideEncryption?: EncryptionSetting\n /** SSE-C settings for the source if it was uploaded with SSE-C. */\n sourceServerSideEncryption?: EncryptionSetting\n /**\n * Callback invoked if best-effort cancellation fails, or if cancellation is\n * skipped because `b2_finish_large_file` may already have committed.\n */\n onCleanupFailure?: CleanupFailureListener\n /** Part size in bytes. Defaults to the account's recommended part size. */\n partSize?: number\n /**\n * Maximum number of parts copied in parallel. Defaults to the\n * SDK-wide transfer concurrency.\n */\n concurrency?: number\n /**\n * Optional abort signal. Aborting cancels any remaining parts and\n * triggers a best-effort `cancelLargeFile` on the unfinished upload.\n */\n signal?: AbortSignal\n }): Promise<FileVersion> {\n return copyLargeFile(this.client.raw, this.client.accountInfo, {\n sourceFileId: options.sourceFileId,\n fileName: options.fileName,\n ...(options.destinationBucketId !== undefined\n ? { destinationBucketId: options.destinationBucketId }\n : { destinationBucketId: this.id }),\n ...(options.contentType !== undefined ? { contentType: options.contentType } : {}),\n ...(options.fileInfo !== undefined ? { fileInfo: options.fileInfo } : {}),\n ...(options.destinationServerSideEncryption !== undefined\n ? { destinationServerSideEncryption: options.destinationServerSideEncryption }\n : {}),\n ...(options.sourceServerSideEncryption !== undefined\n ? { sourceServerSideEncryption: options.sourceServerSideEncryption }\n : {}),\n ...(options.partSize !== undefined ? { partSize: options.partSize } : {}),\n ...(options.concurrency !== undefined ? { concurrency: options.concurrency } : {}),\n ...(options.onCleanupFailure !== undefined\n ? { onCleanupFailure: options.onCleanupFailure }\n : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n })\n }\n\n /**\n * Updates bucket settings such as type, CORS, lifecycle rules, and encryption.\n * @param options - Fields to update. Omitted fields are left unchanged.\n *\n * @returns Updated bucket metadata.\n */\n async update(options: {\n /** Change the bucket access level. */\n bucketType?: BucketType\n /** Replace custom bucket metadata. */\n bucketInfo?: Record<string, string>\n /** Replace CORS rules. */\n corsRules?: CorsRule[]\n /** Change default server-side encryption. */\n defaultServerSideEncryption?: EncryptionSetting\n /** Change default file retention policy. */\n defaultRetention?: BucketRetentionPolicy\n /** Replace lifecycle rules. */\n lifecycleRules?: LifecycleRule[]\n /** Update replication configuration. */\n replicationConfiguration?: ReplicationConfiguration\n /** Optimistic locking: only update if the bucket revision matches. */\n ifRevisionIs?: number\n }): Promise<BucketInfo> {\n return this.client.raw.updateBucket(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n accountId: accountId(this.client.accountInfo.getAccountId()),\n bucketId: this.id,\n ...options,\n },\n )\n }\n\n /**\n * Permanently deletes this bucket. The bucket must be empty (no file versions).\n *\n * @returns The deleted bucket metadata.\n */\n async delete(): Promise<BucketInfo> {\n return this.client.deleteBucket(this.id)\n }\n\n /**\n * Gets a download authorization token scoped to a file name prefix in this bucket.\n * @param fileNamePrefix - Only authorize downloads of files starting with this prefix.\n * @param validDurationInSeconds - How long the authorization is valid (1-604800 seconds).\n *\n * @returns The download authorization response containing a time-limited token.\n */\n async getDownloadAuthorization(\n fileNamePrefix: string,\n validDurationInSeconds: number,\n ): Promise<DownloadAuthorizationResponse> {\n return this.client.raw.getDownloadAuthorization(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { bucketId: this.id, fileNamePrefix, validDurationInSeconds },\n )\n }\n\n /**\n * Gets the event notification rules configured for this bucket.\n *\n * @returns The current notification rules for this bucket.\n */\n async getNotificationRules(): Promise<GetBucketNotificationRulesResponse> {\n return this.client.raw.getBucketNotificationRules(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { bucketId: this.id },\n )\n }\n\n /**\n * Replaces the event notification rules for this bucket.\n * @param rules - The new set of notification rules to apply.\n *\n * @returns The updated notification rules for this bucket.\n */\n async setNotificationRules(\n rules: EventNotificationRule[],\n ): Promise<GetBucketNotificationRulesResponse> {\n return this.client.raw.setBucketNotificationRules(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { bucketId: this.id, eventNotificationRules: rules },\n )\n }\n\n /**\n * Updates the file retention policy for a specific file version. Requires file lock on the bucket.\n * @param fileName - The file path of the version to update.\n * @param fileId - The unique identifier of the file version.\n * @param retention - The new retention policy to apply.\n * @param options - Optional flags. Set `bypassGovernance: true` to shorten governance-mode retention.\n *\n * @returns The updated file retention metadata.\n */\n async updateFileRetention(\n fileName: string,\n fileId: FileId,\n retention: FileRetentionValue,\n options?: { bypassGovernance?: boolean },\n ) {\n return this.client.raw.updateFileRetention(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n fileName,\n fileId,\n fileRetention: retention,\n ...(options?.bypassGovernance !== undefined\n ? { bypassGovernance: options.bypassGovernance }\n : {}),\n },\n )\n }\n\n /**\n * Updates the legal hold status for a specific file version. Requires file lock on the bucket.\n * @param fileName - The file path of the version to update.\n * @param fileId - The unique identifier of the file version.\n * @param legalHold - The new legal hold status to apply.\n *\n * @returns The updated legal hold metadata.\n */\n async updateFileLegalHold(fileName: string, fileId: FileId, legalHold: LegalHoldValue) {\n return this.client.raw.updateFileLegalHold(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { fileName, fileId, legalHold },\n )\n }\n\n /**\n * Refetches this bucket's metadata from B2 so callers operating on\n * replication / lifecycle / retention configuration always start from the\n * server-of-record state.\n *\n * Bucket configuration is monotonically revisioned by B2: B2 increments\n * `revision` on every accepted update. The local {@link info} snapshot\n * captured at construction time goes stale as soon as anyone else (or any\n * prior `update()` call) mutates the bucket, so the ergonomic\n * add/remove helpers below always refresh before composing the next\n * `setX()` call. The result is that each helper is safe to call without\n * the caller having to thread BucketInfo through their code.\n *\n * @returns Fresh {@link BucketInfo} for this bucket.\n *\n * @throws If the bucket no longer exists.\n */\n private async refresh(): Promise<BucketInfo> {\n const fresh = await this.client.listBuckets({ bucketId: this.id })\n const found = fresh[0]\n if (!found) throw new Error(`Bucket ${this.id} not found`)\n return found.info\n }\n\n /**\n * Returns the current cross-region replication configuration, refetched\n * from B2.\n *\n * Use this when you need to read replication state without composing a\n * write. For add/remove flows the helper methods below handle the\n * refresh-then-set sequence for you.\n *\n * @returns The current {@link ReplicationConfiguration}.\n */\n async getReplication(): Promise<ReplicationConfiguration> {\n const fresh = await this.refresh()\n return fresh.replicationConfiguration\n }\n\n /**\n * Replaces this bucket's complete replication configuration.\n * @param replication - The new configuration. Pass an empty source/destination\n * pair (`{ asReplicationSource: null, asReplicationDestination: null }`)\n * to clear replication entirely.\n *\n * @returns The updated bucket metadata.\n */\n async setReplication(replication: ReplicationConfiguration): Promise<BucketInfo> {\n return this.update({ replicationConfiguration: replication })\n }\n\n /**\n * Adds (or replaces by `replicationRuleName`) a single replication rule\n * on this bucket while leaving any other rules, the source key, and the\n * destination key mapping untouched.\n *\n * When this is the very first source-side rule, `sourceApplicationKeyId`\n * must be supplied to seed `asReplicationSource.sourceApplicationKeyId`;\n * for subsequent calls the existing source key is reused unless the\n * caller explicitly overrides it.\n *\n * @param rule - The replication rule to add or replace.\n * @param options - Optional source application key ID override (or seed\n * when no source side exists yet).\n *\n * @returns The updated bucket metadata.\n *\n * @throws If no source-side replication exists yet and the caller did\n * not supply `sourceApplicationKeyId`.\n */\n async addReplicationRule(\n rule: ReplicationRule,\n options?: { sourceApplicationKeyId?: ApplicationKeyId },\n ): Promise<BucketInfo> {\n const current = (await this.refresh()).replicationConfiguration\n const existingSource = current.asReplicationSource\n const sourceKey = options?.sourceApplicationKeyId ?? existingSource?.sourceApplicationKeyId\n if (!sourceKey) {\n throw new Error(\n 'addReplicationRule: no existing source-side replication; pass options.sourceApplicationKeyId',\n )\n }\n const existingRules = existingSource?.replicationRules ?? []\n const without = existingRules.filter((r) => r.replicationRuleName !== rule.replicationRuleName)\n return this.setReplication({\n asReplicationSource: {\n sourceApplicationKeyId: sourceKey,\n replicationRules: [...without, rule],\n },\n asReplicationDestination: current.asReplicationDestination,\n })\n }\n\n /**\n * Removes a single replication rule by name. No-ops cleanly when the rule\n * is not present (returns the unchanged-but-revision-bumped bucket info).\n *\n * @param replicationRuleName - Name of the rule to remove.\n *\n * @returns The updated bucket metadata.\n */\n async removeReplicationRule(replicationRuleName: string): Promise<BucketInfo> {\n const current = (await this.refresh()).replicationConfiguration\n const existingSource = current.asReplicationSource\n if (!existingSource) {\n return this.setReplication(current)\n }\n const filtered = existingSource.replicationRules.filter(\n (r) => r.replicationRuleName !== replicationRuleName,\n )\n return this.setReplication({\n asReplicationSource: {\n sourceApplicationKeyId: existingSource.sourceApplicationKeyId,\n replicationRules: filtered,\n },\n asReplicationDestination: current.asReplicationDestination,\n })\n }\n\n /**\n * Returns the current lifecycle rules for this bucket, refetched from B2.\n *\n * @returns The current array of {@link LifecycleRule}s.\n */\n async getLifecycleRules(): Promise<readonly LifecycleRule[]> {\n const fresh = await this.refresh()\n return fresh.lifecycleRules\n }\n\n /**\n * Replaces this bucket's lifecycle rules in their entirety.\n * @param rules - The new rule set. Pass `[]` to remove all lifecycle\n * automation.\n *\n * @returns The updated bucket metadata.\n */\n async setLifecycleRules(rules: readonly LifecycleRule[]): Promise<BucketInfo> {\n return this.update({ lifecycleRules: [...rules] })\n }\n\n /**\n * Adds (or replaces, matched by `fileNamePrefix`) a single lifecycle rule\n * while leaving any other rules untouched.\n *\n * Matching on prefix mirrors B2's own data model: each unique prefix can\n * have at most one rule, and a `b2_update_bucket` call that contains two\n * rules with the same prefix is rejected. The helper enforces this for\n * the caller.\n *\n * @param rule - The lifecycle rule to add or replace.\n *\n * @returns The updated bucket metadata.\n */\n async addLifecycleRule(rule: LifecycleRule): Promise<BucketInfo> {\n const current = await this.getLifecycleRules()\n const without = current.filter((r) => r.fileNamePrefix !== rule.fileNamePrefix)\n return this.setLifecycleRules([...without, rule])\n }\n\n /**\n * Removes a single lifecycle rule by prefix. No-ops cleanly when the rule\n * is not present.\n *\n * @param fileNamePrefix - The prefix of the rule to remove.\n *\n * @returns The updated bucket metadata.\n */\n async removeLifecycleRule(fileNamePrefix: string): Promise<BucketInfo> {\n const current = await this.getLifecycleRules()\n return this.setLifecycleRules(current.filter((r) => r.fileNamePrefix !== fileNamePrefix))\n }\n\n /**\n * Returns the current default Object Lock retention policy for new\n * uploads to this bucket, refetched from B2.\n *\n * @returns The default {@link BucketRetentionPolicy} (which may be\n * `{ mode: 'none', period: null }` when Object Lock is enabled on the\n * bucket but no default is set).\n */\n async getDefaultRetention(): Promise<BucketRetentionPolicy> {\n const fresh = await this.refresh()\n return fresh.defaultRetention\n }\n\n /**\n * Sets (or clears, by passing `{ mode: 'none', period: null }`) the\n * default Object Lock retention policy applied to new uploads.\n *\n * Object Lock must already be enabled on the bucket. Buckets created\n * without `fileLockEnabled: true` cannot accept a default retention\n * policy and B2 will reject this call.\n *\n * @param policy - The new default retention policy.\n *\n * @returns The updated bucket metadata.\n */\n async setDefaultRetention(policy: BucketRetentionPolicy): Promise<BucketInfo> {\n return this.update({ defaultRetention: policy })\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bucket.js","names":[],"sources":["../src/bucket.ts"],"sourcesContent":["import type { B2Client } from './client.ts'\nimport { copyLargeFile } from './copy/large.ts'\nimport {\n type DownloadResult,\n downloadByName,\n type HeadResult,\n headByName,\n} from './download/single.ts'\nimport type { RetryOptions } from './http/retry.ts'\nimport { mergeUploadRetryOptions } from './internal/upload-retry-options.ts'\nimport { B2Object, type DownloadCallOptions, type HeadCallOptions } from './object.ts'\nimport type {\n BucketDefaultRetention,\n BucketDefaultServerSideEncryption,\n BucketDefaultServerSideEncryptionSetting,\n BucketInfo,\n BucketRetentionPolicy,\n BucketType,\n CorsRule,\n LifecycleRule,\n ReadableReplicationConfiguration,\n} from './types/bucket.ts'\nimport type { DownloadAuthorizationResponse } from './types/download.ts'\nimport type { EncryptionSetting } from './types/encryption.ts'\nimport type {\n FileNameListEntry,\n FileVersion,\n FileVersionListEntry,\n ListedConcreteFileVersion,\n ListedFileVersion,\n ListedHideFileVersion,\n ListFileNamesResponse,\n ListFileNamesWithDelimiterResponse,\n ListFileVersionsResponse,\n ListFileVersionsWithDelimiterResponse,\n MetadataDirective,\n} from './types/file.ts'\nimport { FileAction } from './types/file.ts'\nimport type { ApplicationKeyId, BucketId, FileId, LargeFileId } from './types/ids.ts'\nimport { accountId } from './types/ids.ts'\nimport type { FileRetentionValue, LegalHoldValue } from './types/lock.ts'\nimport type {\n EventNotificationRule,\n GetBucketNotificationRulesResponse,\n} from './types/notifications.ts'\nimport type { ReplicationConfiguration, ReplicationRule } from './types/replication.ts'\nimport type { CancelLargeFileResponse, PartInfo, UnfinishedLargeFile } from './types/upload.ts'\nimport type { CleanupFailureListener } from './upload/cancel.ts'\nimport { Semaphore } from './upload/concurrency.ts'\nimport { uploadLargeFile } from './upload/large.ts'\nimport {\n type BucketUploadOptions,\n rejectSmallResumeFileId,\n stripResumeOnlyOptions,\n} from './upload/options.ts'\nimport { uploadSmallFile } from './upload/single.ts'\nimport { DEFAULT_BULK_CONCURRENCY, DEFAULT_PAGE_SIZE } from './util/defaults.ts'\nimport { type PaginatorOptions, paginateItems } from './util/paginator.ts'\nimport { toError } from './util/to-error.ts'\n\nconst EMPTY_REPLICATION_CONFIGURATION: ReplicationConfiguration = {\n asReplicationSource: null,\n asReplicationDestination: null,\n}\n\nfunction readableReplicationConfigurationOrEmpty(\n response: ReadableReplicationConfiguration,\n operation: string,\n): ReplicationConfiguration {\n if (!response.isClientAuthorizedToRead) {\n throw new Error(\n `${operation}: replication configuration is not readable; grant readBucketReplications before composing replication updates`,\n )\n }\n return response.value ?? EMPTY_REPLICATION_CONFIGURATION\n}\n\n/** A target for bulk deletion: a file name and its specific version ID. */\nexport interface DeleteTarget {\n /** File name (path) of the version to delete. */\n readonly fileName: string\n /** Unique identifier of the file version. */\n readonly fileId: FileId\n}\n\n/** Per-target error encountered during bulk deletion. */\nexport interface DeleteError {\n /** The target that failed. */\n readonly target: DeleteTarget\n /** The error thrown by the underlying `deleteFileVersion` call. */\n readonly error: Error\n}\n\n/** Aggregate result of a {@link Bucket.deleteMany} run. */\nexport interface DeleteManyResult {\n /** Number of file versions successfully deleted. */\n readonly deleted: number\n /** Per-target failures. Empty on full success. */\n readonly errors: readonly DeleteError[]\n}\n\n/** Emitted by {@link Bucket.deleteAll} once a file version has been successfully deleted. */\nexport interface DeleteAllDeleteEvent {\n /** Discriminant identifying a successful delete. */\n readonly type: 'delete'\n /** File name of the deleted version. */\n readonly fileName: string\n /** Unique identifier of the deleted version. */\n readonly fileId: FileId\n}\n\n/** Emitted by {@link Bucket.deleteAll} when a single delete call fails (other versions keep streaming). */\nexport interface DeleteAllErrorEvent {\n /** Discriminant identifying a per-version delete failure. */\n readonly type: 'error'\n /** File name of the version that failed to delete. */\n readonly fileName: string\n /** Unique identifier of the version that failed to delete. */\n readonly fileId: FileId\n /** Human-readable failure reason taken from the underlying error. */\n readonly message: string\n}\n\n/** Emitted by {@link Bucket.deleteAll} in `dryRun` mode for every version that would have been deleted. */\nexport interface DeleteAllSkipEvent {\n /** Discriminant identifying a dry-run skip. */\n readonly type: 'skip'\n /** File name of the version that would have been deleted. */\n readonly fileName: string\n /** Unique identifier of the version that would have been deleted. */\n readonly fileId: FileId\n}\n\n/** Event yielded by {@link Bucket.deleteAll} as it streams through file versions. */\nexport type DeleteAllEvent = DeleteAllDeleteEvent | DeleteAllErrorEvent | DeleteAllSkipEvent\n\n/** Shared options for {@link Bucket.listFileNames}. */\nexport interface BucketListFileNamesBaseOptions {\n /** Start listing after this file name (for pagination). */\n startFileName?: string\n /**\n * Maximum number of files to return per request (1-10000).\n * Forwarded to the raw API's `maxFileCount` parameter.\n */\n pageSize?: number\n /** Only list files with names starting with this prefix. */\n prefix?: string\n /** Optional abort signal for the listing request. */\n signal?: AbortSignal\n}\n\n/** Options for non-delimiter {@link Bucket.listFileNames} calls. */\nexport interface BucketListFileNamesOptions extends BucketListFileNamesBaseOptions {\n /** Omit delimiter to receive only concrete file-version entries. */\n delimiter?: undefined\n}\n\n/** Options for delimiter-grouped {@link Bucket.listFileNames} calls. */\nexport interface BucketListFileNamesWithDelimiterOptions extends BucketListFileNamesBaseOptions {\n /** Delimiter for virtual directory grouping (typically `\"/\"`). */\n delimiter: string\n}\n\n/** Options for callers that dynamically include a delimiter. */\nexport interface BucketListFileNamesMaybeDelimiterOptions extends BucketListFileNamesBaseOptions {\n /** Optional delimiter for virtual directory grouping. */\n delimiter?: string | undefined\n}\n\n/** Shared options for {@link Bucket.listFileVersions}. */\nexport interface BucketListFileVersionsBaseOptions {\n /** Start listing after this file name (for pagination). */\n startFileName?: string\n /** Start listing after this file ID (for pagination within a file name). */\n startFileId?: FileId\n /**\n * Maximum number of file versions to return per request (1-10000).\n * Forwarded to the raw API's `maxFileCount` parameter.\n */\n pageSize?: number\n /** Only list files with names starting with this prefix. */\n prefix?: string\n /** Optional abort signal for the listing request. */\n signal?: AbortSignal\n}\n\n/** Options for non-delimiter {@link Bucket.listFileVersions} calls. */\nexport interface BucketListFileVersionsOptions extends BucketListFileVersionsBaseOptions {\n /** Omit delimiter to receive only concrete file-version entries. */\n delimiter?: undefined\n}\n\n/** Options for delimiter-grouped {@link Bucket.listFileVersions} calls. */\nexport interface BucketListFileVersionsWithDelimiterOptions\n extends BucketListFileVersionsBaseOptions {\n /** Delimiter for virtual directory grouping. */\n delimiter: string\n}\n\n/** Options for callers that dynamically include a delimiter. */\nexport interface BucketListFileVersionsMaybeDelimiterOptions\n extends BucketListFileVersionsBaseOptions {\n /** Optional delimiter for virtual directory grouping. */\n delimiter?: string | undefined\n}\n\n/** Options for non-delimiter {@link Bucket.paginateFileNames} iterators. */\nexport type BucketPaginateFileNamesOptions = {\n /** Only yield files whose names start with this prefix. */\n prefix?: string\n /** Omit delimiter to receive only concrete file-version entries. */\n delimiter?: undefined\n} & PaginatorOptions\n\n/** Options for delimiter-grouped {@link Bucket.paginateFileNames} iterators. */\nexport type BucketPaginateFileNamesWithDelimiterOptions = {\n /** Only yield files whose names start with this prefix. */\n prefix?: string\n /** Delimiter for virtual directory grouping (typically `'/'`). */\n delimiter: string\n} & PaginatorOptions\n\n/** Options for callers that dynamically include a delimiter. */\nexport type BucketPaginateFileNamesMaybeDelimiterOptions = {\n /** Only yield files whose names start with this prefix. */\n prefix?: string\n /** Optional delimiter for virtual directory grouping. */\n delimiter?: string | undefined\n} & PaginatorOptions\n\n/** Options for non-delimiter {@link Bucket.paginateFileVersions} iterators. */\nexport type BucketPaginateFileVersionsOptions = {\n /** Only yield versions whose names start with this prefix. */\n prefix?: string\n /** Omit delimiter to receive only concrete file-version entries. */\n delimiter?: undefined\n} & PaginatorOptions\n\n/** Options for delimiter-grouped {@link Bucket.paginateFileVersions} iterators. */\nexport type BucketPaginateFileVersionsWithDelimiterOptions = {\n /** Only yield versions whose names start with this prefix. */\n prefix?: string\n /** Delimiter for virtual directory grouping. */\n delimiter: string\n} & PaginatorOptions\n\n/** Options for callers that dynamically include a delimiter. */\nexport type BucketPaginateFileVersionsMaybeDelimiterOptions = {\n /** Only yield versions whose names start with this prefix. */\n prefix?: string\n /** Optional delimiter for virtual directory grouping. */\n delimiter?: string | undefined\n} & PaginatorOptions\n\ninterface BucketDefaultRetentionSnapshot {\n readonly retention?: BucketDefaultRetention\n readonly unreadable: boolean\n}\n\ninterface BucketDefaultServerSideEncryptionSnapshot {\n readonly encryption?: BucketDefaultServerSideEncryption\n readonly unreadable: boolean\n}\n\nfunction bucketDefaultRetentionSnapshot(info: BucketInfo): BucketDefaultRetentionSnapshot {\n const fileLock = info.fileLockConfiguration\n if (!fileLock.isClientAuthorizedToRead) return { unreadable: true }\n if (fileLock.value === null) return { unreadable: false }\n return { retention: fileLock.value.defaultRetention, unreadable: false }\n}\n\nfunction bucketDefaultServerSideEncryptionSnapshot(\n info: BucketInfo,\n): BucketDefaultServerSideEncryptionSnapshot {\n const encryption = info.defaultServerSideEncryption\n if (!encryption.isClientAuthorizedToRead) return { unreadable: true }\n if (encryption.value === null) return { unreadable: false }\n return { encryption: encryption.value, unreadable: false }\n}\n\nfunction resumeNeedsFreshBucketDefaults(options: BucketUploadOptions): boolean {\n const resumeRequested = options.resume === true || options.resumeFileId !== undefined\n return (\n resumeRequested &&\n (options.serverSideEncryption === undefined || options.fileRetention === undefined)\n )\n}\n\nfunction listedVersionFileIdOrThrow(version: ListedConcreteFileVersion): FileId {\n const fileId = (version as { readonly fileId?: unknown }).fileId\n if (typeof fileId === 'string') return fileId as FileId\n throw new Error(\n `deleteAll: listFileVersions returned a row without a fileId for ${JSON.stringify(\n version.fileName,\n )}; delimiter folder rows are invalid because deleteAll does not request delimiter grouping`,\n )\n}\n\nfunction listedFileIdOrThrow(\n version: { readonly action: unknown; readonly fileId?: unknown; readonly fileName: string },\n operation: string,\n): FileId {\n if (typeof version.fileId === 'string') return version.fileId as FileId\n throw new Error(\n `${operation}: list response returned a row without a string fileId for ${JSON.stringify(\n version.fileName,\n )}`,\n )\n}\n\nfunction assertNotFolderListEntry(\n version: FileVersionListEntry,\n operation: string,\n): asserts version is ListedConcreteFileVersion {\n if (version.action !== FileAction.Folder) return\n throw new Error(\n `${operation}: list response returned a delimiter folder row for ${JSON.stringify(\n version.fileName,\n )} without requesting delimiter grouping`,\n )\n}\n\nfunction validateListedConcreteEntry(\n version: FileVersionListEntry,\n operation: string,\n): ListedConcreteFileVersion {\n assertNotFolderListEntry(version, operation)\n listedFileIdOrThrow(version, operation)\n return version\n}\n\nfunction validateListedNameEntry(\n version: FileNameListEntry | ListedConcreteFileVersion,\n operation: string,\n options: { allowFolder: boolean },\n): FileNameListEntry {\n if (version.action === FileAction.Folder) {\n if (options.allowFolder) return version\n throw new Error(\n `${operation}: list response returned a delimiter folder row for ${JSON.stringify(\n version.fileName,\n )} without requesting delimiter grouping`,\n )\n }\n if (version.action === FileAction.Hide) {\n throw new Error(\n `${operation}: list response returned a hide marker for ${JSON.stringify(\n version.fileName,\n )}; b2_list_file_names only returns visible file versions`,\n )\n }\n listedFileIdOrThrow(version, operation)\n return version\n}\n\nfunction validateListFileNamesResponse(\n response: ListFileNamesResponse | ListFileNamesWithDelimiterResponse,\n options: { allowFolder: false },\n): ListFileNamesResponse\nfunction validateListFileNamesResponse(\n response: ListFileNamesResponse | ListFileNamesWithDelimiterResponse,\n options: { allowFolder: true },\n): ListFileNamesWithDelimiterResponse\nfunction validateListFileNamesResponse(\n response: ListFileNamesResponse | ListFileNamesWithDelimiterResponse,\n options: { allowFolder: boolean },\n): ListFileNamesResponse | ListFileNamesWithDelimiterResponse {\n const files = response.files.map((version) =>\n validateListedNameEntry(version, 'listFileNames', options),\n )\n return { ...response, files }\n}\n\nfunction validateListFileVersionsResponse(\n response: ListFileVersionsResponse | ListFileVersionsWithDelimiterResponse,\n options: { allowFolder: false },\n): ListFileVersionsResponse\nfunction validateListFileVersionsResponse(\n response: ListFileVersionsResponse | ListFileVersionsWithDelimiterResponse,\n options: { allowFolder: true },\n): ListFileVersionsWithDelimiterResponse\nfunction validateListFileVersionsResponse(\n response: ListFileVersionsResponse | ListFileVersionsWithDelimiterResponse,\n options: { allowFolder: boolean },\n): ListFileVersionsResponse | ListFileVersionsWithDelimiterResponse {\n if (options.allowFolder) {\n const files = response.files.map((version) => {\n if (version.action === FileAction.Folder) return version\n return validateListedConcreteEntry(version, 'listFileVersions')\n })\n return { ...response, files }\n }\n const files = response.files.map((version) =>\n validateListedConcreteEntry(version, 'listFileVersions'),\n )\n return { ...response, files }\n}\n\n/**\n * Handle to a B2 bucket providing upload, download, listing, and management operations.\n *\n * Obtained via {@link B2Client.createBucket}, {@link B2Client.listBuckets}, or {@link B2Client.getBucket}.\n *\n * @example\n * ```ts\n * const bucket = await client.getBucket('my-bucket')\n * await bucket.upload({ fileName: 'hello.txt', source: new BufferSource(data) })\n * ```\n */\nexport class Bucket {\n /** Unique identifier for this bucket. */\n readonly id: BucketId\n /** Human-readable bucket name. */\n readonly name: string\n /** Full bucket metadata as returned by the B2 API. */\n readonly info: BucketInfo\n private readonly client: B2Client\n private readonly uploadRetryOptions: RetryOptions\n\n /**\n * @param client - The parent B2Client instance.\n * @param info - The bucket metadata from the API.\n * @param uploadRetryOptions - Resolved client upload retry defaults.\n *\n * @internal\n */\n constructor(client: B2Client, info: BucketInfo, uploadRetryOptions: RetryOptions) {\n this.client = client\n this.info = info\n this.id = info.bucketId\n this.name = info.bucketName\n this.uploadRetryOptions = uploadRetryOptions\n }\n\n /**\n * Returns a {@link B2Object} handle for a specific file name in this bucket.\n * @param fileName - The file path within the bucket.\n *\n * @returns A B2Object handle bound to this bucket and file name.\n */\n file(fileName: string): B2Object {\n return new B2Object(this.client, this, fileName, this.uploadRetryOptions)\n }\n\n /**\n * Uploads a file to this bucket. Automatically uses multipart upload for files\n * larger than the recommended part size.\n * @param options - Upload configuration including file name, source data, and optional settings.\n *\n * @returns Metadata for the uploaded file version.\n */\n async upload(options: BucketUploadOptions): Promise<FileVersion> {\n const recommendedPartSize = this.client.accountInfo.getRecommendedPartSize()\n const isLarge = options.source.size > recommendedPartSize\n const uploadRetryOptions = mergeUploadRetryOptions(this.uploadRetryOptions, options.retry)\n\n if (isLarge) {\n const bucketInfo = resumeNeedsFreshBucketDefaults(options) ? await this.refresh() : this.info\n const bucketDefaultRetention = bucketDefaultRetentionSnapshot(bucketInfo)\n const bucketDefaultSse = bucketDefaultServerSideEncryptionSnapshot(bucketInfo)\n return uploadLargeFile(this.client.raw, this.client.accountInfo, {\n ...options,\n bucketId: this.id,\n retry: uploadRetryOptions,\n ...(bucketDefaultSse.encryption !== undefined\n ? { bucketDefaultServerSideEncryption: bucketDefaultSse.encryption }\n : {}),\n ...(bucketDefaultSse.unreadable\n ? { bucketDefaultServerSideEncryptionUnreadable: true }\n : {}),\n ...(bucketDefaultRetention.retention !== undefined\n ? { bucketDefaultRetention: bucketDefaultRetention.retention }\n : {}),\n ...(bucketDefaultRetention.unreadable ? { bucketDefaultRetentionUnreadable: true } : {}),\n })\n }\n rejectSmallResumeFileId(options, 'Bucket.upload')\n const smallOptions = stripResumeOnlyOptions(options)\n return uploadSmallFile(this.client.raw, this.client.accountInfo, {\n ...smallOptions,\n bucketId: this.id,\n retry: uploadRetryOptions,\n })\n }\n\n /**\n * Downloads a file from this bucket by name. Pass `method: 'HEAD'` in\n * `options` to fetch only the response headers (file metadata) without\n * streaming the body.\n * @param fileName - The file name (path) to download.\n * @param options - Optional method, range, SSE-C decryption, response-header overrides, and abort signal.\n *\n * @returns The download result containing response headers and a readable body stream.\n */\n async download(fileName: string, options?: DownloadCallOptions): Promise<DownloadResult> {\n return downloadByName(this.client.raw, this.client.accountInfo, {\n bucketName: this.name,\n fileName,\n ...options,\n })\n }\n\n /**\n * Fetches the response headers (file metadata) for a file via HTTP\n * HEAD. Returns a body-less result so callers never have to drain\n * the (logically empty) HEAD body themselves.\n *\n * Use this for metadata-only checks like \"does this file exist\", \"what\n * is its current SHA-1\", \"what is its Content-Length\". For full file\n * retrieval use {@link Bucket.download}.\n *\n * @param fileName - The file name (path) to inspect.\n * @param options - Optional range, SSE-C decryption, response-header\n * overrides, and abort signal. Same shape as {@link Bucket.download}'s\n * options minus `method` (always HEAD) and `onProgress` (no body).\n *\n * @returns Parsed download headers (content type, SHA-1, file info, etc.).\n *\n * @example\n * ```ts\n * const { headers } = await bucket.head('photos/2026/sunset.jpg')\n * console.log(headers.contentLength, headers.contentSha1)\n * ```\n */\n async head(fileName: string, options?: HeadCallOptions): Promise<HeadResult> {\n return headByName(this.client.raw, this.client.accountInfo, {\n bucketName: this.name,\n fileName,\n ...options,\n })\n }\n\n /**\n * Lists file names in this bucket (most recent versions only).\n * Omitting `delimiter` returns only concrete file-version entries. Passing\n * `delimiter` returns the delimiter overload, whose page may include\n * virtual folder rows.\n * @param options - Optional filtering and pagination settings.\n *\n * @returns A page of file versions with an optional continuation token.\n */\n async listFileNames(\n options: BucketListFileNamesWithDelimiterOptions,\n ): Promise<ListFileNamesWithDelimiterResponse>\n async listFileNames(options?: BucketListFileNamesOptions): Promise<ListFileNamesResponse>\n async listFileNames(\n options: BucketListFileNamesMaybeDelimiterOptions,\n ): Promise<ListFileNamesResponse | ListFileNamesWithDelimiterResponse>\n async listFileNames(\n options?:\n | BucketListFileNamesOptions\n | BucketListFileNamesWithDelimiterOptions\n | BucketListFileNamesMaybeDelimiterOptions,\n ): Promise<ListFileNamesResponse | ListFileNamesWithDelimiterResponse> {\n const response = await this.client.raw.listFileNames(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n bucketId: this.id,\n ...(options?.startFileName !== undefined ? { startFileName: options.startFileName } : {}),\n ...(options?.pageSize !== undefined ? { maxFileCount: options.pageSize } : {}),\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options?.delimiter !== undefined ? { delimiter: options.delimiter } : {}),\n },\n {\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n },\n )\n return options?.delimiter !== undefined\n ? validateListFileNamesResponse(response, { allowFolder: true })\n : validateListFileNamesResponse(response, { allowFolder: false })\n }\n\n /**\n * Lists all file versions in this bucket, including hidden files.\n * Omitting `delimiter` returns only concrete file-version entries. Passing\n * `delimiter` returns the delimiter overload, whose page may include\n * virtual folder rows.\n * @param options - Optional filtering and pagination settings.\n *\n * @returns A page of file versions with an optional continuation token.\n */\n async listFileVersions(\n options: BucketListFileVersionsWithDelimiterOptions,\n ): Promise<ListFileVersionsWithDelimiterResponse>\n async listFileVersions(options?: BucketListFileVersionsOptions): Promise<ListFileVersionsResponse>\n async listFileVersions(\n options: BucketListFileVersionsMaybeDelimiterOptions,\n ): Promise<ListFileVersionsResponse | ListFileVersionsWithDelimiterResponse>\n async listFileVersions(\n options?:\n | BucketListFileVersionsOptions\n | BucketListFileVersionsWithDelimiterOptions\n | BucketListFileVersionsMaybeDelimiterOptions,\n ): Promise<ListFileVersionsResponse | ListFileVersionsWithDelimiterResponse> {\n const response = await this.client.raw.listFileVersions(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n bucketId: this.id,\n ...(options?.startFileName !== undefined ? { startFileName: options.startFileName } : {}),\n ...(options?.startFileId !== undefined ? { startFileId: options.startFileId } : {}),\n ...(options?.pageSize !== undefined ? { maxFileCount: options.pageSize } : {}),\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options?.delimiter !== undefined ? { delimiter: options.delimiter } : {}),\n },\n {\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n },\n )\n return options?.delimiter !== undefined\n ? validateListFileVersionsResponse(response, { allowFolder: true })\n : validateListFileVersionsResponse(response, { allowFolder: false })\n }\n\n /**\n * Async iterator that yields the latest visible version of every file in\n * the bucket, automatically handling pagination via `listFileNames`.\n *\n * Hidden files (those whose latest version is a hide marker) are NOT\n * yielded by this iterator. Use {@link paginateFileVersions} when you\n * need full version history.\n *\n * @param options - Filter + pagination + abort options. `pageSize` is\n * forwarded to `b2_list_file_names`'s `maxFileCount` (default 1000,\n * B2-capped at 10000).\n *\n * @returns An async iterable of concrete file versions. Passing `delimiter`\n * selects the delimiter overload, which may also yield virtual folders.\n *\n * @example\n * ```ts\n * for await (const file of bucket.paginateFileNames({ prefix: 'photos/' })) {\n * console.log(file.fileName, file.contentLength)\n * }\n * ```\n */\n paginateFileNames(\n options: BucketPaginateFileNamesWithDelimiterOptions,\n ): AsyncIterableIterator<FileNameListEntry>\n paginateFileNames(\n options?: BucketPaginateFileNamesOptions,\n ): AsyncIterableIterator<ListedFileVersion>\n paginateFileNames(\n options: BucketPaginateFileNamesMaybeDelimiterOptions,\n ): AsyncIterableIterator<ListedFileVersion | FileNameListEntry>\n paginateFileNames(\n options?:\n | BucketPaginateFileNamesOptions\n | BucketPaginateFileNamesWithDelimiterOptions\n | BucketPaginateFileNamesMaybeDelimiterOptions,\n ): AsyncIterableIterator<ListedFileVersion | FileNameListEntry> {\n return paginateItems(\n async (cursor: string | undefined) => {\n const request = {\n pageSize: options?.pageSize ?? DEFAULT_PAGE_SIZE,\n ...(cursor !== undefined ? { startFileName: cursor } : {}),\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n }\n const resp =\n options?.delimiter !== undefined\n ? await this.listFileNames({ ...request, delimiter: options.delimiter })\n : await this.listFileNames(request)\n return { page: resp, nextCursor: resp.nextFileName ?? undefined }\n },\n (page) => page.files,\n options?.signal,\n )\n }\n\n /**\n * Async iterator that yields every version of every file in the bucket,\n * including hidden files and historical versions, automatically handling\n * pagination via `listFileVersions`.\n *\n * The two-cursor `(nextFileName, nextFileId)` continuation that the raw\n * endpoint exposes is threaded internally; callers iterate flat.\n *\n * @param options - Filter + pagination + abort options.\n *\n * @returns An async iterable of concrete file-version entries. Passing\n * `delimiter` selects the delimiter overload, which may also yield virtual\n * folders.\n */\n paginateFileVersions(\n options: BucketPaginateFileVersionsWithDelimiterOptions,\n ): AsyncIterableIterator<FileVersionListEntry>\n paginateFileVersions(\n options?: BucketPaginateFileVersionsOptions,\n ): AsyncIterableIterator<ListedConcreteFileVersion>\n paginateFileVersions(\n options: BucketPaginateFileVersionsMaybeDelimiterOptions,\n ): AsyncIterableIterator<ListedConcreteFileVersion | FileVersionListEntry>\n paginateFileVersions(\n options?:\n | BucketPaginateFileVersionsOptions\n | BucketPaginateFileVersionsWithDelimiterOptions\n | BucketPaginateFileVersionsMaybeDelimiterOptions,\n ): AsyncIterableIterator<ListedConcreteFileVersion | FileVersionListEntry> {\n type Cursor = { fileName: string; fileId: FileId | undefined }\n return paginateItems(\n async (cursor: Cursor | undefined) => {\n const request = {\n pageSize: options?.pageSize ?? DEFAULT_PAGE_SIZE,\n ...(cursor !== undefined ? { startFileName: cursor.fileName } : {}),\n ...(cursor?.fileId !== undefined ? { startFileId: cursor.fileId } : {}),\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n }\n const resp =\n options?.delimiter !== undefined\n ? await this.listFileVersions({ ...request, delimiter: options.delimiter })\n : await this.listFileVersions(request)\n const nextCursor: Cursor | undefined =\n resp.nextFileName !== null\n ? { fileName: resp.nextFileName, fileId: resp.nextFileId ?? undefined }\n : undefined\n return { page: resp, nextCursor }\n },\n (page) => page.files,\n options?.signal,\n )\n }\n\n /**\n * Async iterator that yields every unfinished large file in the bucket,\n * automatically handling pagination via `listUnfinishedLargeFiles`.\n *\n * Useful for janitorial scripts that want to inspect or cancel abandoned\n * multipart uploads (typically followed by {@link cancelLargeFile} on\n * the underlying raw client).\n *\n * @param options - Filter + pagination + abort options. `pageSize` is\n * B2-capped at 100 for this endpoint.\n *\n * @returns An async iterable of unfinished-large-file metadata entries.\n */\n paginateUnfinishedLargeFiles(\n options?: {\n /** Only yield large files whose names start with this prefix. */\n namePrefix?: string\n } & PaginatorOptions,\n ): AsyncIterableIterator<UnfinishedLargeFile> {\n return paginateItems(\n async (cursor: LargeFileId | undefined) => {\n const resp = await this.listUnfinishedLargeFiles({\n pageSize: options?.pageSize ?? 100,\n ...(cursor !== undefined ? { startFileId: cursor } : {}),\n ...(options?.namePrefix !== undefined ? { namePrefix: options.namePrefix } : {}),\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n })\n return { page: resp, nextCursor: resp.nextFileId ?? undefined }\n },\n (page) => page.files,\n options?.signal,\n )\n }\n\n /**\n * Async iterator that yields every uploaded part for a specific large\n * file, automatically handling pagination via `listParts`.\n *\n * @param largeFileId - The unfinished large file to enumerate parts of.\n * @param options - Pagination + abort options. `pageSize` is B2-capped\n * at 1000 for this endpoint; the default is 1000.\n *\n * @returns An async iterable of {@link PartInfo} entries.\n */\n paginateParts(\n largeFileId: LargeFileId,\n options?: PaginatorOptions,\n ): AsyncIterableIterator<PartInfo> {\n return paginateItems(\n async (cursor: number | undefined) => {\n const resp = await this.client.raw.listParts(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n fileId: largeFileId,\n maxPartCount: options?.pageSize ?? DEFAULT_PAGE_SIZE,\n ...(cursor !== undefined ? { startPartNumber: cursor } : {}),\n },\n options?.signal !== undefined ? { signal: options.signal } : undefined,\n )\n return { page: resp, nextCursor: resp.nextPartNumber ?? undefined }\n },\n (page) => page.parts,\n options?.signal,\n )\n }\n\n /**\n * Looks up the latest visible version of a file by name.\n * Uses `listFileNames` under the hood; returns `null` when the file does not\n * exist or is hidden.\n * @param fileName - The exact file path to look up.\n *\n * @returns The latest {@link FileVersion}, or `null` if not found.\n */\n async getFileInfoByName(fileName: string): Promise<FileVersion | null> {\n const resp = await this.listFileNames({ prefix: fileName, pageSize: 1 })\n const match = resp.files.find((f) => f.fileName === fileName)\n if (!match) return null\n return match\n }\n\n /**\n * Removes the latest hide marker for a file, restoring visibility of the\n * previous upload. Returns the deleted hide marker, or `null` if there was\n * no hide marker to remove (file is already visible or does not exist).\n * @param fileName - The file path to unhide.\n *\n * @returns The deleted listed hide-marker row, or `null` if nothing was hidden.\n */\n async unhideFile(fileName: string): Promise<ListedHideFileVersion | null> {\n // The latest version of a hidden file appears in listFileVersions but not\n // in listFileNames. Walk versions until we find the hide marker on top.\n const resp = await this.listFileVersions({ prefix: fileName, pageSize: 100 })\n const versions = resp.files.filter((f) => f.fileName === fileName)\n if (versions.length === 0) return null\n // listFileVersions sorts by name asc then upload timestamp desc, so the\n // first entry is the latest version.\n const latest = versions[0]\n if (latest?.action !== FileAction.Hide) return null\n const latestFileId = (latest as { readonly fileId?: unknown }).fileId\n if (typeof latestFileId !== 'string') {\n throw new Error(\n `unhideFile: listFileVersions returned a hide marker without a fileId for ${JSON.stringify(\n fileName,\n )}`,\n )\n }\n await this.deleteFileVersion(fileName, latestFileId as FileId)\n return latest\n }\n\n /**\n * Hides a file by creating a hide marker. The file remains in version history but is no longer visible in `listFileNames`.\n * @param fileName - The file path to hide.\n * @param options - Optional request controls such as an abort signal.\n *\n * @returns Metadata for the newly created hide marker.\n */\n async hideFile(fileName: string, options?: { signal?: AbortSignal }): Promise<FileVersion> {\n return this.client.raw.hideFile(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { bucketId: this.id, fileName },\n options,\n )\n }\n\n /**\n * Permanently deletes a specific file version. Both file name and file ID are required.\n *\n * If the file is under Object Lock retention, B2 will reject the\n * delete: compliance-mode files cannot be deleted until the retention\n * expires; governance-mode files require `bypassGovernance: true`\n * AND a calling key with the `bypassGovernance` capability. Files on\n * legal hold cannot be deleted by anyone until the hold is removed.\n *\n * @param fileName - The file path of the version to delete.\n * @param fileId - The unique identifier of the file version to delete.\n * @param options - Optional governance and abort controls.\n */\n async deleteFileVersion(\n fileName: string,\n fileId: FileId,\n options?: { bypassGovernance?: boolean; signal?: AbortSignal },\n ): Promise<void> {\n await this.client.raw.deleteFileVersion(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n fileName,\n fileId,\n ...(options?.bypassGovernance !== undefined\n ? { bypassGovernance: options.bypassGovernance }\n : {}),\n },\n options?.signal !== undefined ? { signal: options.signal } : undefined,\n )\n }\n\n /**\n * Cancels an in-progress large file upload so the partial parts are not\n * retained or billed. The most common reason to call this is to clean up\n * abandoned multipart uploads surfaced by {@link listUnfinishedLargeFiles}.\n * @param fileId - The unique identifier of the unfinished large file to cancel.\n *\n * @returns Metadata about the cancelled large file.\n */\n async cancelLargeFile(fileId: LargeFileId): Promise<CancelLargeFileResponse> {\n return this.client.raw.cancelLargeFile(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { fileId },\n )\n }\n\n /**\n * Lists large files in this bucket that were started but never finished or\n * cancelled. Wraps `b2_list_unfinished_large_files`.\n * @param options - Optional pagination filters.\n *\n * @returns The page of unfinished large files plus a continuation token.\n */\n async listUnfinishedLargeFiles(options?: {\n /** Restrict results to files whose name starts with this prefix. */\n namePrefix?: string\n /** Start listing at this file ID, inclusive (for pagination). */\n startFileId?: LargeFileId\n /**\n * Maximum number of files to return per request (1-100). Forwarded\n * to the raw API's `maxFileCount` parameter.\n */\n pageSize?: number\n /** Abort signal for cancelling the list request. */\n signal?: AbortSignal\n }) {\n return this.client.raw.listUnfinishedLargeFiles(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n bucketId: this.id,\n ...(options?.namePrefix !== undefined ? { namePrefix: options.namePrefix } : {}),\n ...(options?.startFileId !== undefined ? { startFileId: options.startFileId } : {}),\n ...(options?.pageSize !== undefined ? { maxFileCount: options.pageSize } : {}),\n },\n options?.signal !== undefined ? { signal: options.signal } : undefined,\n )\n }\n\n /**\n * Deletes many file versions with bounded concurrency. Errors from individual\n * deletes are collected and returned rather than thrown, so partial success\n * does not abort the run.\n *\n * When `options.signal` is supplied and aborted, in-flight deletes\n * complete (they're already on the wire), but no new deletes start\n * after the abort fires. Subsequent targets are short-circuited to an\n * error entry so the result tally reflects what actually happened.\n * @param targets - File versions to delete.\n * @param options - Optional concurrency override and abort signal.\n * Concurrency defaults to the SDK-wide bulk-metadata setting\n * (currently 10, higher than transfer concurrency because each\n * task is a single tiny API round-trip).\n *\n * @returns A summary of successes and per-target errors.\n */\n async deleteMany(\n targets: readonly DeleteTarget[],\n options?: { concurrency?: number; signal?: AbortSignal },\n ): Promise<DeleteManyResult> {\n const concurrency = options?.concurrency ?? DEFAULT_BULK_CONCURRENCY\n const sem = new Semaphore(concurrency)\n const signal = options?.signal\n let deleted = 0\n const errors: DeleteError[] = []\n\n await Promise.all(\n targets.map(async (target) => {\n await sem.acquire()\n try {\n // Honour abort BETWEEN acquisitions: in-flight deletes\n // complete (they're already on the wire), but new tasks don't\n // start once the signal fires. Without this gate, aborting a\n // 1000-item deleteMany would still let the next `concurrency`\n // tasks dispatch before the caller's await returned.\n if (signal?.aborted) {\n errors.push({\n target,\n error: toError(signal.reason ?? 'aborted'),\n })\n return\n }\n await this.deleteFileVersion(target.fileName, target.fileId)\n deleted++\n } catch (err) {\n errors.push({\n target,\n error: toError(err),\n })\n } finally {\n sem.release()\n }\n }),\n )\n\n return { deleted, errors }\n }\n\n /**\n * Async generator that streams every file version in the bucket (optionally\n * filtered by prefix) and deletes each one. Yields a {@link DeleteAllEvent}\n * per file version. With `dryRun: true`, no deletes are performed but `skip`\n * events are still emitted.\n * @param options - Optional prefix filter, page size, and dry-run flag.\n *\n * @returns An async generator of per-file events.\n */\n async *deleteAll(options?: {\n /** Only delete file versions whose names start with this prefix. */\n prefix?: string\n /** Number of file versions fetched per API page (default 1000). */\n pageSize?: number\n /** If true, yield `skip` events without actually deleting anything. */\n dryRun?: boolean\n }): AsyncGenerator<DeleteAllEvent> {\n const dryRun = options?.dryRun ?? false\n const pageSize = options?.pageSize ?? DEFAULT_PAGE_SIZE\n\n let startFileName: string | undefined\n let startFileId: FileId | undefined\n while (true) {\n const page = await this.listFileVersions({\n pageSize,\n ...(options?.prefix !== undefined ? { prefix: options.prefix } : {}),\n ...(startFileName !== undefined ? { startFileName } : {}),\n ...(startFileId !== undefined ? { startFileId } : {}),\n })\n\n for (const version of page.files) {\n const fileId = listedVersionFileIdOrThrow(version)\n if (dryRun) {\n yield { type: 'skip', fileName: version.fileName, fileId }\n continue\n }\n try {\n await this.deleteFileVersion(version.fileName, fileId)\n yield { type: 'delete', fileName: version.fileName, fileId }\n } catch (err) {\n yield {\n type: 'error',\n fileName: version.fileName,\n fileId,\n message: toError(err).message,\n }\n }\n }\n\n if (!page.nextFileName) break\n startFileName = page.nextFileName\n startFileId = page.nextFileId ?? undefined\n }\n }\n\n /**\n * Creates a server-side copy of a file within or across buckets.\n * @param options - Copy configuration including source file ID and destination name.\n *\n * @returns Metadata for the newly created file version.\n */\n async copyFile(options: {\n /** File ID of the source file to copy. */\n sourceFileId: FileId\n /** Destination file name in the target bucket. */\n fileName: string\n /** Target bucket ID. Defaults to this bucket if omitted. */\n destinationBucketId?: BucketId\n /** Whether to copy or replace file metadata. */\n metadataDirective?: MetadataDirective\n /** Override content type (only with `REPLACE` metadata directive). */\n contentType?: string\n /** Override file info (only with `REPLACE` metadata directive). */\n fileInfo?: Record<string, string>\n /**\n * @deprecated Renamed to `destinationServerSideEncryption` for consistency with\n * multipart copy. Still honored as a fallback when the new field is absent.\n */\n serverSideEncryption?: EncryptionSetting\n /** Server-side encryption for the destination file. Preferred over `serverSideEncryption`. */\n destinationServerSideEncryption?: EncryptionSetting\n /** SSE-C settings for the source if it was uploaded with SSE-C. */\n sourceServerSideEncryption?: EncryptionSetting\n /** Optional abort signal for cancelling the copy request. */\n signal?: AbortSignal\n }): Promise<FileVersion> {\n const { serverSideEncryption, destinationServerSideEncryption, signal, ...copyOptions } =\n options\n const destinationEncryption = destinationServerSideEncryption ?? serverSideEncryption\n return this.client.raw.copyFile(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n ...copyOptions,\n ...(destinationEncryption !== undefined\n ? { destinationServerSideEncryption: destinationEncryption }\n : {}),\n },\n signal !== undefined ? { signal } : undefined,\n )\n }\n\n /**\n * Copies a file via the server-side multipart protocol. Each part is copied\n * by reference through `b2_copy_part`; data never traverses the client. Falls\n * back to a single `copyFile` call when the source fits within a single part.\n * @param options - Copy parameters including source file ID, destination name, part size, and concurrency.\n *\n * @returns Metadata for the newly created destination file version.\n */\n async copyLargeFile(options: {\n /** File ID of the source file to copy. */\n sourceFileId: FileId\n /** Destination file name in the target bucket. */\n fileName: string\n /** Target bucket ID. Defaults to this bucket if omitted. */\n destinationBucketId?: BucketId\n /** Override content type for the destination. */\n contentType?: string\n /** Custom file info for the destination. */\n fileInfo?: Record<string, string>\n /** Server-side encryption for the destination file. */\n destinationServerSideEncryption?: EncryptionSetting\n /** SSE-C settings for the source if it was uploaded with SSE-C. */\n sourceServerSideEncryption?: EncryptionSetting\n /**\n * Callback invoked if best-effort cancellation fails, or if cancellation is\n * skipped because `b2_finish_large_file` may already have committed.\n */\n onCleanupFailure?: CleanupFailureListener\n /** Part size in bytes. Defaults to the account's recommended part size. */\n partSize?: number\n /**\n * Maximum number of parts copied in parallel. Defaults to the\n * SDK-wide transfer concurrency.\n */\n concurrency?: number\n /**\n * Optional abort signal. Aborting cancels any remaining parts and\n * triggers a best-effort `cancelLargeFile` on the unfinished upload.\n */\n signal?: AbortSignal\n }): Promise<FileVersion> {\n return copyLargeFile(this.client.raw, this.client.accountInfo, {\n sourceFileId: options.sourceFileId,\n fileName: options.fileName,\n ...(options.destinationBucketId !== undefined\n ? { destinationBucketId: options.destinationBucketId }\n : { destinationBucketId: this.id }),\n ...(options.contentType !== undefined ? { contentType: options.contentType } : {}),\n ...(options.fileInfo !== undefined ? { fileInfo: options.fileInfo } : {}),\n ...(options.destinationServerSideEncryption !== undefined\n ? { destinationServerSideEncryption: options.destinationServerSideEncryption }\n : {}),\n ...(options.sourceServerSideEncryption !== undefined\n ? { sourceServerSideEncryption: options.sourceServerSideEncryption }\n : {}),\n ...(options.partSize !== undefined ? { partSize: options.partSize } : {}),\n ...(options.concurrency !== undefined ? { concurrency: options.concurrency } : {}),\n ...(options.onCleanupFailure !== undefined\n ? { onCleanupFailure: options.onCleanupFailure }\n : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n })\n }\n\n /**\n * Updates bucket settings such as type, CORS, lifecycle rules, and encryption.\n * @param options - Fields to update. Omitted fields are left unchanged.\n *\n * @returns Updated bucket metadata.\n */\n async update(options: {\n /** Change the bucket access level. */\n bucketType?: BucketType\n /**\n * Replace custom bucket metadata. Keys must be 1-50 UTF-8 bytes, must not\n * start with `b2-`, and all values together must be at most 10,000 UTF-8\n * bytes. Keys must match {@link BUCKET_INFO_KEY_PATTERN}. There is no\n * bucketInfo pair-count cap.\n */\n bucketInfo?: Record<string, string>\n /**\n * Replace CORS rules. A bucket may have at most 100 rules; rule names must\n * be unique, 6-63 characters, match `[A-Za-z0-9-]`, and not start with\n * `b2-`. Each rule must be less than 1,000 UTF-8 bytes across its name,\n * origins, operations, allowed headers, and exposed headers.\n * `maxAgeSeconds` must be at most 86,400.\n */\n corsRules?: CorsRule[]\n /** Change default server-side encryption. */\n defaultServerSideEncryption?: BucketDefaultServerSideEncryptionSetting\n /** Change default file retention policy. */\n defaultRetention?: BucketRetentionPolicy\n /** Replace lifecycle rules. */\n lifecycleRules?: LifecycleRule[]\n /** Update replication configuration. */\n replicationConfiguration?: ReplicationConfiguration\n /** Optimistic locking: only update if the bucket revision matches. */\n ifRevisionIs?: number\n }): Promise<BucketInfo> {\n const {\n bucketInfo,\n bucketType,\n corsRules,\n defaultRetention,\n defaultServerSideEncryption,\n ifRevisionIs,\n lifecycleRules,\n replicationConfiguration,\n } = options\n return this.client.raw.updateBucket(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n ...(bucketType !== undefined ? { bucketType } : {}),\n ...(bucketInfo !== undefined ? { bucketInfo } : {}),\n ...(corsRules !== undefined ? { corsRules } : {}),\n ...(defaultServerSideEncryption !== undefined ? { defaultServerSideEncryption } : {}),\n ...(defaultRetention !== undefined ? { defaultRetention } : {}),\n ...(lifecycleRules !== undefined ? { lifecycleRules } : {}),\n ...(replicationConfiguration !== undefined ? { replicationConfiguration } : {}),\n ...(ifRevisionIs !== undefined ? { ifRevisionIs } : {}),\n accountId: accountId(this.client.accountInfo.getAccountId()),\n bucketId: this.id,\n },\n )\n }\n\n /**\n * Permanently deletes this bucket. The bucket must be empty (no file versions).\n *\n * @returns The deleted bucket metadata.\n */\n async delete(): Promise<BucketInfo> {\n return this.client.deleteBucket(this.id)\n }\n\n /**\n * Gets a download authorization token scoped to a file name prefix in this bucket.\n * @param fileNamePrefix - Only authorize downloads of files starting with this prefix.\n * @param validDurationInSeconds - How long the authorization is valid (1-604800 seconds).\n *\n * @returns The download authorization response containing a time-limited token.\n */\n async getDownloadAuthorization(\n fileNamePrefix: string,\n validDurationInSeconds: number,\n ): Promise<DownloadAuthorizationResponse> {\n return this.client.raw.getDownloadAuthorization(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { bucketId: this.id, fileNamePrefix, validDurationInSeconds },\n )\n }\n\n /**\n * Gets the event notification rules configured for this bucket.\n *\n * @returns The current notification rules for this bucket.\n */\n async getNotificationRules(): Promise<GetBucketNotificationRulesResponse> {\n return this.client.raw.getBucketNotificationRules(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { bucketId: this.id },\n )\n }\n\n /**\n * Replaces the event notification rules for this bucket.\n * @param rules - The new set of notification rules to apply.\n *\n * @returns The updated notification rules for this bucket.\n */\n async setNotificationRules(\n rules: readonly EventNotificationRule[],\n ): Promise<GetBucketNotificationRulesResponse> {\n return this.client.raw.setBucketNotificationRules(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { bucketId: this.id, eventNotificationRules: rules },\n )\n }\n\n /**\n * Updates the file retention policy for a specific file version. Requires file lock on the bucket.\n * @param fileName - The file path of the version to update.\n * @param fileId - The unique identifier of the file version.\n * @param retention - The new retention policy to apply.\n * @param options - Optional flags. Set `bypassGovernance: true` to shorten governance-mode retention.\n *\n * @returns The updated file retention metadata.\n */\n async updateFileRetention(\n fileName: string,\n fileId: FileId,\n retention: FileRetentionValue,\n options?: { bypassGovernance?: boolean },\n ) {\n return this.client.raw.updateFileRetention(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n {\n fileName,\n fileId,\n fileRetention: retention,\n ...(options?.bypassGovernance !== undefined\n ? { bypassGovernance: options.bypassGovernance }\n : {}),\n },\n )\n }\n\n /**\n * Updates the legal hold status for a specific file version. Requires file lock on the bucket.\n * @param fileName - The file path of the version to update.\n * @param fileId - The unique identifier of the file version.\n * @param legalHold - The new legal hold status to apply.\n *\n * @returns The updated legal hold metadata.\n */\n async updateFileLegalHold(fileName: string, fileId: FileId, legalHold: LegalHoldValue) {\n return this.client.raw.updateFileLegalHold(\n this.client.accountInfo.getApiUrl(),\n this.client.accountInfo.getAuthToken(),\n { fileName, fileId, legalHold },\n )\n }\n\n /**\n * Refetches this bucket's metadata from B2 so callers operating on\n * replication / lifecycle / retention configuration always start from the\n * server-of-record state.\n *\n * Bucket configuration is monotonically revisioned by B2: B2 increments\n * `revision` on every accepted update. The local {@link info} snapshot\n * captured at construction time goes stale as soon as anyone else (or any\n * prior `update()` call) mutates the bucket, so the ergonomic\n * add/remove helpers below always refresh before composing the next\n * `setX()` call. The result is that each helper is safe to call without\n * the caller having to thread BucketInfo through their code.\n *\n * @returns Fresh {@link BucketInfo} for this bucket.\n *\n * @throws If the bucket no longer exists.\n */\n private async refresh(): Promise<BucketInfo> {\n const fresh = await this.client.listBuckets({ bucketId: this.id })\n const found = fresh[0]\n if (!found) throw new Error(`Bucket ${this.id} not found`)\n return found.info\n }\n\n /**\n * Returns the current cross-region replication configuration, refetched\n * from B2.\n *\n * Use this when you need to read replication state without composing a\n * write. For add/remove flows the helper methods below handle the\n * refresh-then-set sequence for you.\n *\n * @returns The current readable replication wrapper. Its `value` is null\n * when no replication is configured or when the caller is not authorized\n * to read replication settings.\n */\n async getReplication(): Promise<ReadableReplicationConfiguration> {\n const fresh = await this.refresh()\n return fresh.replicationConfiguration\n }\n\n /**\n * Replaces this bucket's complete replication configuration.\n * @param replication - The new configuration. Pass an empty source/destination\n * pair (`{ asReplicationSource: null, asReplicationDestination: null }`)\n * to clear replication entirely.\n *\n * @returns The updated bucket metadata.\n */\n async setReplication(replication: ReplicationConfiguration): Promise<BucketInfo> {\n return this.update({ replicationConfiguration: replication })\n }\n\n /**\n * Adds (or replaces by `replicationRuleName`) a single replication rule\n * on this bucket while leaving any other rules, the source key, and the\n * destination key mapping untouched.\n *\n * When this is the very first source-side rule, `sourceApplicationKeyId`\n * must be supplied to seed `asReplicationSource.sourceApplicationKeyId`;\n * for subsequent calls the existing source key is reused unless the\n * caller explicitly overrides it.\n *\n * @param rule - The replication rule to add or replace.\n * @param options - Optional source application key ID override (or seed\n * when no source side exists yet).\n *\n * @returns The updated bucket metadata.\n *\n * @throws If no source-side replication exists yet and the caller did\n * not supply `sourceApplicationKeyId`.\n * @throws If the caller is not authorized to read current replication settings.\n */\n async addReplicationRule(\n rule: ReplicationRule,\n options?: { sourceApplicationKeyId?: ApplicationKeyId },\n ): Promise<BucketInfo> {\n const current = readableReplicationConfigurationOrEmpty(\n (await this.refresh()).replicationConfiguration,\n 'addReplicationRule',\n )\n const existingSource = current.asReplicationSource\n const sourceKey = options?.sourceApplicationKeyId ?? existingSource?.sourceApplicationKeyId\n if (!sourceKey) {\n throw new Error(\n 'addReplicationRule: no existing source-side replication; pass options.sourceApplicationKeyId',\n )\n }\n const existingRules = existingSource?.replicationRules ?? []\n const without = existingRules.filter((r) => r.replicationRuleName !== rule.replicationRuleName)\n return this.setReplication({\n asReplicationSource: {\n sourceApplicationKeyId: sourceKey,\n replicationRules: [...without, rule],\n },\n asReplicationDestination: current.asReplicationDestination,\n })\n }\n\n /**\n * Removes a single replication rule by name. No-ops cleanly when the rule\n * is not present (returns the unchanged-but-revision-bumped bucket info).\n *\n * @param replicationRuleName - Name of the rule to remove.\n *\n * @returns The updated bucket metadata.\n *\n * @throws If the caller is not authorized to read current replication settings.\n */\n async removeReplicationRule(replicationRuleName: string): Promise<BucketInfo> {\n const current = readableReplicationConfigurationOrEmpty(\n (await this.refresh()).replicationConfiguration,\n 'removeReplicationRule',\n )\n const existingSource = current.asReplicationSource\n if (!existingSource) {\n return this.setReplication(current)\n }\n const filtered = existingSource.replicationRules.filter(\n (r) => r.replicationRuleName !== replicationRuleName,\n )\n return this.setReplication({\n asReplicationSource: {\n sourceApplicationKeyId: existingSource.sourceApplicationKeyId,\n replicationRules: filtered,\n },\n asReplicationDestination: current.asReplicationDestination,\n })\n }\n\n /**\n * Returns the current lifecycle rules for this bucket, refetched from B2.\n *\n * @returns The current array of {@link LifecycleRule}s.\n */\n async getLifecycleRules(): Promise<readonly LifecycleRule[]> {\n const fresh = await this.refresh()\n return fresh.lifecycleRules\n }\n\n /**\n * Replaces this bucket's lifecycle rules in their entirety.\n * @param rules - The new rule set. Pass `[]` to remove all lifecycle\n * automation.\n *\n * @returns The updated bucket metadata.\n */\n async setLifecycleRules(rules: readonly LifecycleRule[]): Promise<BucketInfo> {\n return this.update({ lifecycleRules: [...rules] })\n }\n\n /**\n * Adds (or replaces, matched by `fileNamePrefix`) a single lifecycle rule\n * while leaving any other rules untouched.\n *\n * Matching on prefix mirrors B2's own data model: each unique prefix can\n * have at most one rule, and a `b2_update_bucket` call that contains two\n * rules with the same prefix is rejected. The helper enforces this for\n * the caller.\n *\n * @param rule - The lifecycle rule to add or replace.\n *\n * @returns The updated bucket metadata.\n */\n async addLifecycleRule(rule: LifecycleRule): Promise<BucketInfo> {\n const current = await this.getLifecycleRules()\n const without = current.filter((r) => r.fileNamePrefix !== rule.fileNamePrefix)\n return this.setLifecycleRules([...without, rule])\n }\n\n /**\n * Removes a single lifecycle rule by prefix. No-ops cleanly when the rule\n * is not present.\n *\n * @param fileNamePrefix - The prefix of the rule to remove.\n *\n * @returns The updated bucket metadata.\n */\n async removeLifecycleRule(fileNamePrefix: string): Promise<BucketInfo> {\n const current = await this.getLifecycleRules()\n return this.setLifecycleRules(current.filter((r) => r.fileNamePrefix !== fileNamePrefix))\n }\n\n /**\n * Returns the current default Object Lock retention policy for new\n * uploads to this bucket, refetched from B2.\n *\n * @returns The default {@link BucketDefaultRetention}, or `undefined` if\n * the file lock configuration is not readable. B2 represents no bucket\n * default retention as `{ mode: null, period: null }`.\n */\n async getDefaultRetention(): Promise<BucketDefaultRetention | undefined> {\n const fresh = await this.refresh()\n return bucketDefaultRetentionSnapshot(fresh).retention\n }\n\n /**\n * Sets (or clears, by passing `{ mode: 'none', period: null }`) the\n * default Object Lock retention policy applied to new uploads.\n *\n * Object Lock must already be enabled on the bucket. Buckets created\n * without `fileLockEnabled: true` cannot accept a default retention\n * policy and B2 will reject this call.\n *\n * @param policy - The new default retention policy.\n *\n * @returns The updated bucket metadata.\n */\n async setDefaultRetention(policy: BucketRetentionPolicy): Promise<BucketInfo> {\n return this.update({ defaultRetention: policy })\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AA4DA,IAAM,kCAA4D;CAChE,qBAAqB;CACrB,0BAA0B;AAC5B;AAEA,SAAS,wCACP,UACA,WAC0B;CAC1B,IAAI,CAAC,SAAS,0BACZ,MAAM,IAAI,MACR,GAAG,UAAU,+GACf;CAEF,OAAO,SAAS,SAAS;AAC3B;AA6LA,SAAS,+BAA+B,MAAkD;CACxF,MAAM,WAAW,KAAK;CACtB,IAAI,CAAC,SAAS,0BAA0B,OAAO,EAAE,YAAY,KAAK;CAClE,IAAI,SAAS,UAAU,MAAM,OAAO,EAAE,YAAY,MAAM;CACxD,OAAO;EAAE,WAAW,SAAS,MAAM;EAAkB,YAAY;CAAM;AACzE;AAEA,SAAS,0CACP,MAC2C;CAC3C,MAAM,aAAa,KAAK;CACxB,IAAI,CAAC,WAAW,0BAA0B,OAAO,EAAE,YAAY,KAAK;CACpE,IAAI,WAAW,UAAU,MAAM,OAAO,EAAE,YAAY,MAAM;CAC1D,OAAO;EAAE,YAAY,WAAW;EAAO,YAAY;CAAM;AAC3D;AAEA,SAAS,+BAA+B,SAAuC;CAE7E,QADwB,QAAQ,WAAW,QAAQ,QAAQ,iBAAiB,KAAA,OAGzE,QAAQ,yBAAyB,KAAA,KAAa,QAAQ,kBAAkB,KAAA;AAE7E;AAEA,SAAS,2BAA2B,SAA4C;CAC9E,MAAM,SAAU,QAA0C;CAC1D,IAAI,OAAO,WAAW,UAAU,OAAO;CACvC,MAAM,IAAI,MACR,mEAAmE,KAAK,UACtE,QAAQ,QACV,EAAE,0FACJ;AACF;AAEA,SAAS,oBACP,SACA,WACQ;CACR,IAAI,OAAO,QAAQ,WAAW,UAAU,OAAO,QAAQ;CACvD,MAAM,IAAI,MACR,GAAG,UAAU,6DAA6D,KAAK,UAC7E,QAAQ,QACV,GACF;AACF;AAEA,SAAS,yBACP,SACA,WAC8C;CAC9C,IAAI,QAAQ,WAAW,WAAW,QAAQ;CAC1C,MAAM,IAAI,MACR,GAAG,UAAU,sDAAsD,KAAK,UACtE,QAAQ,QACV,EAAE,uCACJ;AACF;AAEA,SAAS,4BACP,SACA,WAC2B;CAC3B,yBAAyB,SAAS,SAAS;CAC3C,oBAAoB,SAAS,SAAS;CACtC,OAAO;AACT;AAEA,SAAS,wBACP,SACA,WACA,SACmB;CACnB,IAAI,QAAQ,WAAW,WAAW,QAAQ;EACxC,IAAI,QAAQ,aAAa,OAAO;EAChC,MAAM,IAAI,MACR,GAAG,UAAU,sDAAsD,KAAK,UACtE,QAAQ,QACV,EAAE,uCACJ;CACF;CACA,IAAI,QAAQ,WAAW,WAAW,MAChC,MAAM,IAAI,MACR,GAAG,UAAU,6CAA6C,KAAK,UAC7D,QAAQ,QACV,EAAE,wDACJ;CAEF,oBAAoB,SAAS,SAAS;CACtC,OAAO;AACT;AAUA,SAAS,8BACP,UACA,SAC4D;CAC5D,MAAM,QAAQ,SAAS,MAAM,KAAK,YAChC,wBAAwB,SAAS,iBAAiB,OAAO,CAC3D;CACA,OAAO;EAAE,GAAG;EAAU;CAAM;AAC9B;AAUA,SAAS,iCACP,UACA,SACkE;CAClE,IAAI,QAAQ,aAAa;EACvB,MAAM,QAAQ,SAAS,MAAM,KAAK,YAAY;GAC5C,IAAI,QAAQ,WAAW,WAAW,QAAQ,OAAO;GACjD,OAAO,4BAA4B,SAAS,kBAAkB;EAChE,CAAC;EACD,OAAO;GAAE,GAAG;GAAU;EAAM;CAC9B;CACA,MAAM,QAAQ,SAAS,MAAM,KAAK,YAChC,4BAA4B,SAAS,kBAAkB,CACzD;CACA,OAAO;EAAE,GAAG;EAAU;CAAM;AAC9B;;;;;;;;;;;;AAaA,IAAa,SAAb,MAAoB;;CAElB;;CAEA;;CAEA;CACA;CACA;;;;;;;;CASA,YAAY,QAAkB,MAAkB,oBAAkC;EAChF,KAAK,SAAS;EACd,KAAK,OAAO;EACZ,KAAK,KAAK,KAAK;EACf,KAAK,OAAO,KAAK;EACjB,KAAK,qBAAqB;CAC5B;;;;;;;CAQA,KAAK,UAA4B;EAC/B,OAAO,IAAI,SAAS,KAAK,QAAQ,MAAM,UAAU,KAAK,kBAAkB;CAC1E;;;;;;;;CASA,MAAM,OAAO,SAAoD;EAC/D,MAAM,sBAAsB,KAAK,OAAO,YAAY,uBAAuB;EAC3E,MAAM,UAAU,QAAQ,OAAO,OAAO;EACtC,MAAM,qBAAqB,wBAAwB,KAAK,oBAAoB,QAAQ,KAAK;EAEzF,IAAI,SAAS;GACX,MAAM,aAAa,+BAA+B,OAAO,IAAI,MAAM,KAAK,QAAQ,IAAI,KAAK;GACzF,MAAM,yBAAyB,+BAA+B,UAAU;GACxE,MAAM,mBAAmB,0CAA0C,UAAU;GAC7E,OAAO,gBAAgB,KAAK,OAAO,KAAK,KAAK,OAAO,aAAa;IAC/D,GAAG;IACH,UAAU,KAAK;IACf,OAAO;IACP,GAAI,iBAAiB,eAAe,KAAA,IAChC,EAAE,mCAAmC,iBAAiB,WAAW,IACjE,CAAC;IACL,GAAI,iBAAiB,aACjB,EAAE,6CAA6C,KAAK,IACpD,CAAC;IACL,GAAI,uBAAuB,cAAc,KAAA,IACrC,EAAE,wBAAwB,uBAAuB,UAAU,IAC3D,CAAC;IACL,GAAI,uBAAuB,aAAa,EAAE,kCAAkC,KAAK,IAAI,CAAC;GACxF,CAAC;EACH;EACA,wBAAwB,SAAS,eAAe;EAChD,MAAM,eAAe,uBAAuB,OAAO;EACnD,OAAO,gBAAgB,KAAK,OAAO,KAAK,KAAK,OAAO,aAAa;GAC/D,GAAG;GACH,UAAU,KAAK;GACf,OAAO;EACT,CAAC;CACH;;;;;;;;;;CAWA,MAAM,SAAS,UAAkB,SAAwD;EACvF,OAAO,eAAe,KAAK,OAAO,KAAK,KAAK,OAAO,aAAa;GAC9D,YAAY,KAAK;GACjB;GACA,GAAG;EACL,CAAC;CACH;;;;;;;;;;;;;;;;;;;;;;;CAwBA,MAAM,KAAK,UAAkB,SAAgD;EAC3E,OAAO,WAAW,KAAK,OAAO,KAAK,KAAK,OAAO,aAAa;GAC1D,YAAY,KAAK;GACjB;GACA,GAAG;EACL,CAAC;CACH;CAkBA,MAAM,cACJ,SAIqE;EACrE,MAAM,WAAW,MAAM,KAAK,OAAO,IAAI,cACrC,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GACE,UAAU,KAAK;GACf,GAAI,SAAS,kBAAkB,KAAA,IAAY,EAAE,eAAe,QAAQ,cAAc,IAAI,CAAC;GACvF,GAAI,SAAS,aAAa,KAAA,IAAY,EAAE,cAAc,QAAQ,SAAS,IAAI,CAAC;GAC5E,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;GAClE,GAAI,SAAS,cAAc,KAAA,IAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;EAC7E,GACA,EACE,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC,EACpE,CACF;EACA,OAAO,SAAS,cAAc,KAAA,IAC1B,8BAA8B,UAAU,EAAE,aAAa,KAAK,CAAC,IAC7D,8BAA8B,UAAU,EAAE,aAAa,MAAM,CAAC;CACpE;CAkBA,MAAM,iBACJ,SAI2E;EAC3E,MAAM,WAAW,MAAM,KAAK,OAAO,IAAI,iBACrC,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GACE,UAAU,KAAK;GACf,GAAI,SAAS,kBAAkB,KAAA,IAAY,EAAE,eAAe,QAAQ,cAAc,IAAI,CAAC;GACvF,GAAI,SAAS,gBAAgB,KAAA,IAAY,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;GACjF,GAAI,SAAS,aAAa,KAAA,IAAY,EAAE,cAAc,QAAQ,SAAS,IAAI,CAAC;GAC5E,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;GAClE,GAAI,SAAS,cAAc,KAAA,IAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;EAC7E,GACA,EACE,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC,EACpE,CACF;EACA,OAAO,SAAS,cAAc,KAAA,IAC1B,iCAAiC,UAAU,EAAE,aAAa,KAAK,CAAC,IAChE,iCAAiC,UAAU,EAAE,aAAa,MAAM,CAAC;CACvE;CAiCA,kBACE,SAI8D;EAC9D,OAAO,cACL,OAAO,WAA+B;GACpC,MAAM,UAAU;IACd,UAAU,SAAS,YAAA;IACnB,GAAI,WAAW,KAAA,IAAY,EAAE,eAAe,OAAO,IAAI,CAAC;IACxD,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;IAClE,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;GACpE;GACA,MAAM,OACJ,SAAS,cAAc,KAAA,IACnB,MAAM,KAAK,cAAc;IAAE,GAAG;IAAS,WAAW,QAAQ;GAAU,CAAC,IACrE,MAAM,KAAK,cAAc,OAAO;GACtC,OAAO;IAAE,MAAM;IAAM,YAAY,KAAK,gBAAgB,KAAA;GAAU;EAClE,IACC,SAAS,KAAK,OACf,SAAS,MACX;CACF;CAyBA,qBACE,SAIyE;EAEzE,OAAO,cACL,OAAO,WAA+B;GACpC,MAAM,UAAU;IACd,UAAU,SAAS,YAAA;IACnB,GAAI,WAAW,KAAA,IAAY,EAAE,eAAe,OAAO,SAAS,IAAI,CAAC;IACjE,GAAI,QAAQ,WAAW,KAAA,IAAY,EAAE,aAAa,OAAO,OAAO,IAAI,CAAC;IACrE,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;IAClE,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;GACpE;GACA,MAAM,OACJ,SAAS,cAAc,KAAA,IACnB,MAAM,KAAK,iBAAiB;IAAE,GAAG;IAAS,WAAW,QAAQ;GAAU,CAAC,IACxE,MAAM,KAAK,iBAAiB,OAAO;GAKzC,OAAO;IAAE,MAAM;IAAM,YAHnB,KAAK,iBAAiB,OAClB;KAAE,UAAU,KAAK;KAAc,QAAQ,KAAK,cAAc,KAAA;IAAU,IACpE,KAAA;GAC0B;EAClC,IACC,SAAS,KAAK,OACf,SAAS,MACX;CACF;;;;;;;;;;;;;;CAeA,6BACE,SAI4C;EAC5C,OAAO,cACL,OAAO,WAAoC;GACzC,MAAM,OAAO,MAAM,KAAK,yBAAyB;IAC/C,UAAU,SAAS,YAAY;IAC/B,GAAI,WAAW,KAAA,IAAY,EAAE,aAAa,OAAO,IAAI,CAAC;IACtD,GAAI,SAAS,eAAe,KAAA,IAAY,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;IAC9E,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;GACpE,CAAC;GACD,OAAO;IAAE,MAAM;IAAM,YAAY,KAAK,cAAc,KAAA;GAAU;EAChE,IACC,SAAS,KAAK,OACf,SAAS,MACX;CACF;;;;;;;;;;;CAYA,cACE,aACA,SACiC;EACjC,OAAO,cACL,OAAO,WAA+B;GACpC,MAAM,OAAO,MAAM,KAAK,OAAO,IAAI,UACjC,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;IACE,QAAQ;IACR,cAAc,SAAS,YAAA;IACvB,GAAI,WAAW,KAAA,IAAY,EAAE,iBAAiB,OAAO,IAAI,CAAC;GAC5D,GACA,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,KAAA,CAC/D;GACA,OAAO;IAAE,MAAM;IAAM,YAAY,KAAK,kBAAkB,KAAA;GAAU;EACpE,IACC,SAAS,KAAK,OACf,SAAS,MACX;CACF;;;;;;;;;CAUA,MAAM,kBAAkB,UAA+C;EAErE,MAAM,SAAQ,MADK,KAAK,cAAc;GAAE,QAAQ;GAAU,UAAU;EAAE,CAAC,EAAA,CACpD,MAAM,MAAM,MAAM,EAAE,aAAa,QAAQ;EAC5D,IAAI,CAAC,OAAO,OAAO;EACnB,OAAO;CACT;;;;;;;;;CAUA,MAAM,WAAW,UAAyD;EAIxE,MAAM,YAAW,MADE,KAAK,iBAAiB;GAAE,QAAQ;GAAU,UAAU;EAAI,CAAC,EAAA,CACtD,MAAM,QAAQ,MAAM,EAAE,aAAa,QAAQ;EACjE,IAAI,SAAS,WAAW,GAAG,OAAO;EAGlC,MAAM,SAAS,SAAS;EACxB,IAAI,QAAQ,WAAW,WAAW,MAAM,OAAO;EAC/C,MAAM,eAAgB,OAAyC;EAC/D,IAAI,OAAO,iBAAiB,UAC1B,MAAM,IAAI,MACR,4EAA4E,KAAK,UAC/E,QACF,GACF;EAEF,MAAM,KAAK,kBAAkB,UAAU,YAAsB;EAC7D,OAAO;CACT;;;;;;;;CASA,MAAM,SAAS,UAAkB,SAA0D;EACzF,OAAO,KAAK,OAAO,IAAI,SACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GAAE,UAAU,KAAK;GAAI;EAAS,GAC9B,OACF;CACF;;;;;;;;;;;;;;CAeA,MAAM,kBACJ,UACA,QACA,SACe;EACf,MAAM,KAAK,OAAO,IAAI,kBACpB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GACE;GACA;GACA,GAAI,SAAS,qBAAqB,KAAA,IAC9B,EAAE,kBAAkB,QAAQ,iBAAiB,IAC7C,CAAC;EACP,GACA,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,KAAA,CAC/D;CACF;;;;;;;;;CAUA,MAAM,gBAAgB,QAAuD;EAC3E,OAAO,KAAK,OAAO,IAAI,gBACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC,EAAE,OAAO,CACX;CACF;;;;;;;;CASA,MAAM,yBAAyB,SAY5B;EACD,OAAO,KAAK,OAAO,IAAI,yBACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GACE,UAAU,KAAK;GACf,GAAI,SAAS,eAAe,KAAA,IAAY,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;GAC9E,GAAI,SAAS,gBAAgB,KAAA,IAAY,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;GACjF,GAAI,SAAS,aAAa,KAAA,IAAY,EAAE,cAAc,QAAQ,SAAS,IAAI,CAAC;EAC9E,GACA,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,KAAA,CAC/D;CACF;;;;;;;;;;;;;;;;;;CAmBA,MAAM,WACJ,SACA,SAC2B;EAC3B,MAAM,cAAc,SAAS,eAAA;EAC7B,MAAM,MAAM,IAAI,UAAU,WAAW;EACrC,MAAM,SAAS,SAAS;EACxB,IAAI,UAAU;EACd,MAAM,SAAwB,CAAC;EAE/B,MAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,WAAW;GAC5B,MAAM,IAAI,QAAQ;GAClB,IAAI;IAMF,IAAI,QAAQ,SAAS;KACnB,OAAO,KAAK;MACV;MACA,OAAO,QAAQ,OAAO,UAAU,SAAS;KAC3C,CAAC;KACD;IACF;IACA,MAAM,KAAK,kBAAkB,OAAO,UAAU,OAAO,MAAM;IAC3D;GACF,SAAS,KAAK;IACZ,OAAO,KAAK;KACV;KACA,OAAO,QAAQ,GAAG;IACpB,CAAC;GACH,UAAU;IACR,IAAI,QAAQ;GACd;EACF,CAAC,CACH;EAEA,OAAO;GAAE;GAAS;EAAO;CAC3B;;;;;;;;;;CAWA,OAAO,UAAU,SAOkB;EACjC,MAAM,SAAS,SAAS,UAAU;EAClC,MAAM,WAAW,SAAS,YAAA;EAE1B,IAAI;EACJ,IAAI;EACJ,OAAO,MAAM;GACX,MAAM,OAAO,MAAM,KAAK,iBAAiB;IACvC;IACA,GAAI,SAAS,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;IAClE,GAAI,kBAAkB,KAAA,IAAY,EAAE,cAAc,IAAI,CAAC;IACvD,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;GACrD,CAAC;GAED,KAAK,MAAM,WAAW,KAAK,OAAO;IAChC,MAAM,SAAS,2BAA2B,OAAO;IACjD,IAAI,QAAQ;KACV,MAAM;MAAE,MAAM;MAAQ,UAAU,QAAQ;MAAU;KAAO;KACzD;IACF;IACA,IAAI;KACF,MAAM,KAAK,kBAAkB,QAAQ,UAAU,MAAM;KACrD,MAAM;MAAE,MAAM;MAAU,UAAU,QAAQ;MAAU;KAAO;IAC7D,SAAS,KAAK;KACZ,MAAM;MACJ,MAAM;MACN,UAAU,QAAQ;MAClB;MACA,SAAS,QAAQ,GAAG,CAAC,CAAC;KACxB;IACF;GACF;GAEA,IAAI,CAAC,KAAK,cAAc;GACxB,gBAAgB,KAAK;GACrB,cAAc,KAAK,cAAc,KAAA;EACnC;CACF;;;;;;;CAQA,MAAM,SAAS,SAwBU;EACvB,MAAM,EAAE,sBAAsB,iCAAiC,QAAQ,GAAG,gBACxE;EACF,MAAM,wBAAwB,mCAAmC;EACjE,OAAO,KAAK,OAAO,IAAI,SACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GACE,GAAG;GACH,GAAI,0BAA0B,KAAA,IAC1B,EAAE,iCAAiC,sBAAsB,IACzD,CAAC;EACP,GACA,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,KAAA,CACtC;CACF;;;;;;;;;CAUA,MAAM,cAAc,SAgCK;EACvB,OAAO,cAAc,KAAK,OAAO,KAAK,KAAK,OAAO,aAAa;GAC7D,cAAc,QAAQ;GACtB,UAAU,QAAQ;GAClB,GAAI,QAAQ,wBAAwB,KAAA,IAChC,EAAE,qBAAqB,QAAQ,oBAAoB,IACnD,EAAE,qBAAqB,KAAK,GAAG;GACnC,GAAI,QAAQ,gBAAgB,KAAA,IAAY,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;GAChF,GAAI,QAAQ,aAAa,KAAA,IAAY,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;GACvE,GAAI,QAAQ,oCAAoC,KAAA,IAC5C,EAAE,iCAAiC,QAAQ,gCAAgC,IAC3E,CAAC;GACL,GAAI,QAAQ,+BAA+B,KAAA,IACvC,EAAE,4BAA4B,QAAQ,2BAA2B,IACjE,CAAC;GACL,GAAI,QAAQ,aAAa,KAAA,IAAY,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;GACvE,GAAI,QAAQ,gBAAgB,KAAA,IAAY,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;GAChF,GAAI,QAAQ,qBAAqB,KAAA,IAC7B,EAAE,kBAAkB,QAAQ,iBAAiB,IAC7C,CAAC;GACL,GAAI,QAAQ,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;EACnE,CAAC;CACH;;;;;;;CAQA,MAAM,OAAO,SA4BW;EACtB,MAAM,EACJ,YACA,YACA,WACA,kBACA,6BACA,cACA,gBACA,6BACE;EACJ,OAAO,KAAK,OAAO,IAAI,aACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GACE,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;GACjD,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;GACjD,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;GAC/C,GAAI,gCAAgC,KAAA,IAAY,EAAE,4BAA4B,IAAI,CAAC;GACnF,GAAI,qBAAqB,KAAA,IAAY,EAAE,iBAAiB,IAAI,CAAC;GAC7D,GAAI,mBAAmB,KAAA,IAAY,EAAE,eAAe,IAAI,CAAC;GACzD,GAAI,6BAA6B,KAAA,IAAY,EAAE,yBAAyB,IAAI,CAAC;GAC7E,GAAI,iBAAiB,KAAA,IAAY,EAAE,aAAa,IAAI,CAAC;GACrD,WAAW,UAAU,KAAK,OAAO,YAAY,aAAa,CAAC;GAC3D,UAAU,KAAK;EACjB,CACF;CACF;;;;;;CAOA,MAAM,SAA8B;EAClC,OAAO,KAAK,OAAO,aAAa,KAAK,EAAE;CACzC;;;;;;;;CASA,MAAM,yBACJ,gBACA,wBACwC;EACxC,OAAO,KAAK,OAAO,IAAI,yBACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GAAE,UAAU,KAAK;GAAI;GAAgB;EAAuB,CAC9D;CACF;;;;;;CAOA,MAAM,uBAAoE;EACxE,OAAO,KAAK,OAAO,IAAI,2BACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC,EAAE,UAAU,KAAK,GAAG,CACtB;CACF;;;;;;;CAQA,MAAM,qBACJ,OAC6C;EAC7C,OAAO,KAAK,OAAO,IAAI,2BACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GAAE,UAAU,KAAK;GAAI,wBAAwB;EAAM,CACrD;CACF;;;;;;;;;;CAWA,MAAM,oBACJ,UACA,QACA,WACA,SACA;EACA,OAAO,KAAK,OAAO,IAAI,oBACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GACE;GACA;GACA,eAAe;GACf,GAAI,SAAS,qBAAqB,KAAA,IAC9B,EAAE,kBAAkB,QAAQ,iBAAiB,IAC7C,CAAC;EACP,CACF;CACF;;;;;;;;;CAUA,MAAM,oBAAoB,UAAkB,QAAgB,WAA2B;EACrF,OAAO,KAAK,OAAO,IAAI,oBACrB,KAAK,OAAO,YAAY,UAAU,GAClC,KAAK,OAAO,YAAY,aAAa,GACrC;GAAE;GAAU;GAAQ;EAAU,CAChC;CACF;;;;;;;;;;;;;;;;;;CAmBA,MAAc,UAA+B;EAE3C,MAAM,SAAQ,MADM,KAAK,OAAO,YAAY,EAAE,UAAU,KAAK,GAAG,CAAC,EAAA,CAC7C;EACpB,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,UAAU,KAAK,GAAG,WAAW;EACzD,OAAO,MAAM;CACf;;;;;;;;;;;;;CAcA,MAAM,iBAA4D;EAEhE,QAAO,MADa,KAAK,QAAQ,EAAA,CACpB;CACf;;;;;;;;;CAUA,MAAM,eAAe,aAA4D;EAC/E,OAAO,KAAK,OAAO,EAAE,0BAA0B,YAAY,CAAC;CAC9D;;;;;;;;;;;;;;;;;;;;;CAsBA,MAAM,mBACJ,MACA,SACqB;EACrB,MAAM,UAAU,yCACb,MAAM,KAAK,QAAQ,EAAA,CAAG,0BACvB,oBACF;EACA,MAAM,iBAAiB,QAAQ;EAC/B,MAAM,YAAY,SAAS,0BAA0B,gBAAgB;EACrE,IAAI,CAAC,WACH,MAAM,IAAI,MACR,8FACF;EAGF,MAAM,WADgB,gBAAgB,oBAAoB,CAAC,EAAA,CAC7B,QAAQ,MAAM,EAAE,wBAAwB,KAAK,mBAAmB;EAC9F,OAAO,KAAK,eAAe;GACzB,qBAAqB;IACnB,wBAAwB;IACxB,kBAAkB,CAAC,GAAG,SAAS,IAAI;GACrC;GACA,0BAA0B,QAAQ;EACpC,CAAC;CACH;;;;;;;;;;;CAYA,MAAM,sBAAsB,qBAAkD;EAC5E,MAAM,UAAU,yCACb,MAAM,KAAK,QAAQ,EAAA,CAAG,0BACvB,uBACF;EACA,MAAM,iBAAiB,QAAQ;EAC/B,IAAI,CAAC,gBACH,OAAO,KAAK,eAAe,OAAO;EAEpC,MAAM,WAAW,eAAe,iBAAiB,QAC9C,MAAM,EAAE,wBAAwB,mBACnC;EACA,OAAO,KAAK,eAAe;GACzB,qBAAqB;IACnB,wBAAwB,eAAe;IACvC,kBAAkB;GACpB;GACA,0BAA0B,QAAQ;EACpC,CAAC;CACH;;;;;;CAOA,MAAM,oBAAuD;EAE3D,QAAO,MADa,KAAK,QAAQ,EAAA,CACpB;CACf;;;;;;;;CASA,MAAM,kBAAkB,OAAsD;EAC5E,OAAO,KAAK,OAAO,EAAE,gBAAgB,CAAC,GAAG,KAAK,EAAE,CAAC;CACnD;;;;;;;;;;;;;;CAeA,MAAM,iBAAiB,MAA0C;EAE/D,MAAM,WAAU,MADM,KAAK,kBAAkB,EAAA,CACrB,QAAQ,MAAM,EAAE,mBAAmB,KAAK,cAAc;EAC9E,OAAO,KAAK,kBAAkB,CAAC,GAAG,SAAS,IAAI,CAAC;CAClD;;;;;;;;;CAUA,MAAM,oBAAoB,gBAA6C;EACrE,MAAM,UAAU,MAAM,KAAK,kBAAkB;EAC7C,OAAO,KAAK,kBAAkB,QAAQ,QAAQ,MAAM,EAAE,mBAAmB,cAAc,CAAC;CAC1F;;;;;;;;;CAUA,MAAM,sBAAmE;EAEvE,OAAO,+BAA+B,MADlB,KAAK,QAAQ,CACU,CAAC,CAAC;CAC/C;;;;;;;;;;;;;CAcA,MAAM,oBAAoB,QAAoD;EAC5E,OAAO,KAAK,OAAO,EAAE,kBAAkB,OAAO,CAAC;CACjD;AACF"}
package/dist/client.cjs CHANGED
@@ -1,10 +1,12 @@
1
1
  const require_in_memory = require("./auth/in-memory.cjs");
2
2
  const require_ids = require("./types/ids.cjs");
3
+ const require_abort = require("./util/abort.cjs");
3
4
  require("./util/defaults.cjs");
4
5
  const require_retry = require("./http/retry.cjs");
5
6
  const require_paginator = require("./util/paginator.cjs");
6
7
  const require_bucket = require("./bucket.cjs");
7
8
  const require_realms = require("./auth/realms.cjs");
9
+ const require_reauth_coalescer = require("./auth/reauth-coalescer.cjs");
8
10
  const require_url_guard = require("./http/url-guard.cjs");
9
11
  const require_transport = require("./http/transport.cjs");
10
12
  const require_raw_index = require("./raw/index.cjs");
@@ -38,6 +40,7 @@ var B2Client = class {
38
40
  realmUrl;
39
41
  userAllowedSuffixes;
40
42
  resolvedUploadRetryOptions;
43
+ reauthCoalescer;
41
44
  /**
42
45
  * Creates a new B2Client. Call {@link authorize} before making API requests.
43
46
  * @param options - Configuration including credentials, realm, and transport settings.
@@ -53,6 +56,7 @@ var B2Client = class {
53
56
  ...require_retry.DEFAULT_RETRY_OPTIONS,
54
57
  ...options.retry
55
58
  };
59
+ this.reauthCoalescer = new require_reauth_coalescer.ReauthCoalescer((signal) => this.doReauthorize(signal));
56
60
  let baseTransport;
57
61
  if (options.transport !== void 0) {
58
62
  baseTransport = options.transport;
@@ -69,7 +73,7 @@ var B2Client = class {
69
73
  const retryTransport = new require_transport.RetryTransport({
70
74
  transport: baseTransport,
71
75
  retry: this.resolvedUploadRetryOptions,
72
- onReauth: () => this.reauthorize()
76
+ onReauth: (signal) => this.reauthorize(signal)
73
77
  });
74
78
  const cachedAuth = this.accountInfo.getAuth();
75
79
  if (cachedAuth !== null) this.lockUrlGuard(cachedAuth);
@@ -78,10 +82,14 @@ var B2Client = class {
78
82
  /**
79
83
  * Authenticates with B2 and stores the authorization state. Must be called before other methods.
80
84
  *
85
+ * @param options - Optional request controls.
86
+ *
81
87
  * @returns The authorization response containing tokens, URLs, and capabilities.
82
88
  */
83
- async authorize() {
84
- const auth = await this.raw.authorizeAccount(this.applicationKeyId, this.applicationKey, this.realmUrl);
89
+ async authorize(options) {
90
+ require_abort.throwIfSignalAborted(options?.signal);
91
+ const auth = await this.raw.authorizeAccount(this.applicationKeyId, this.applicationKey, this.realmUrl, options?.signal !== void 0 ? { signal: options.signal } : void 0);
92
+ require_abort.throwIfSignalAborted(options?.signal);
85
93
  this.accountInfo.setAuth(auth);
86
94
  this.lockUrlGuard(auth);
87
95
  return auth;
@@ -98,11 +106,15 @@ var B2Client = class {
98
106
  * {@link RetryTransport} can rewrite the in-flight request's
99
107
  * Authorization header before retrying.
100
108
  *
109
+ * @param signal - Optional abort signal for the request that triggered reauthorization.
110
+ *
101
111
  * @returns The fresh authorization token.
102
112
  */
103
- async reauthorize() {
104
- this.accountInfo.clear();
105
- return (await this.authorize()).authorizationToken;
113
+ reauthorize(signal) {
114
+ return this.reauthCoalescer.run(signal);
115
+ }
116
+ async doReauthorize(signal) {
117
+ return (await this.authorize({ signal })).authorizationToken;
106
118
  }
107
119
  /**
108
120
  * Creates a new B2 bucket.
@@ -111,9 +123,18 @@ var B2Client = class {
111
123
  * @returns A {@link Bucket} handle for the newly created bucket.
112
124
  */
113
125
  async createBucket(options) {
126
+ const { bucketInfo, bucketName, bucketType, corsRules, defaultRetention, defaultServerSideEncryption, fileLockEnabled, lifecycleRules, replicationConfiguration } = options;
114
127
  const request = {
115
- accountId: require_ids.accountId(this.accountInfo.getAccountId()),
116
- ...options
128
+ ...bucketInfo !== void 0 ? { bucketInfo } : {},
129
+ bucketName,
130
+ bucketType,
131
+ ...corsRules !== void 0 ? { corsRules } : {},
132
+ ...defaultServerSideEncryption !== void 0 ? { defaultServerSideEncryption } : {},
133
+ ...defaultRetention !== void 0 ? { defaultRetention } : {},
134
+ ...fileLockEnabled !== void 0 ? { fileLockEnabled } : {},
135
+ ...lifecycleRules !== void 0 ? { lifecycleRules } : {},
136
+ ...replicationConfiguration !== void 0 ? { replicationConfiguration } : {},
137
+ accountId: require_ids.accountId(this.accountInfo.getAccountId())
117
138
  };
118
139
  const info = await this.raw.createBucket(this.accountInfo.getApiUrl(), this.accountInfo.getAuthToken(), request);
119
140
  return new require_bucket.Bucket(this, info, this.resolvedUploadRetryOptions);
@@ -1 +1 @@
1
- {"version":3,"file":"client.cjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import type { AccountInfo } from './auth/account-info.ts'\nimport { InMemoryAccountInfo } from './auth/in-memory.ts'\nimport { getRealmUrl } from './auth/realms.ts'\nimport { Bucket } from './bucket.ts'\nimport { DEFAULT_RETRY_OPTIONS, type RetryOptions } from './http/retry.ts'\nimport type { HttpTransport } from './http/transport.ts'\nimport { FetchTransport, RetryTransport } from './http/transport.ts'\nimport { deriveAllowedSuffixes, UrlGuard } from './http/url-guard.ts'\nimport { RawClient } from './raw/index.ts'\nimport type { AuthorizeAccountResponse, Capability } from './types/auth.ts'\nimport type {\n BucketInfo,\n BucketRetentionPolicy,\n BucketType,\n CorsRule,\n CreateBucketRequest,\n LifecycleRule,\n} from './types/bucket.ts'\nimport type { EncryptionSetting } from './types/encryption.ts'\nimport type { ApplicationKeyId, BucketId } from './types/ids.ts'\nimport { accountId } from './types/ids.ts'\nimport type {\n ApplicationKey,\n CreateKeyOptions,\n FullApplicationKey,\n ListKeysResponse,\n} from './types/key.ts'\nimport type { ReplicationConfiguration } from './types/replication.ts'\nimport { DEFAULT_PAGE_SIZE } from './util/defaults.ts'\nimport { type PaginatorOptions, paginateItems } from './util/paginator.ts'\n\n/** Result of {@link B2Client.hasCapabilities}. */\nexport interface CapabilityCheckResult {\n /** `true` when the key carries every requested capability. */\n readonly ok: boolean\n /** Capabilities the call requested that the current key does not hold. Empty when `ok` is `true`. */\n readonly missing: readonly Capability[]\n}\n\n/** Configuration options for creating a {@link B2Client}. */\nexport interface B2ClientOptions {\n /** The application key ID from the B2 dashboard or `b2_create_key`. */\n readonly applicationKeyId: string\n /** The application key secret. */\n readonly applicationKey: string\n /**\n * B2 realm to authenticate against. Accepts a known realm-map key\n * (`\"production\"` or `\"staging\"`) or a direct base URL. Custom HTTPS hosts\n * are trusted with the application key during authorize, so never derive\n * `realm` from untrusted input. URL values must use HTTPS, or loopback IP\n * literal HTTP for local testing only; application-key credentials are sent\n * unencrypted over loopback HTTP. Unsupported schemes, malformed URLs,\n * non-URL strings, plaintext HTTP hostnames such as `localhost`, and\n * non-loopback plaintext HTTP are rejected before credentials are sent. URL\n * values must not include userinfo, query strings, or fragments. Defaults to\n * `\"production\"`.\n */\n readonly realm?: string\n /** Storage backend for authorization state. Defaults to {@link InMemoryAccountInfo}. */\n readonly accountInfo?: AccountInfo\n /** Custom HTTP transport. Defaults to {@link FetchTransport}. Wrapped by {@link RetryTransport}. */\n readonly transport?: HttpTransport\n /** Override retry behavior (max retries, backoff, and per-attempt timeout). */\n readonly retry?: Partial<RetryOptions>\n /** Custom user-agent string prepended to the SDK default. */\n readonly userAgent?: string\n /**\n * Override the SSRF allow-list. By default the SDK locks the\n * {@link FetchTransport} to host suffixes derived from the realm's authorize\n * response (e.g. `backblazeb2.com`, `backblaze.com`) so a compromised B2\n * endpoint cannot redirect the SDK to internal services. Pass an explicit\n * list to add hosts (e.g. when testing against a self-hosted proxy) or set\n * to an empty array to disable the guard entirely (not recommended).\n *\n * Only consulted when {@link B2ClientOptions.transport} is unset; a custom\n * transport is the user's responsibility to harden.\n */\n readonly allowedHostSuffixes?: readonly string[]\n /**\n * Follow same-origin GET/HEAD redirects in the default fetch transport after\n * checking each target with the SSRF guard. POST redirects remain blocked.\n * Defaults to true.\n */\n readonly followSameOriginRedirects?: boolean\n}\n\n/**\n * High-level B2 client providing ergonomic access to buckets, files, and keys.\n *\n * @example\n * ```ts\n * const client = new B2Client({\n * applicationKeyId: process.env.B2_APPLICATION_KEY_ID,\n * applicationKey: process.env.B2_APPLICATION_KEY,\n * })\n * await client.authorize()\n * const buckets = await client.listBuckets()\n * ```\n */\nexport class B2Client {\n /** Low-level client for direct B2 API calls. */\n readonly raw: RawClient\n /** Authorization state storage (tokens, URLs, capabilities). */\n readonly accountInfo: AccountInfo\n /**\n * SSRF allow-list applied by the default {@link FetchTransport}. `null` when\n * a custom transport was supplied — in that case the SDK does not own the\n * guard. Locked down by {@link B2Client.authorize}.\n */\n readonly urlGuard: UrlGuard | null\n private readonly applicationKeyId: string\n private readonly applicationKey: string\n private readonly realmUrl: string\n private readonly userAllowedSuffixes: readonly string[] | undefined\n private readonly resolvedUploadRetryOptions: RetryOptions\n\n /**\n * Creates a new B2Client. Call {@link authorize} before making API requests.\n * @param options - Configuration including credentials, realm, and transport settings.\n */\n constructor(options: B2ClientOptions) {\n this.applicationKeyId = options.applicationKeyId\n this.applicationKey = options.applicationKey\n this.realmUrl = getRealmUrl(options.realm ?? 'production')\n this.accountInfo = options.accountInfo ?? new InMemoryAccountInfo()\n bindAccountInfoAuthContext(this.accountInfo, this.realmUrl, this.applicationKeyId)\n this.userAllowedSuffixes = options.allowedHostSuffixes\n this.resolvedUploadRetryOptions = { ...DEFAULT_RETRY_OPTIONS, ...options.retry }\n\n let baseTransport: HttpTransport\n if (options.transport !== undefined) {\n baseTransport = options.transport\n this.urlGuard = null\n } else {\n const urlGuard = new UrlGuard()\n baseTransport = new FetchTransport({\n urlGuard,\n ...(options.userAgent !== undefined ? { userAgent: options.userAgent } : {}),\n ...(options.followSameOriginRedirects !== undefined\n ? { followSameOriginRedirects: options.followSameOriginRedirects }\n : {}),\n })\n this.urlGuard = urlGuard\n }\n\n const retryTransport = new RetryTransport({\n transport: baseTransport,\n retry: this.resolvedUploadRetryOptions,\n onReauth: () => this.reauthorize(),\n })\n\n const cachedAuth = this.accountInfo.getAuth()\n if (cachedAuth !== null) this.lockUrlGuard(cachedAuth)\n\n this.raw = new RawClient({ transport: retryTransport })\n }\n\n /**\n * Authenticates with B2 and stores the authorization state. Must be called before other methods.\n *\n * @returns The authorization response containing tokens, URLs, and capabilities.\n */\n async authorize(): Promise<AuthorizeAccountResponse> {\n const auth = await this.raw.authorizeAccount(\n this.applicationKeyId,\n this.applicationKey,\n this.realmUrl,\n )\n this.accountInfo.setAuth(auth)\n this.lockUrlGuard(auth)\n return auth\n }\n\n private lockUrlGuard(auth: AuthorizeAccountResponse): void {\n if (this.urlGuard !== null) {\n const derived = deriveAllowedSuffixes(auth.apiInfo.storageApi)\n const merged =\n this.userAllowedSuffixes !== undefined\n ? this.userAllowedSuffixes.length === 0\n ? []\n : Array.from(new Set([...derived, ...this.userAllowedSuffixes]))\n : derived\n this.urlGuard.setAllowedSuffixes(merged)\n }\n }\n\n /**\n * Refresh credentials after a 401. Returns the fresh auth token so\n * {@link RetryTransport} can rewrite the in-flight request's\n * Authorization header before retrying.\n *\n * @returns The fresh authorization token.\n */\n private async reauthorize(): Promise<string> {\n this.accountInfo.clear()\n const auth = await this.authorize()\n return auth.authorizationToken\n }\n\n /**\n * Creates a new B2 bucket.\n * @param options - Bucket configuration including name, type, and optional settings.\n *\n * @returns A {@link Bucket} handle for the newly created bucket.\n */\n async createBucket(options: {\n /** Globally unique bucket name (6-63 chars; letters, digits, hyphens, periods). */\n bucketName: string\n /** Access level: `\"allPrivate\"` or `\"allPublic\"`. */\n bucketType: BucketType\n /** Custom key-value metadata stored with the bucket. */\n bucketInfo?: Record<string, string>\n /** CORS rules for browser-based access. */\n corsRules?: CorsRule[]\n /** Default server-side encryption for new files. */\n defaultServerSideEncryption?: EncryptionSetting\n /** Default retention policy for new files (requires file lock). */\n defaultRetention?: BucketRetentionPolicy\n /** Enable file lock (Object Lock) on the bucket. Cannot be disabled once set. */\n fileLockEnabled?: boolean\n /** Lifecycle rules for automatic file deletion or hiding. */\n lifecycleRules?: LifecycleRule[]\n /** Cross-region replication configuration. */\n replicationConfiguration?: ReplicationConfiguration\n }): Promise<Bucket> {\n const request: CreateBucketRequest = {\n accountId: accountId(this.accountInfo.getAccountId()),\n ...options,\n }\n const info = await this.raw.createBucket(\n this.accountInfo.getApiUrl(),\n this.accountInfo.getAuthToken(),\n request,\n )\n return new Bucket(this, info, this.resolvedUploadRetryOptions)\n }\n\n /**\n * Lists buckets in the account, optionally filtered by ID, name, or type.\n * @param options - Optional filters for bucket ID, name, or type.\n *\n * @returns An array of {@link Bucket} handles.\n */\n async listBuckets(options?: {\n /** Filter to a specific bucket by ID. */\n bucketId?: BucketId\n /** Filter to a specific bucket by name. */\n bucketName?: string\n /** Filter by bucket types (e.g., `[\"allPrivate\"]`). */\n bucketTypes?: BucketType[]\n }): Promise<Bucket[]> {\n const resp = await this.raw.listBuckets(\n this.accountInfo.getApiUrl(),\n this.accountInfo.getAuthToken(),\n {\n accountId: accountId(this.accountInfo.getAccountId()),\n ...options,\n },\n )\n return resp.buckets.map((info) => new Bucket(this, info, this.resolvedUploadRetryOptions))\n }\n\n /**\n * Looks up a single bucket by name.\n * @param bucketName - The name of the bucket to find.\n *\n * @returns The {@link Bucket} handle, or `null` if not found.\n */\n async getBucket(bucketName: string): Promise<Bucket | null> {\n const buckets = await this.listBuckets({ bucketName })\n const filteredMatch = buckets[0]\n if (filteredMatch !== undefined) return filteredMatch\n\n const unfilteredBuckets = await this.listBuckets()\n return unfilteredBuckets.find((bucket) => bucket.name === bucketName) ?? null\n }\n\n /**\n * Permanently deletes a bucket. The bucket must be empty.\n * @param id - The unique identifier of the bucket to delete.\n *\n * @returns The deleted bucket metadata.\n */\n async deleteBucket(id: BucketId): Promise<BucketInfo> {\n return this.raw.deleteBucket(this.accountInfo.getApiUrl(), this.accountInfo.getAuthToken(), {\n accountId: accountId(this.accountInfo.getAccountId()),\n bucketId: id,\n })\n }\n\n /**\n * Creates a new application key with the specified capabilities.\n * @param options - Key configuration including capabilities, name, and optional restrictions.\n *\n * @returns The full key including the secret (only returned at creation time).\n */\n async createKey(options: CreateKeyOptions): Promise<FullApplicationKey> {\n return this.raw.createKey(this.accountInfo.getApiUrl(), this.accountInfo.getAuthToken(), {\n accountId: accountId(this.accountInfo.getAccountId()),\n ...options,\n })\n }\n\n /**\n * Lists application keys in the account.\n * @param options - Optional pagination settings.\n *\n * @returns A page of application keys with an optional continuation token.\n */\n async listKeys(options?: {\n /**\n * Maximum number of keys to return per request. Forwarded to the\n * raw API's `maxKeyCount` parameter.\n */\n pageSize?: number\n /** Start listing after this key ID (for pagination). */\n startApplicationKeyId?: ApplicationKeyId\n }): Promise<ListKeysResponse> {\n return this.raw.listKeys(this.accountInfo.getApiUrl(), this.accountInfo.getAuthToken(), {\n accountId: accountId(this.accountInfo.getAccountId()),\n ...(options?.pageSize !== undefined ? { maxKeyCount: options.pageSize } : {}),\n ...(options?.startApplicationKeyId !== undefined\n ? { startApplicationKeyId: options.startApplicationKeyId }\n : {}),\n })\n }\n\n /**\n * Async iterator that yields every application key on the account,\n * automatically handling pagination via `listKeys`.\n *\n * @param options - Pagination + abort options. `pageSize` is forwarded\n * to `maxKeyCount`; the default is 1000.\n *\n * @returns An async iterable of {@link ApplicationKey} entries.\n *\n * @example\n * ```ts\n * for await (const key of client.paginateKeys()) {\n * console.log(key.keyName, key.capabilities)\n * }\n * ```\n */\n paginateKeys(options?: PaginatorOptions): AsyncIterableIterator<ApplicationKey> {\n return paginateItems(\n async (cursor: ApplicationKeyId | undefined) => {\n const resp = await this.listKeys({\n pageSize: options?.pageSize ?? DEFAULT_PAGE_SIZE,\n ...(cursor !== undefined ? { startApplicationKeyId: cursor } : {}),\n })\n return { page: resp, nextCursor: resp.nextApplicationKeyId ?? undefined }\n },\n (page) => page.keys,\n options?.signal,\n )\n }\n\n /**\n * Permanently deletes an application key.\n * @param applicationKeyId - The unique identifier of the key to delete.\n *\n * @returns The deleted application key metadata.\n */\n async deleteKey(applicationKeyId: ApplicationKeyId): Promise<ApplicationKey> {\n return this.raw.deleteKey(this.accountInfo.getApiUrl(), this.accountInfo.getAuthToken(), {\n applicationKeyId,\n })\n }\n\n /**\n * Checks whether the authorized application key carries every capability in\n * `needed`. Returns the missing capabilities so callers can fail fast with a\n * clear error instead of a generic 401/403 from the server.\n *\n * @param needed - The capabilities required by the planned operation.\n *\n * @returns An object with `ok: true` when every needed capability is\n * present, otherwise `{ ok: false, missing: [...] }`.\n *\n * @throws If {@link authorize} has not been called yet.\n */\n hasCapabilities(needed: readonly Capability[]): CapabilityCheckResult {\n const auth = this.accountInfo.getAuth()\n if (!auth) throw new Error('Not authorized. Call authorize() first.')\n const available = new Set<string>(auth.apiInfo.storageApi.allowed.capabilities)\n const missing = needed.filter((cap) => !available.has(cap as string))\n return { ok: missing.length === 0, missing }\n }\n}\n\nfunction bindAccountInfoAuthContext(\n accountInfo: AccountInfo,\n realmUrl: string,\n applicationKeyId: string,\n): void {\n accountInfo.setApplicationKeyId?.(applicationKeyId)\n accountInfo.setRealmUrl?.(realmUrl)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"client.cjs","names":[],"sources":["../src/client.ts"],"sourcesContent":["import type { AccountInfo } from './auth/account-info.ts'\nimport { InMemoryAccountInfo } from './auth/in-memory.ts'\nimport { getRealmUrl } from './auth/realms.ts'\nimport { ReauthCoalescer } from './auth/reauth-coalescer.ts'\nimport { Bucket } from './bucket.ts'\nimport { DEFAULT_RETRY_OPTIONS, type RetryOptions } from './http/retry.ts'\nimport type { HttpTransport } from './http/transport.ts'\nimport { FetchTransport, RetryTransport } from './http/transport.ts'\nimport { deriveAllowedSuffixes, UrlGuard } from './http/url-guard.ts'\nimport { RawClient } from './raw/index.ts'\nimport type { AuthorizeAccountResponse, Capability } from './types/auth.ts'\nimport type {\n BucketDefaultServerSideEncryptionSetting,\n BucketInfo,\n BucketRetentionPolicy,\n BucketType,\n BucketTypesFilter,\n CorsRule,\n CreateBucketRequest,\n LifecycleRule,\n} from './types/bucket.ts'\nimport type { ApplicationKeyId, BucketId } from './types/ids.ts'\nimport { accountId } from './types/ids.ts'\nimport type {\n ApplicationKey,\n CreateKeyOptions,\n FullApplicationKey,\n ListKeysResponse,\n} from './types/key.ts'\nimport type { ReplicationConfiguration } from './types/replication.ts'\nimport { throwIfSignalAborted } from './util/abort.ts'\nimport { DEFAULT_PAGE_SIZE } from './util/defaults.ts'\nimport { type PaginatorOptions, paginateItems } from './util/paginator.ts'\n\n/** Result of {@link B2Client.hasCapabilities}. */\nexport interface CapabilityCheckResult {\n /** `true` when the key carries every requested capability. */\n readonly ok: boolean\n /** Capabilities the call requested that the current key does not hold. Empty when `ok` is `true`. */\n readonly missing: readonly Capability[]\n}\n\n/** Configuration options for creating a {@link B2Client}. */\nexport interface B2ClientOptions {\n /** The application key ID from the B2 dashboard or `b2_create_key`. */\n readonly applicationKeyId: string\n /** The application key secret. */\n readonly applicationKey: string\n /**\n * B2 realm to authenticate against. Accepts a known realm-map key\n * (`\"production\"` or `\"staging\"`) or a direct base URL. Custom HTTPS hosts\n * are trusted with the application key during authorize, so never derive\n * `realm` from untrusted input. URL values must use HTTPS, or loopback IP\n * literal HTTP for local testing only; application-key credentials are sent\n * unencrypted over loopback HTTP. Unsupported schemes, malformed URLs,\n * non-URL strings, plaintext HTTP hostnames such as `localhost`, and\n * non-loopback plaintext HTTP are rejected before credentials are sent. URL\n * values must not include userinfo, query strings, or fragments. Defaults to\n * `\"production\"`.\n */\n readonly realm?: string\n /** Storage backend for authorization state. Defaults to {@link InMemoryAccountInfo}. */\n readonly accountInfo?: AccountInfo\n /** Custom HTTP transport. Defaults to {@link FetchTransport}. Wrapped by {@link RetryTransport}. */\n readonly transport?: HttpTransport\n /** Override retry behavior (max retries, backoff, and per-attempt timeout). */\n readonly retry?: Partial<RetryOptions>\n /** Custom user-agent string prepended to the SDK default. */\n readonly userAgent?: string\n /**\n * Override the SSRF allow-list. By default the SDK locks the\n * {@link FetchTransport} to host suffixes derived from the realm's authorize\n * response (e.g. `backblazeb2.com`, `backblaze.com`) so a compromised B2\n * endpoint cannot redirect the SDK to internal services. Pass an explicit\n * list to add hosts (e.g. when testing against a self-hosted proxy) or set\n * to an empty array to disable the guard entirely (not recommended).\n *\n * Only consulted when {@link B2ClientOptions.transport} is unset; a custom\n * transport is the user's responsibility to harden.\n */\n readonly allowedHostSuffixes?: readonly string[]\n /**\n * Follow same-origin GET/HEAD redirects in the default fetch transport after\n * checking each target with the SSRF guard. POST redirects remain blocked.\n * Defaults to true.\n */\n readonly followSameOriginRedirects?: boolean\n}\n\n/** Options for {@link B2Client.authorize}. */\nexport interface B2ClientAuthorizeOptions {\n /** Abort signal for cancelling the authorize request. */\n readonly signal?: AbortSignal\n}\n\n/**\n * High-level B2 client providing ergonomic access to buckets, files, and keys.\n *\n * @example\n * ```ts\n * const client = new B2Client({\n * applicationKeyId: process.env.B2_APPLICATION_KEY_ID,\n * applicationKey: process.env.B2_APPLICATION_KEY,\n * })\n * await client.authorize()\n * const buckets = await client.listBuckets()\n * ```\n */\nexport class B2Client {\n /** Low-level client for direct B2 API calls. */\n readonly raw: RawClient\n /** Authorization state storage (tokens, URLs, capabilities). */\n readonly accountInfo: AccountInfo\n /**\n * SSRF allow-list applied by the default {@link FetchTransport}. `null` when\n * a custom transport was supplied — in that case the SDK does not own the\n * guard. Locked down by {@link B2Client.authorize}.\n */\n readonly urlGuard: UrlGuard | null\n private readonly applicationKeyId: string\n private readonly applicationKey: string\n private readonly realmUrl: string\n private readonly userAllowedSuffixes: readonly string[] | undefined\n private readonly resolvedUploadRetryOptions: RetryOptions\n private readonly reauthCoalescer: ReauthCoalescer<string>\n\n /**\n * Creates a new B2Client. Call {@link authorize} before making API requests.\n * @param options - Configuration including credentials, realm, and transport settings.\n */\n constructor(options: B2ClientOptions) {\n this.applicationKeyId = options.applicationKeyId\n this.applicationKey = options.applicationKey\n this.realmUrl = getRealmUrl(options.realm ?? 'production')\n this.accountInfo = options.accountInfo ?? new InMemoryAccountInfo()\n bindAccountInfoAuthContext(this.accountInfo, this.realmUrl, this.applicationKeyId)\n this.userAllowedSuffixes = options.allowedHostSuffixes\n this.resolvedUploadRetryOptions = { ...DEFAULT_RETRY_OPTIONS, ...options.retry }\n this.reauthCoalescer = new ReauthCoalescer((signal) => this.doReauthorize(signal))\n\n let baseTransport: HttpTransport\n if (options.transport !== undefined) {\n baseTransport = options.transport\n this.urlGuard = null\n } else {\n const urlGuard = new UrlGuard()\n baseTransport = new FetchTransport({\n urlGuard,\n ...(options.userAgent !== undefined ? { userAgent: options.userAgent } : {}),\n ...(options.followSameOriginRedirects !== undefined\n ? { followSameOriginRedirects: options.followSameOriginRedirects }\n : {}),\n })\n this.urlGuard = urlGuard\n }\n\n const retryTransport = new RetryTransport({\n transport: baseTransport,\n retry: this.resolvedUploadRetryOptions,\n onReauth: (signal) => this.reauthorize(signal),\n })\n\n const cachedAuth = this.accountInfo.getAuth()\n if (cachedAuth !== null) this.lockUrlGuard(cachedAuth)\n\n this.raw = new RawClient({ transport: retryTransport })\n }\n\n /**\n * Authenticates with B2 and stores the authorization state. Must be called before other methods.\n *\n * @param options - Optional request controls.\n *\n * @returns The authorization response containing tokens, URLs, and capabilities.\n */\n async authorize(options?: B2ClientAuthorizeOptions): Promise<AuthorizeAccountResponse> {\n throwIfSignalAborted(options?.signal)\n const auth = await this.raw.authorizeAccount(\n this.applicationKeyId,\n this.applicationKey,\n this.realmUrl,\n options?.signal !== undefined ? { signal: options.signal } : undefined,\n )\n throwIfSignalAborted(options?.signal)\n this.accountInfo.setAuth(auth)\n this.lockUrlGuard(auth)\n return auth\n }\n\n private lockUrlGuard(auth: AuthorizeAccountResponse): void {\n if (this.urlGuard !== null) {\n const derived = deriveAllowedSuffixes(auth.apiInfo.storageApi)\n const merged =\n this.userAllowedSuffixes !== undefined\n ? this.userAllowedSuffixes.length === 0\n ? []\n : Array.from(new Set([...derived, ...this.userAllowedSuffixes]))\n : derived\n this.urlGuard.setAllowedSuffixes(merged)\n }\n }\n\n /**\n * Refresh credentials after a 401. Returns the fresh auth token so\n * {@link RetryTransport} can rewrite the in-flight request's\n * Authorization header before retrying.\n *\n * @param signal - Optional abort signal for the request that triggered reauthorization.\n *\n * @returns The fresh authorization token.\n */\n private reauthorize(signal: AbortSignal | undefined): Promise<string> {\n return this.reauthCoalescer.run(signal)\n }\n\n private async doReauthorize(signal: AbortSignal): Promise<string> {\n const auth = await this.authorize({ signal })\n return auth.authorizationToken\n }\n\n /**\n * Creates a new B2 bucket.\n * @param options - Bucket configuration including name, type, and optional settings.\n *\n * @returns A {@link Bucket} handle for the newly created bucket.\n */\n async createBucket(options: {\n /** Globally unique bucket name (6-63 chars; letters, digits, hyphens, periods). */\n bucketName: string\n /** Access level: `\"allPrivate\"` or `\"allPublic\"`. */\n bucketType: BucketType\n /**\n * Custom key-value metadata stored with the bucket. Keys must be 1-50\n * UTF-8 bytes, must not start with `b2-`, and all values together must be\n * at most 10,000 UTF-8 bytes. Keys must match\n * {@link BUCKET_INFO_KEY_PATTERN}. There is no bucketInfo pair-count cap.\n */\n bucketInfo?: Record<string, string>\n /**\n * CORS rules for browser-based access. A bucket may have at most 100\n * rules; rule names must be unique, 6-63 characters, match\n * `[A-Za-z0-9-]`, and not start with `b2-`. Each rule must be less than\n * 1,000 UTF-8 bytes across its name, origins, operations, allowed headers,\n * and exposed headers. `maxAgeSeconds` must be at most 86,400.\n */\n corsRules?: CorsRule[]\n /** Default server-side encryption for new files. */\n defaultServerSideEncryption?: BucketDefaultServerSideEncryptionSetting\n /** Default retention policy for new files (requires file lock). */\n defaultRetention?: BucketRetentionPolicy\n /** Enable file lock (Object Lock) on the bucket. Cannot be disabled once set. */\n fileLockEnabled?: boolean\n /** Lifecycle rules for automatic file deletion or hiding. */\n lifecycleRules?: LifecycleRule[]\n /** Cross-region replication configuration. */\n replicationConfiguration?: ReplicationConfiguration\n }): Promise<Bucket> {\n const {\n bucketInfo,\n bucketName,\n bucketType,\n corsRules,\n defaultRetention,\n defaultServerSideEncryption,\n fileLockEnabled,\n lifecycleRules,\n replicationConfiguration,\n } = options\n const request: CreateBucketRequest = {\n ...(bucketInfo !== undefined ? { bucketInfo } : {}),\n bucketName,\n bucketType,\n ...(corsRules !== undefined ? { corsRules } : {}),\n ...(defaultServerSideEncryption !== undefined ? { defaultServerSideEncryption } : {}),\n ...(defaultRetention !== undefined ? { defaultRetention } : {}),\n ...(fileLockEnabled !== undefined ? { fileLockEnabled } : {}),\n ...(lifecycleRules !== undefined ? { lifecycleRules } : {}),\n ...(replicationConfiguration !== undefined ? { replicationConfiguration } : {}),\n accountId: accountId(this.accountInfo.getAccountId()),\n }\n const info = await this.raw.createBucket(\n this.accountInfo.getApiUrl(),\n this.accountInfo.getAuthToken(),\n request,\n )\n return new Bucket(this, info, this.resolvedUploadRetryOptions)\n }\n\n /**\n * Lists buckets in the account, optionally filtered by ID, name, or type.\n * @param options - Optional filters for bucket ID, name, or type.\n *\n * @returns An array of {@link Bucket} handles.\n */\n async listBuckets(options?: {\n /** Filter to a specific bucket by ID. */\n bucketId?: BucketId\n /** Filter to a specific bucket by name. */\n bucketName?: string\n /** Filter by bucket types (e.g., `[\"allPrivate\"]`, `[\"shared\"]`, or `[\"all\"]`). */\n bucketTypes?: BucketTypesFilter\n }): Promise<Bucket[]> {\n const resp = await this.raw.listBuckets(\n this.accountInfo.getApiUrl(),\n this.accountInfo.getAuthToken(),\n {\n accountId: accountId(this.accountInfo.getAccountId()),\n ...options,\n },\n )\n return resp.buckets.map((info) => new Bucket(this, info, this.resolvedUploadRetryOptions))\n }\n\n /**\n * Looks up a single bucket by name.\n * @param bucketName - The name of the bucket to find.\n *\n * @returns The {@link Bucket} handle, or `null` if not found.\n */\n async getBucket(bucketName: string): Promise<Bucket | null> {\n const buckets = await this.listBuckets({ bucketName })\n const filteredMatch = buckets[0]\n if (filteredMatch !== undefined) return filteredMatch\n\n const unfilteredBuckets = await this.listBuckets()\n return unfilteredBuckets.find((bucket) => bucket.name === bucketName) ?? null\n }\n\n /**\n * Permanently deletes a bucket. The bucket must be empty.\n * @param id - The unique identifier of the bucket to delete.\n *\n * @returns The deleted bucket metadata.\n */\n async deleteBucket(id: BucketId): Promise<BucketInfo> {\n return this.raw.deleteBucket(this.accountInfo.getApiUrl(), this.accountInfo.getAuthToken(), {\n accountId: accountId(this.accountInfo.getAccountId()),\n bucketId: id,\n })\n }\n\n /**\n * Creates a new application key with the specified capabilities.\n * @param options - Key configuration including capabilities, name, and optional restrictions.\n *\n * @returns The full key including the secret (only returned at creation time).\n */\n async createKey(options: CreateKeyOptions): Promise<FullApplicationKey> {\n return this.raw.createKey(this.accountInfo.getApiUrl(), this.accountInfo.getAuthToken(), {\n accountId: accountId(this.accountInfo.getAccountId()),\n ...options,\n })\n }\n\n /**\n * Lists application keys in the account.\n * @param options - Optional pagination settings.\n *\n * @returns A page of application keys with an optional continuation token.\n */\n async listKeys(options?: {\n /**\n * Maximum number of keys to return per request. Forwarded to the\n * raw API's `maxKeyCount` parameter.\n */\n pageSize?: number\n /** Start listing at this key ID, usually from `nextApplicationKeyId`. */\n startApplicationKeyId?: ApplicationKeyId\n }): Promise<ListKeysResponse> {\n return this.raw.listKeys(this.accountInfo.getApiUrl(), this.accountInfo.getAuthToken(), {\n accountId: accountId(this.accountInfo.getAccountId()),\n ...(options?.pageSize !== undefined ? { maxKeyCount: options.pageSize } : {}),\n ...(options?.startApplicationKeyId !== undefined\n ? { startApplicationKeyId: options.startApplicationKeyId }\n : {}),\n })\n }\n\n /**\n * Async iterator that yields every application key on the account,\n * automatically handling pagination via `listKeys`.\n *\n * @param options - Pagination + abort options. `pageSize` is forwarded\n * to `maxKeyCount`; the default is 1000.\n *\n * @returns An async iterable of {@link ApplicationKey} entries.\n *\n * @example\n * ```ts\n * for await (const key of client.paginateKeys()) {\n * console.log(key.keyName, key.capabilities)\n * }\n * ```\n */\n paginateKeys(options?: PaginatorOptions): AsyncIterableIterator<ApplicationKey> {\n return paginateItems(\n async (cursor: ApplicationKeyId | undefined) => {\n const resp = await this.listKeys({\n pageSize: options?.pageSize ?? DEFAULT_PAGE_SIZE,\n ...(cursor !== undefined ? { startApplicationKeyId: cursor } : {}),\n })\n return { page: resp, nextCursor: resp.nextApplicationKeyId ?? undefined }\n },\n (page) => page.keys,\n options?.signal,\n )\n }\n\n /**\n * Permanently deletes an application key.\n * @param applicationKeyId - The unique identifier of the key to delete.\n *\n * @returns The deleted application key metadata.\n */\n async deleteKey(applicationKeyId: ApplicationKeyId): Promise<ApplicationKey> {\n return this.raw.deleteKey(this.accountInfo.getApiUrl(), this.accountInfo.getAuthToken(), {\n applicationKeyId,\n })\n }\n\n /**\n * Checks whether the authorized application key carries every capability in\n * `needed`. Returns the missing capabilities so callers can fail fast with a\n * clear error instead of a generic 401/403 from the server.\n *\n * @param needed - The capabilities required by the planned operation.\n *\n * @returns An object with `ok: true` when every needed capability is\n * present, otherwise `{ ok: false, missing: [...] }`.\n *\n * @throws If {@link authorize} has not been called yet.\n */\n hasCapabilities(needed: readonly Capability[]): CapabilityCheckResult {\n const auth = this.accountInfo.getAuth()\n if (!auth) throw new Error('Not authorized. Call authorize() first.')\n const available = new Set<string>(auth.apiInfo.storageApi.allowed.capabilities)\n const missing = needed.filter((cap) => !available.has(cap as string))\n return { ok: missing.length === 0, missing }\n }\n}\n\nfunction bindAccountInfoAuthContext(\n accountInfo: AccountInfo,\n realmUrl: string,\n applicationKeyId: string,\n): void {\n accountInfo.setApplicationKeyId?.(applicationKeyId)\n accountInfo.setRealmUrl?.(realmUrl)\n}\n"],"mappings":"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"}