@backblaze-labs/b2-sdk 0.1.0 → 0.2.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 (701) hide show
  1. package/CHANGELOG.md +110 -5
  2. package/README.md +144 -33
  3. package/dist/_virtual/_b2-sdk-version-json.cjs +4 -0
  4. package/dist/_virtual/_b2-sdk-version-json.js +4 -0
  5. package/dist/auth/account-info.d.cts +32 -0
  6. package/dist/auth/account-info.d.cts.map +1 -1
  7. package/dist/auth/account-info.d.ts +32 -0
  8. package/dist/auth/account-info.d.ts.map +1 -1
  9. package/dist/auth/file.cjs +408 -207
  10. package/dist/auth/file.cjs.map +1 -1
  11. package/dist/auth/file.d.cts +77 -3
  12. package/dist/auth/file.d.cts.map +1 -1
  13. package/dist/auth/file.d.ts +77 -3
  14. package/dist/auth/file.d.ts.map +1 -1
  15. package/dist/auth/file.js +407 -207
  16. package/dist/auth/file.js.map +1 -1
  17. package/dist/auth/in-memory.cjs +212 -183
  18. package/dist/auth/in-memory.cjs.map +1 -1
  19. package/dist/auth/in-memory.d.cts +8 -0
  20. package/dist/auth/in-memory.d.cts.map +1 -1
  21. package/dist/auth/in-memory.d.ts +8 -0
  22. package/dist/auth/in-memory.d.ts.map +1 -1
  23. package/dist/auth/in-memory.js +211 -182
  24. package/dist/auth/in-memory.js.map +1 -1
  25. package/dist/auth/index.cjs +7 -9
  26. package/dist/auth/index.d.cts +3 -2
  27. package/dist/auth/index.d.cts.map +1 -1
  28. package/dist/auth/index.d.ts +3 -2
  29. package/dist/auth/index.d.ts.map +1 -1
  30. package/dist/auth/index.js +2 -8
  31. package/dist/auth/realms.cjs +80 -7
  32. package/dist/auth/realms.cjs.map +1 -1
  33. package/dist/auth/realms.d.cts +27 -4
  34. package/dist/auth/realms.d.cts.map +1 -1
  35. package/dist/auth/realms.d.ts +27 -4
  36. package/dist/auth/realms.d.ts.map +1 -1
  37. package/dist/auth/realms.js +80 -9
  38. package/dist/auth/realms.js.map +1 -1
  39. package/dist/auth/upload-url-pool.cjs +55 -51
  40. package/dist/auth/upload-url-pool.cjs.map +1 -1
  41. package/dist/auth/upload-url-pool.js +55 -51
  42. package/dist/auth/upload-url-pool.js.map +1 -1
  43. package/dist/bucket.cjs +785 -787
  44. package/dist/bucket.cjs.map +1 -1
  45. package/dist/bucket.d.cts +35 -47
  46. package/dist/bucket.d.cts.map +1 -1
  47. package/dist/bucket.d.ts +35 -47
  48. package/dist/bucket.d.ts.map +1 -1
  49. package/dist/bucket.js +780 -782
  50. package/dist/bucket.js.map +1 -1
  51. package/dist/client.cjs +246 -228
  52. package/dist/client.cjs.map +1 -1
  53. package/dist/client.d.cts +25 -17
  54. package/dist/client.d.cts.map +1 -1
  55. package/dist/client.d.ts +25 -17
  56. package/dist/client.d.ts.map +1 -1
  57. package/dist/client.js +243 -225
  58. package/dist/client.js.map +1 -1
  59. package/dist/copy/large.cjs +114 -71
  60. package/dist/copy/large.cjs.map +1 -1
  61. package/dist/copy/large.d.cts +6 -0
  62. package/dist/copy/large.d.cts.map +1 -1
  63. package/dist/copy/large.d.ts +6 -0
  64. package/dist/copy/large.d.ts.map +1 -1
  65. package/dist/copy/large.js +112 -69
  66. package/dist/copy/large.js.map +1 -1
  67. package/dist/download/checksum.cjs +89 -0
  68. package/dist/download/checksum.cjs.map +1 -0
  69. package/dist/download/checksum.d.cts +40 -0
  70. package/dist/download/checksum.d.cts.map +1 -0
  71. package/dist/download/checksum.d.ts +40 -0
  72. package/dist/download/checksum.d.ts.map +1 -0
  73. package/dist/download/checksum.js +87 -0
  74. package/dist/download/checksum.js.map +1 -0
  75. package/dist/download/parallel.cjs +214 -118
  76. package/dist/download/parallel.cjs.map +1 -1
  77. package/dist/download/parallel.d.cts +5 -1
  78. package/dist/download/parallel.d.cts.map +1 -1
  79. package/dist/download/parallel.d.ts +5 -1
  80. package/dist/download/parallel.d.ts.map +1 -1
  81. package/dist/download/parallel.js +212 -116
  82. package/dist/download/parallel.js.map +1 -1
  83. package/dist/download/single.cjs +188 -97
  84. package/dist/download/single.cjs.map +1 -1
  85. package/dist/download/single.d.cts +6 -1
  86. package/dist/download/single.d.cts.map +1 -1
  87. package/dist/download/single.d.ts +6 -1
  88. package/dist/download/single.d.ts.map +1 -1
  89. package/dist/download/single.js +186 -98
  90. package/dist/download/single.js.map +1 -1
  91. package/dist/errors/index.cjs +699 -243
  92. package/dist/errors/index.cjs.map +1 -1
  93. package/dist/errors/index.d.cts +285 -82
  94. package/dist/errors/index.d.cts.map +1 -1
  95. package/dist/errors/index.d.ts +285 -82
  96. package/dist/errors/index.d.ts.map +1 -1
  97. package/dist/errors/index.js +678 -261
  98. package/dist/errors/index.js.map +1 -1
  99. package/dist/http/retry.cjs +45 -28
  100. package/dist/http/retry.cjs.map +1 -1
  101. package/dist/http/retry.d.cts +15 -2
  102. package/dist/http/retry.d.cts.map +1 -1
  103. package/dist/http/retry.d.ts +15 -2
  104. package/dist/http/retry.d.ts.map +1 -1
  105. package/dist/http/retry.js +46 -31
  106. package/dist/http/retry.js.map +1 -1
  107. package/dist/http/transport.cjs +438 -140
  108. package/dist/http/transport.cjs.map +1 -1
  109. package/dist/http/transport.d.cts +21 -2
  110. package/dist/http/transport.d.cts.map +1 -1
  111. package/dist/http/transport.d.ts +21 -2
  112. package/dist/http/transport.d.ts.map +1 -1
  113. package/dist/http/transport.js +437 -140
  114. package/dist/http/transport.js.map +1 -1
  115. package/dist/http/url-guard.cjs +154 -89
  116. package/dist/http/url-guard.cjs.map +1 -1
  117. package/dist/http/url-guard.d.cts +25 -3
  118. package/dist/http/url-guard.d.cts.map +1 -1
  119. package/dist/http/url-guard.d.ts +25 -3
  120. package/dist/http/url-guard.d.ts.map +1 -1
  121. package/dist/http/url-guard.js +152 -90
  122. package/dist/http/url-guard.js.map +1 -1
  123. package/dist/http/user-agent.cjs +84 -44
  124. package/dist/http/user-agent.cjs.map +1 -1
  125. package/dist/http/user-agent.js +84 -46
  126. package/dist/http/user-agent.js.map +1 -1
  127. package/dist/index.cjs +101 -77
  128. package/dist/index.d.cts +27 -21
  129. package/dist/index.d.cts.map +1 -1
  130. package/dist/index.d.ts +27 -21
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +15 -71
  133. package/dist/internal/b2-naming.cjs +66 -0
  134. package/dist/internal/b2-naming.cjs.map +1 -0
  135. package/dist/internal/b2-naming.d.cts +43 -0
  136. package/dist/internal/b2-naming.d.cts.map +1 -0
  137. package/dist/internal/b2-naming.d.ts +43 -0
  138. package/dist/internal/b2-naming.d.ts.map +1 -0
  139. package/dist/internal/b2-naming.js +60 -0
  140. package/dist/internal/b2-naming.js.map +1 -0
  141. package/dist/internal/upload-retry-options.cjs +21 -0
  142. package/dist/internal/upload-retry-options.cjs.map +1 -0
  143. package/dist/internal/upload-retry-options.d.cts +12 -0
  144. package/dist/internal/upload-retry-options.d.cts.map +1 -0
  145. package/dist/internal/upload-retry-options.d.ts +12 -0
  146. package/dist/internal/upload-retry-options.d.ts.map +1 -0
  147. package/dist/internal/upload-retry-options.js +21 -0
  148. package/dist/internal/upload-retry-options.js.map +1 -0
  149. package/dist/internal/url-redaction.cjs +31 -0
  150. package/dist/internal/url-redaction.cjs.map +1 -0
  151. package/dist/internal/url-redaction.d.cts +17 -0
  152. package/dist/internal/url-redaction.d.cts.map +1 -0
  153. package/dist/internal/url-redaction.d.ts +17 -0
  154. package/dist/internal/url-redaction.d.ts.map +1 -0
  155. package/dist/internal/url-redaction.js +31 -0
  156. package/dist/internal/url-redaction.js.map +1 -0
  157. package/dist/notifications/index.cjs +4 -6
  158. package/dist/notifications/index.d.cts +1 -1
  159. package/dist/notifications/index.d.cts.map +1 -1
  160. package/dist/notifications/index.d.ts +1 -1
  161. package/dist/notifications/index.d.ts.map +1 -1
  162. package/dist/notifications/index.js +1 -6
  163. package/dist/notifications/webhook.cjs +195 -85
  164. package/dist/notifications/webhook.cjs.map +1 -1
  165. package/dist/notifications/webhook.d.cts.map +1 -1
  166. package/dist/notifications/webhook.d.ts.map +1 -1
  167. package/dist/notifications/webhook.js +195 -87
  168. package/dist/notifications/webhook.js.map +1 -1
  169. package/dist/object.cjs +253 -210
  170. package/dist/object.cjs.map +1 -1
  171. package/dist/object.d.cts +9 -55
  172. package/dist/object.d.cts.map +1 -1
  173. package/dist/object.d.ts +9 -55
  174. package/dist/object.d.ts.map +1 -1
  175. package/dist/object.js +249 -206
  176. package/dist/object.js.map +1 -1
  177. package/dist/raw/encoding.cjs +74 -35
  178. package/dist/raw/encoding.cjs.map +1 -1
  179. package/dist/raw/encoding.js +74 -38
  180. package/dist/raw/encoding.js.map +1 -1
  181. package/dist/raw/index.cjs +678 -587
  182. package/dist/raw/index.cjs.map +1 -1
  183. package/dist/raw/index.d.cts +121 -18
  184. package/dist/raw/index.d.cts.map +1 -1
  185. package/dist/raw/index.d.ts +121 -18
  186. package/dist/raw/index.d.ts.map +1 -1
  187. package/dist/raw/index.js +674 -589
  188. package/dist/raw/index.js.map +1 -1
  189. package/dist/s3/index.cjs +355 -18
  190. package/dist/s3/index.cjs.map +1 -1
  191. package/dist/s3/index.d.cts +233 -5
  192. package/dist/s3/index.d.cts.map +1 -1
  193. package/dist/s3/index.d.ts +233 -5
  194. package/dist/s3/index.d.ts.map +1 -1
  195. package/dist/s3/index.js +351 -22
  196. package/dist/s3/index.js.map +1 -1
  197. package/dist/s3/sigv4.cjs +149 -0
  198. package/dist/s3/sigv4.cjs.map +1 -0
  199. package/dist/s3/sigv4.d.cts +43 -0
  200. package/dist/s3/sigv4.d.cts.map +1 -0
  201. package/dist/s3/sigv4.d.ts +43 -0
  202. package/dist/s3/sigv4.d.ts.map +1 -0
  203. package/dist/s3/sigv4.js +148 -0
  204. package/dist/s3/sigv4.js.map +1 -0
  205. package/dist/s3/validation.cjs +69 -0
  206. package/dist/s3/validation.cjs.map +1 -0
  207. package/dist/s3/validation.d.cts +43 -0
  208. package/dist/s3/validation.d.cts.map +1 -0
  209. package/dist/s3/validation.d.ts +43 -0
  210. package/dist/s3/validation.d.ts.map +1 -0
  211. package/dist/s3/validation.js +66 -0
  212. package/dist/s3/validation.js.map +1 -0
  213. package/dist/simulator/capabilities.cjs +63 -48
  214. package/dist/simulator/capabilities.cjs.map +1 -1
  215. package/dist/simulator/capabilities.js +63 -49
  216. package/dist/simulator/capabilities.js.map +1 -1
  217. package/dist/simulator/index.cjs +2124 -1548
  218. package/dist/simulator/index.cjs.map +1 -1
  219. package/dist/simulator/index.d.cts +79 -11
  220. package/dist/simulator/index.d.cts.map +1 -1
  221. package/dist/simulator/index.d.ts +79 -11
  222. package/dist/simulator/index.d.ts.map +1 -1
  223. package/dist/simulator/index.js +2112 -1546
  224. package/dist/simulator/index.js.map +1 -1
  225. package/dist/simulator/validation.cjs +191 -153
  226. package/dist/simulator/validation.cjs.map +1 -1
  227. package/dist/simulator/validation.d.cts +3 -21
  228. package/dist/simulator/validation.d.cts.map +1 -1
  229. package/dist/simulator/validation.d.ts +3 -21
  230. package/dist/simulator/validation.d.ts.map +1 -1
  231. package/dist/simulator/validation.js +188 -162
  232. package/dist/simulator/validation.js.map +1 -1
  233. package/dist/streams/collect.cjs +74 -24
  234. package/dist/streams/collect.cjs.map +1 -1
  235. package/dist/streams/collect.d.cts +14 -1
  236. package/dist/streams/collect.d.cts.map +1 -1
  237. package/dist/streams/collect.d.ts +14 -1
  238. package/dist/streams/collect.d.ts.map +1 -1
  239. package/dist/streams/collect.js +74 -25
  240. package/dist/streams/collect.js.map +1 -1
  241. package/dist/streams/file-source.cjs +287 -0
  242. package/dist/streams/file-source.cjs.map +1 -0
  243. package/dist/streams/file-source.d.cts +96 -0
  244. package/dist/streams/file-source.d.cts.map +1 -0
  245. package/dist/streams/file-source.d.ts +96 -0
  246. package/dist/streams/file-source.d.ts.map +1 -0
  247. package/dist/streams/file-source.js +286 -0
  248. package/dist/streams/file-source.js.map +1 -0
  249. package/dist/streams/hash.cjs +207 -115
  250. package/dist/streams/hash.cjs.map +1 -1
  251. package/dist/streams/hash.d.cts +5 -4
  252. package/dist/streams/hash.d.cts.map +1 -1
  253. package/dist/streams/hash.d.ts +5 -4
  254. package/dist/streams/hash.d.ts.map +1 -1
  255. package/dist/streams/hash.js +208 -95
  256. package/dist/streams/hash.js.map +1 -1
  257. package/dist/streams/index.cjs +12 -12
  258. package/dist/streams/index.d.cts +3 -3
  259. package/dist/streams/index.d.cts.map +1 -1
  260. package/dist/streams/index.d.ts +3 -3
  261. package/dist/streams/index.d.ts.map +1 -1
  262. package/dist/streams/index.js +2 -10
  263. package/dist/streams/progress.cjs +60 -46
  264. package/dist/streams/progress.cjs.map +1 -1
  265. package/dist/streams/progress.js +60 -46
  266. package/dist/streams/progress.js.map +1 -1
  267. package/dist/streams/source.cjs +316 -146
  268. package/dist/streams/source.cjs.map +1 -1
  269. package/dist/streams/source.d.cts +56 -18
  270. package/dist/streams/source.d.cts.map +1 -1
  271. package/dist/streams/source.d.ts +56 -18
  272. package/dist/streams/source.d.ts.map +1 -1
  273. package/dist/streams/source.js +312 -149
  274. package/dist/streams/source.js.map +1 -1
  275. package/dist/sync/actions/index.cjs +236 -184
  276. package/dist/sync/actions/index.cjs.map +1 -1
  277. package/dist/sync/actions/index.d.cts +29 -21
  278. package/dist/sync/actions/index.d.cts.map +1 -1
  279. package/dist/sync/actions/index.d.ts +29 -21
  280. package/dist/sync/actions/index.d.ts.map +1 -1
  281. package/dist/sync/actions/index.js +236 -190
  282. package/dist/sync/actions/index.js.map +1 -1
  283. package/dist/sync/b2-sha1-reader.cjs +148 -0
  284. package/dist/sync/b2-sha1-reader.cjs.map +1 -0
  285. package/dist/sync/b2-sha1-reader.d.cts +58 -0
  286. package/dist/sync/b2-sha1-reader.d.cts.map +1 -0
  287. package/dist/sync/b2-sha1-reader.d.ts +58 -0
  288. package/dist/sync/b2-sha1-reader.d.ts.map +1 -0
  289. package/dist/sync/b2-sha1-reader.js +145 -0
  290. package/dist/sync/b2-sha1-reader.js.map +1 -0
  291. package/dist/sync/download-staging.cjs +265 -0
  292. package/dist/sync/download-staging.cjs.map +1 -0
  293. package/dist/sync/download-staging.d.cts +54 -0
  294. package/dist/sync/download-staging.d.cts.map +1 -0
  295. package/dist/sync/download-staging.d.ts +54 -0
  296. package/dist/sync/download-staging.d.ts.map +1 -0
  297. package/dist/sync/download-staging.js +259 -0
  298. package/dist/sync/download-staging.js.map +1 -0
  299. package/dist/sync/filesystem-errors.cjs +32 -0
  300. package/dist/sync/filesystem-errors.cjs.map +1 -0
  301. package/dist/sync/filesystem-errors.d.cts +8 -0
  302. package/dist/sync/filesystem-errors.d.cts.map +1 -0
  303. package/dist/sync/filesystem-errors.d.ts +8 -0
  304. package/dist/sync/filesystem-errors.d.ts.map +1 -0
  305. package/dist/sync/filesystem-errors.js +32 -0
  306. package/dist/sync/filesystem-errors.js.map +1 -0
  307. package/dist/sync/filters.cjs +217 -0
  308. package/dist/sync/filters.cjs.map +1 -0
  309. package/dist/sync/filters.d.cts +51 -0
  310. package/dist/sync/filters.d.cts.map +1 -0
  311. package/dist/sync/filters.d.ts +51 -0
  312. package/dist/sync/filters.d.ts.map +1 -0
  313. package/dist/sync/filters.js +213 -0
  314. package/dist/sync/filters.js.map +1 -0
  315. package/dist/sync/index.cjs +39 -22
  316. package/dist/sync/index.d.cts +14 -9
  317. package/dist/sync/index.d.cts.map +1 -1
  318. package/dist/sync/index.d.ts +14 -9
  319. package/dist/sync/index.d.ts.map +1 -1
  320. package/dist/sync/index.js +9 -20
  321. package/dist/sync/local-file-identity.cjs +61 -0
  322. package/dist/sync/local-file-identity.cjs.map +1 -0
  323. package/dist/sync/local-file-identity.d.cts +37 -0
  324. package/dist/sync/local-file-identity.d.cts.map +1 -0
  325. package/dist/sync/local-file-identity.d.ts +37 -0
  326. package/dist/sync/local-file-identity.d.ts.map +1 -0
  327. package/dist/sync/local-file-identity.js +60 -0
  328. package/dist/sync/local-file-identity.js.map +1 -0
  329. package/dist/sync/local-file-io.cjs +364 -0
  330. package/dist/sync/local-file-io.cjs.map +1 -0
  331. package/dist/sync/local-file-io.d.cts +75 -0
  332. package/dist/sync/local-file-io.d.cts.map +1 -0
  333. package/dist/sync/local-file-io.d.ts +75 -0
  334. package/dist/sync/local-file-io.d.ts.map +1 -0
  335. package/dist/sync/local-file-io.js +360 -0
  336. package/dist/sync/local-file-io.js.map +1 -0
  337. package/dist/sync/local-filesystem-root.cjs +27 -0
  338. package/dist/sync/local-filesystem-root.cjs.map +1 -0
  339. package/dist/sync/local-filesystem-root.d.cts +18 -0
  340. package/dist/sync/local-filesystem-root.d.cts.map +1 -0
  341. package/dist/sync/local-filesystem-root.d.ts +18 -0
  342. package/dist/sync/local-filesystem-root.d.ts.map +1 -0
  343. package/dist/sync/local-filesystem-root.js +26 -0
  344. package/dist/sync/local-filesystem-root.js.map +1 -0
  345. package/dist/sync/local-sha1.cjs +119 -0
  346. package/dist/sync/local-sha1.cjs.map +1 -0
  347. package/dist/sync/local-sha1.d.cts +39 -0
  348. package/dist/sync/local-sha1.d.cts.map +1 -0
  349. package/dist/sync/local-sha1.d.ts +39 -0
  350. package/dist/sync/local-sha1.d.ts.map +1 -0
  351. package/dist/sync/local-sha1.js +117 -0
  352. package/dist/sync/local-sha1.js.map +1 -0
  353. package/dist/sync/pairing.cjs +118 -29
  354. package/dist/sync/pairing.cjs.map +1 -1
  355. package/dist/sync/pairing.d.cts +7 -2
  356. package/dist/sync/pairing.d.cts.map +1 -1
  357. package/dist/sync/pairing.d.ts +7 -2
  358. package/dist/sync/pairing.d.ts.map +1 -1
  359. package/dist/sync/pairing.js +120 -31
  360. package/dist/sync/pairing.js.map +1 -1
  361. package/dist/sync/path-order.cjs +30 -0
  362. package/dist/sync/path-order.cjs.map +1 -0
  363. package/dist/sync/path-order.d.cts +28 -0
  364. package/dist/sync/path-order.d.cts.map +1 -0
  365. package/dist/sync/path-order.d.ts +28 -0
  366. package/dist/sync/path-order.d.ts.map +1 -0
  367. package/dist/sync/path-order.js +29 -0
  368. package/dist/sync/path-order.js.map +1 -0
  369. package/dist/sync/path-safety.cjs +111 -0
  370. package/dist/sync/path-safety.cjs.map +1 -0
  371. package/dist/sync/path-safety.d.cts +78 -0
  372. package/dist/sync/path-safety.d.cts.map +1 -0
  373. package/dist/sync/path-safety.d.ts +78 -0
  374. package/dist/sync/path-safety.d.ts.map +1 -0
  375. package/dist/sync/path-safety.js +105 -0
  376. package/dist/sync/path-safety.js.map +1 -0
  377. package/dist/sync/paths.d.cts +19 -0
  378. package/dist/sync/paths.d.cts.map +1 -0
  379. package/dist/sync/paths.d.ts +19 -0
  380. package/dist/sync/paths.d.ts.map +1 -0
  381. package/dist/sync/policies/compare.cjs +389 -11
  382. package/dist/sync/policies/compare.cjs.map +1 -1
  383. package/dist/sync/policies/compare.d.cts +100 -2
  384. package/dist/sync/policies/compare.d.cts.map +1 -1
  385. package/dist/sync/policies/compare.d.ts +100 -2
  386. package/dist/sync/policies/compare.d.ts.map +1 -1
  387. package/dist/sync/policies/compare.js +387 -13
  388. package/dist/sync/policies/compare.js.map +1 -1
  389. package/dist/sync/policies/index.cjs +76 -65
  390. package/dist/sync/policies/index.cjs.map +1 -1
  391. package/dist/sync/policies/index.d.cts +35 -6
  392. package/dist/sync/policies/index.d.cts.map +1 -1
  393. package/dist/sync/policies/index.d.ts +35 -6
  394. package/dist/sync/policies/index.d.ts.map +1 -1
  395. package/dist/sync/policies/index.js +76 -65
  396. package/dist/sync/policies/index.js.map +1 -1
  397. package/dist/sync/prefix.cjs +96 -0
  398. package/dist/sync/prefix.cjs.map +1 -0
  399. package/dist/sync/prefix.d.cts +55 -0
  400. package/dist/sync/prefix.d.cts.map +1 -0
  401. package/dist/sync/prefix.d.ts +55 -0
  402. package/dist/sync/prefix.d.ts.map +1 -0
  403. package/dist/sync/prefix.js +92 -0
  404. package/dist/sync/prefix.js.map +1 -0
  405. package/dist/sync/regexp-safety.cjs +192 -0
  406. package/dist/sync/regexp-safety.cjs.map +1 -0
  407. package/dist/sync/regexp-safety.d.cts +29 -0
  408. package/dist/sync/regexp-safety.d.cts.map +1 -0
  409. package/dist/sync/regexp-safety.d.ts +29 -0
  410. package/dist/sync/regexp-safety.d.ts.map +1 -0
  411. package/dist/sync/regexp-safety.js +190 -0
  412. package/dist/sync/regexp-safety.js.map +1 -0
  413. package/dist/sync/scan-events.cjs +33 -0
  414. package/dist/sync/scan-events.cjs.map +1 -0
  415. package/dist/sync/scan-events.d.cts +17 -0
  416. package/dist/sync/scan-events.d.cts.map +1 -0
  417. package/dist/sync/scan-events.d.ts +17 -0
  418. package/dist/sync/scan-events.d.ts.map +1 -0
  419. package/dist/sync/scan-events.js +32 -0
  420. package/dist/sync/scan-events.js.map +1 -0
  421. package/dist/sync/scan-limit.cjs +33 -0
  422. package/dist/sync/scan-limit.cjs.map +1 -0
  423. package/dist/sync/scan-limit.d.cts +21 -0
  424. package/dist/sync/scan-limit.d.cts.map +1 -0
  425. package/dist/sync/scan-limit.d.ts +21 -0
  426. package/dist/sync/scan-limit.d.ts.map +1 -0
  427. package/dist/sync/scan-limit.js +31 -0
  428. package/dist/sync/scan-limit.js.map +1 -0
  429. package/dist/sync/scanners/b2.cjs +239 -55
  430. package/dist/sync/scanners/b2.cjs.map +1 -1
  431. package/dist/sync/scanners/b2.d.cts +26 -7
  432. package/dist/sync/scanners/b2.d.cts.map +1 -1
  433. package/dist/sync/scanners/b2.d.ts +26 -7
  434. package/dist/sync/scanners/b2.d.ts.map +1 -1
  435. package/dist/sync/scanners/b2.js +239 -55
  436. package/dist/sync/scanners/b2.js.map +1 -1
  437. package/dist/sync/scanners/local.cjs +215 -56
  438. package/dist/sync/scanners/local.cjs.map +1 -1
  439. package/dist/sync/scanners/local.d.cts +22 -7
  440. package/dist/sync/scanners/local.d.cts.map +1 -1
  441. package/dist/sync/scanners/local.d.ts +22 -7
  442. package/dist/sync/scanners/local.d.ts.map +1 -1
  443. package/dist/sync/scanners/local.js +216 -57
  444. package/dist/sync/scanners/local.js.map +1 -1
  445. package/dist/sync/sha1-metadata.cjs +94 -0
  446. package/dist/sync/sha1-metadata.cjs.map +1 -0
  447. package/dist/sync/sha1-metadata.d.cts +82 -0
  448. package/dist/sync/sha1-metadata.d.cts.map +1 -0
  449. package/dist/sync/sha1-metadata.d.ts +82 -0
  450. package/dist/sync/sha1-metadata.d.ts.map +1 -0
  451. package/dist/sync/sha1-metadata.js +89 -0
  452. package/dist/sync/sha1-metadata.js.map +1 -0
  453. package/dist/sync/sha1-options.cjs +23 -0
  454. package/dist/sync/sha1-options.cjs.map +1 -0
  455. package/dist/sync/sha1-options.d.cts +14 -0
  456. package/dist/sync/sha1-options.d.cts.map +1 -0
  457. package/dist/sync/sha1-options.d.ts +14 -0
  458. package/dist/sync/sha1-options.d.ts.map +1 -0
  459. package/dist/sync/sha1-options.js +21 -0
  460. package/dist/sync/sha1-options.js.map +1 -0
  461. package/dist/sync/synchronizer.cjs +782 -197
  462. package/dist/sync/synchronizer.cjs.map +1 -1
  463. package/dist/sync/synchronizer.d.cts +47 -1
  464. package/dist/sync/synchronizer.d.cts.map +1 -1
  465. package/dist/sync/synchronizer.d.ts +47 -1
  466. package/dist/sync/synchronizer.d.ts.map +1 -1
  467. package/dist/sync/synchronizer.js +779 -173
  468. package/dist/sync/synchronizer.js.map +1 -1
  469. package/dist/sync/types.d.cts +208 -16
  470. package/dist/sync/types.d.cts.map +1 -1
  471. package/dist/sync/types.d.ts +208 -16
  472. package/dist/sync/types.d.ts.map +1 -1
  473. package/dist/types/auth.cjs +76 -56
  474. package/dist/types/auth.cjs.map +1 -1
  475. package/dist/types/auth.d.cts +67 -9
  476. package/dist/types/auth.d.cts.map +1 -1
  477. package/dist/types/auth.d.ts +67 -9
  478. package/dist/types/auth.d.ts.map +1 -1
  479. package/dist/types/auth.js +77 -57
  480. package/dist/types/auth.js.map +1 -1
  481. package/dist/types/bucket.cjs +74 -38
  482. package/dist/types/bucket.cjs.map +1 -1
  483. package/dist/types/bucket.js +75 -41
  484. package/dist/types/bucket.js.map +1 -1
  485. package/dist/types/encryption.cjs +364 -327
  486. package/dist/types/encryption.cjs.map +1 -1
  487. package/dist/types/encryption.d.cts +16 -0
  488. package/dist/types/encryption.d.cts.map +1 -1
  489. package/dist/types/encryption.d.ts +16 -0
  490. package/dist/types/encryption.d.ts.map +1 -1
  491. package/dist/types/encryption.js +364 -310
  492. package/dist/types/encryption.js.map +1 -1
  493. package/dist/types/errors.cjs +47 -0
  494. package/dist/types/errors.cjs.map +1 -0
  495. package/dist/types/errors.d.cts +13 -4
  496. package/dist/types/errors.d.cts.map +1 -1
  497. package/dist/types/errors.d.ts +13 -4
  498. package/dist/types/errors.d.ts.map +1 -1
  499. package/dist/types/errors.js +47 -0
  500. package/dist/types/errors.js.map +1 -0
  501. package/dist/types/file.cjs +36 -19
  502. package/dist/types/file.cjs.map +1 -1
  503. package/dist/types/file.d.cts +2 -2
  504. package/dist/types/file.d.cts.map +1 -1
  505. package/dist/types/file.d.ts +2 -2
  506. package/dist/types/file.d.ts.map +1 -1
  507. package/dist/types/file.js +37 -21
  508. package/dist/types/file.js.map +1 -1
  509. package/dist/types/ids.cjs +53 -9
  510. package/dist/types/ids.cjs.map +1 -1
  511. package/dist/types/ids.js +54 -15
  512. package/dist/types/ids.js.map +1 -1
  513. package/dist/types/index.d.cts +12 -11
  514. package/dist/types/index.d.cts.map +1 -1
  515. package/dist/types/index.d.ts +12 -11
  516. package/dist/types/index.d.ts.map +1 -1
  517. package/dist/types/key.d.cts +44 -8
  518. package/dist/types/key.d.cts.map +1 -1
  519. package/dist/types/key.d.ts +44 -8
  520. package/dist/types/key.d.ts.map +1 -1
  521. package/dist/types/lock.cjs +33 -13
  522. package/dist/types/lock.cjs.map +1 -1
  523. package/dist/types/lock.js +34 -15
  524. package/dist/types/lock.js.map +1 -1
  525. package/dist/types/notifications.cjs +44 -22
  526. package/dist/types/notifications.cjs.map +1 -1
  527. package/dist/types/notifications.js +45 -23
  528. package/dist/types/notifications.js.map +1 -1
  529. package/dist/types/upload.d.cts +39 -5
  530. package/dist/types/upload.d.cts.map +1 -1
  531. package/dist/types/upload.d.ts +39 -5
  532. package/dist/types/upload.d.ts.map +1 -1
  533. package/dist/upload/abort-scope.cjs +91 -0
  534. package/dist/upload/abort-scope.cjs.map +1 -0
  535. package/dist/upload/abort-scope.d.cts +48 -0
  536. package/dist/upload/abort-scope.d.cts.map +1 -0
  537. package/dist/upload/abort-scope.d.ts +48 -0
  538. package/dist/upload/abort-scope.d.ts.map +1 -0
  539. package/dist/upload/abort-scope.js +88 -0
  540. package/dist/upload/abort-scope.js.map +1 -0
  541. package/dist/upload/cancel.cjs +183 -8
  542. package/dist/upload/cancel.cjs.map +1 -1
  543. package/dist/upload/cancel.d.cts +110 -2
  544. package/dist/upload/cancel.d.cts.map +1 -1
  545. package/dist/upload/cancel.d.ts +110 -2
  546. package/dist/upload/cancel.d.ts.map +1 -1
  547. package/dist/upload/cancel.js +178 -9
  548. package/dist/upload/cancel.js.map +1 -1
  549. package/dist/upload/concurrency.cjs +79 -52
  550. package/dist/upload/concurrency.cjs.map +1 -1
  551. package/dist/upload/concurrency.js +79 -53
  552. package/dist/upload/concurrency.js.map +1 -1
  553. package/dist/upload/finish.cjs +59 -0
  554. package/dist/upload/finish.cjs.map +1 -0
  555. package/dist/upload/finish.d.cts +26 -0
  556. package/dist/upload/finish.d.cts.map +1 -0
  557. package/dist/upload/finish.d.ts +26 -0
  558. package/dist/upload/finish.d.ts.map +1 -0
  559. package/dist/upload/finish.js +59 -0
  560. package/dist/upload/finish.js.map +1 -0
  561. package/dist/upload/large.cjs +301 -218
  562. package/dist/upload/large.cjs.map +1 -1
  563. package/dist/upload/large.d.cts +76 -9
  564. package/dist/upload/large.d.cts.map +1 -1
  565. package/dist/upload/large.d.ts +76 -9
  566. package/dist/upload/large.d.ts.map +1 -1
  567. package/dist/upload/large.js +301 -218
  568. package/dist/upload/large.js.map +1 -1
  569. package/dist/upload/options.cjs +28 -0
  570. package/dist/upload/options.cjs.map +1 -0
  571. package/dist/upload/options.d.cts +104 -0
  572. package/dist/upload/options.d.cts.map +1 -0
  573. package/dist/upload/options.d.ts +104 -0
  574. package/dist/upload/options.d.ts.map +1 -0
  575. package/dist/upload/options.js +27 -0
  576. package/dist/upload/options.js.map +1 -0
  577. package/dist/upload/resume.cjs +333 -33
  578. package/dist/upload/resume.cjs.map +1 -1
  579. package/dist/upload/resume.d.cts +82 -12
  580. package/dist/upload/resume.d.cts.map +1 -1
  581. package/dist/upload/resume.d.ts +82 -12
  582. package/dist/upload/resume.d.ts.map +1 -1
  583. package/dist/upload/resume.js +330 -33
  584. package/dist/upload/resume.js.map +1 -1
  585. package/dist/upload/retry.cjs +186 -0
  586. package/dist/upload/retry.cjs.map +1 -0
  587. package/dist/upload/retry.d.cts +127 -0
  588. package/dist/upload/retry.d.cts.map +1 -0
  589. package/dist/upload/retry.d.ts +127 -0
  590. package/dist/upload/retry.d.ts.map +1 -0
  591. package/dist/upload/retry.js +182 -0
  592. package/dist/upload/retry.js.map +1 -0
  593. package/dist/upload/single.cjs +68 -44
  594. package/dist/upload/single.cjs.map +1 -1
  595. package/dist/upload/single.d.cts +2 -1
  596. package/dist/upload/single.d.cts.map +1 -1
  597. package/dist/upload/single.d.ts +2 -1
  598. package/dist/upload/single.d.ts.map +1 -1
  599. package/dist/upload/single.js +68 -44
  600. package/dist/upload/single.js.map +1 -1
  601. package/dist/upload/stream.cjs +317 -193
  602. package/dist/upload/stream.cjs.map +1 -1
  603. package/dist/upload/stream.d.cts +3 -1
  604. package/dist/upload/stream.d.cts.map +1 -1
  605. package/dist/upload/stream.d.ts +3 -1
  606. package/dist/upload/stream.d.ts.map +1 -1
  607. package/dist/upload/stream.js +316 -192
  608. package/dist/upload/stream.js.map +1 -1
  609. package/dist/util/best-effort.cjs +42 -8
  610. package/dist/util/best-effort.cjs.map +1 -1
  611. package/dist/util/best-effort.d.cts +2 -1
  612. package/dist/util/best-effort.d.cts.map +1 -1
  613. package/dist/util/best-effort.d.ts +2 -1
  614. package/dist/util/best-effort.d.ts.map +1 -1
  615. package/dist/util/best-effort.js +43 -9
  616. package/dist/util/best-effort.js.map +1 -1
  617. package/dist/util/bytes.cjs +23 -0
  618. package/dist/util/bytes.cjs.map +1 -0
  619. package/dist/util/bytes.d.cts +15 -0
  620. package/dist/util/bytes.d.cts.map +1 -0
  621. package/dist/util/bytes.d.ts +15 -0
  622. package/dist/util/bytes.d.ts.map +1 -0
  623. package/dist/util/bytes.js +23 -0
  624. package/dist/util/bytes.js.map +1 -0
  625. package/dist/util/crypto.cjs +68 -0
  626. package/dist/util/crypto.cjs.map +1 -0
  627. package/dist/util/crypto.d.cts +26 -0
  628. package/dist/util/crypto.d.cts.map +1 -0
  629. package/dist/util/crypto.d.ts +26 -0
  630. package/dist/util/crypto.d.ts.map +1 -0
  631. package/dist/util/crypto.js +66 -0
  632. package/dist/util/crypto.js.map +1 -0
  633. package/dist/util/defaults.cjs +25 -9
  634. package/dist/util/defaults.cjs.map +1 -1
  635. package/dist/util/defaults.js +26 -11
  636. package/dist/util/defaults.js.map +1 -1
  637. package/dist/util/error-reason.cjs +41 -0
  638. package/dist/util/error-reason.cjs.map +1 -0
  639. package/dist/util/error-reason.d.cts +9 -0
  640. package/dist/util/error-reason.d.cts.map +1 -0
  641. package/dist/util/error-reason.d.ts +9 -0
  642. package/dist/util/error-reason.d.ts.map +1 -0
  643. package/dist/util/error-reason.js +41 -0
  644. package/dist/util/error-reason.js.map +1 -0
  645. package/dist/util/http.cjs +23 -0
  646. package/dist/util/http.cjs.map +1 -0
  647. package/dist/util/http.d.cts +13 -0
  648. package/dist/util/http.d.cts.map +1 -0
  649. package/dist/util/http.d.ts +13 -0
  650. package/dist/util/http.d.ts.map +1 -0
  651. package/dist/util/http.js +23 -0
  652. package/dist/util/http.js.map +1 -0
  653. package/dist/util/normalize.cjs +66 -7
  654. package/dist/util/normalize.cjs.map +1 -1
  655. package/dist/util/normalize.js +67 -10
  656. package/dist/util/normalize.js.map +1 -1
  657. package/dist/util/paginator.cjs +63 -14
  658. package/dist/util/paginator.cjs.map +1 -1
  659. package/dist/util/paginator.js +64 -16
  660. package/dist/util/paginator.js.map +1 -1
  661. package/dist/util/plan-ranges.cjs +47 -22
  662. package/dist/util/plan-ranges.cjs.map +1 -1
  663. package/dist/util/plan-ranges.js +48 -24
  664. package/dist/util/plan-ranges.js.map +1 -1
  665. package/dist/util/sha1.cjs +27 -0
  666. package/dist/util/sha1.cjs.map +1 -0
  667. package/dist/util/sha1.d.cts +17 -0
  668. package/dist/util/sha1.d.cts.map +1 -0
  669. package/dist/util/sha1.d.ts +17 -0
  670. package/dist/util/sha1.d.ts.map +1 -0
  671. package/dist/util/sha1.js +26 -0
  672. package/dist/util/sha1.js.map +1 -0
  673. package/dist/util/text-codec.cjs +29 -5
  674. package/dist/util/text-codec.cjs.map +1 -1
  675. package/dist/util/text-codec.js +30 -7
  676. package/dist/util/text-codec.js.map +1 -1
  677. package/dist/util/to-error.cjs +18 -4
  678. package/dist/util/to-error.cjs.map +1 -1
  679. package/dist/util/to-error.js +19 -5
  680. package/dist/util/to-error.js.map +1 -1
  681. package/dist/version.cjs +17 -5
  682. package/dist/version.cjs.map +1 -1
  683. package/dist/version.d.cts +3 -3
  684. package/dist/version.d.ts +3 -3
  685. package/dist/version.js +19 -6
  686. package/dist/version.js.map +1 -1
  687. package/package.json +19 -16
  688. package/dist/auth/index.cjs.map +0 -1
  689. package/dist/auth/index.js.map +0 -1
  690. package/dist/index.cjs.map +0 -1
  691. package/dist/index.js.map +0 -1
  692. package/dist/notifications/index.cjs.map +0 -1
  693. package/dist/notifications/index.js.map +0 -1
  694. package/dist/package.json.cjs +0 -9
  695. package/dist/package.json.cjs.map +0 -1
  696. package/dist/package.json.js +0 -9
  697. package/dist/package.json.js.map +0 -1
  698. package/dist/streams/index.cjs.map +0 -1
  699. package/dist/streams/index.js.map +0 -1
  700. package/dist/sync/index.cjs.map +0 -1
  701. package/dist/sync/index.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/raw/index.ts"],"sourcesContent":["/**\n * Low-level 1:1 bindings for every B2 native API endpoint.\n *\n * Each method on {@link RawClient} maps directly to a single `b2_*` HTTP call\n * with fully typed request and response objects. No retry logic, no URL pooling,\n * no automatic reauthorization. Use this when you need precise control over\n * individual API calls; for most use cases prefer the high-level `B2Client`.\n *\n * @packageDocumentation\n */\n\nimport type { HttpTransport } from '../http/transport.ts'\nimport type {\n ApplicationKey,\n AuthorizeAccountResponse,\n BucketInfo,\n CancelLargeFileRequest,\n CancelLargeFileResponse,\n CopyFileRequest,\n CopyPartRequest,\n CopyPartResponse,\n CreateBucketRequest,\n CreateKeyRequest,\n DeleteBucketRequest,\n DeleteFileVersionRequest,\n DeleteFileVersionResponse,\n DeleteKeyRequest,\n DownloadAuthorizationRequest,\n DownloadAuthorizationResponse,\n FileVersion,\n FinishLargeFileRequest,\n FullApplicationKey,\n GetBucketNotificationRulesRequest,\n GetBucketNotificationRulesResponse,\n GetFileInfoRequest,\n GetUploadPartUrlRequest,\n GetUploadPartUrlResponse,\n GetUploadUrlRequest,\n GetUploadUrlResponse,\n HideFileRequest,\n ListBucketsRequest,\n ListBucketsResponse,\n ListFileNamesRequest,\n ListFileNamesResponse,\n ListFileVersionsRequest,\n ListFileVersionsResponse,\n ListKeysRequest,\n ListKeysResponse,\n ListPartsRequest,\n ListPartsResponse,\n ListUnfinishedLargeFilesRequest,\n ListUnfinishedLargeFilesResponse,\n SetBucketNotificationRulesRequest,\n SetBucketNotificationRulesResponse,\n StartLargeFileRequest,\n StartLargeFileResponse,\n UpdateBucketRequest,\n UpdateFileLegalHoldRequest,\n UpdateFileLegalHoldResponse,\n UpdateFileRetentionRequest,\n UpdateFileRetentionResponse,\n} from '../types/index.ts'\nimport type { UploadFileHeaders, UploadPartHeaders, UploadPartResponse } from '../types/upload.ts'\nimport { normalizeFileVersionListSha1, normalizeFileVersionSha1 } from '../util/normalize.ts'\nimport { buildFileInfoHeaders, encodeFileName } from './encoding.ts'\n\n/** Configuration for constructing a {@link RawClient}. */\nexport interface RawClientOptions {\n /** The HTTP transport used to send requests (e.g., FetchTransport or RetryTransport). */\n readonly transport: HttpTransport\n}\n\n/**\n * Low-level client providing 1:1 bindings to all B2 native API endpoints.\n *\n * Each method maps directly to a single B2 API call. Most methods accept\n * `(apiUrl, authToken, request)` and return the JSON response. Upload and\n * download methods accept endpoint-specific parameters instead.\n */\nexport class RawClient {\n /** @internal */\n private readonly transport: HttpTransport\n\n /**\n * Creates a new RawClient with the given transport.\n * @param options - The constructor configuration.\n */\n constructor(options: RawClientOptions) {\n this.transport = options.transport\n }\n\n // --- Auth ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-authorize-account | b2_authorize_account}.\n * @param applicationKeyId - The application key ID for authentication.\n * @param applicationKey - The application key secret.\n * @param realmUrl - The B2 realm URL to authenticate against.\n *\n * @returns The authorization response with API URLs and credentials.\n */\n async authorizeAccount(\n applicationKeyId: string,\n applicationKey: string,\n realmUrl = 'https://api.backblazeb2.com',\n ): Promise<AuthorizeAccountResponse> {\n const response = await this.transport.send({\n url: `${realmUrl}/b2api/v3/b2_authorize_account`,\n method: 'GET',\n headers: {\n Authorization: `Basic ${btoa(`${applicationKeyId}:${applicationKey}`)}`,\n },\n })\n return response.json<AuthorizeAccountResponse>()\n }\n\n // --- Buckets ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-create-bucket | b2_create_bucket}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The created bucket metadata.\n */\n async createBucket(\n apiUrl: string,\n authToken: string,\n request: CreateBucketRequest,\n ): Promise<BucketInfo> {\n return this.postJson<BucketInfo>(apiUrl, authToken, 'b2_create_bucket', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-delete-bucket | b2_delete_bucket}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The deleted bucket metadata.\n */\n async deleteBucket(\n apiUrl: string,\n authToken: string,\n request: DeleteBucketRequest,\n ): Promise<BucketInfo> {\n return this.postJson<BucketInfo>(apiUrl, authToken, 'b2_delete_bucket', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-buckets | b2_list_buckets}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The list of matching buckets.\n */\n async listBuckets(\n apiUrl: string,\n authToken: string,\n request: ListBucketsRequest,\n ): Promise<ListBucketsResponse> {\n return this.postJson<ListBucketsResponse>(apiUrl, authToken, 'b2_list_buckets', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-update-bucket | b2_update_bucket}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The updated bucket metadata.\n */\n async updateBucket(\n apiUrl: string,\n authToken: string,\n request: UpdateBucketRequest,\n ): Promise<BucketInfo> {\n return this.postJson<BucketInfo>(apiUrl, authToken, 'b2_update_bucket', request)\n }\n\n // --- Files ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-upload-url | b2_get_upload_url}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The upload URL and authorization token.\n */\n async getUploadUrl(\n apiUrl: string,\n authToken: string,\n request: GetUploadUrlRequest,\n ): Promise<GetUploadUrlResponse> {\n return this.postJson<GetUploadUrlResponse>(apiUrl, authToken, 'b2_get_upload_url', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-upload-file | b2_upload_file}.\n *\n * Unlike most methods, this posts directly to the `uploadUrl` obtained\n * from {@link getUploadUrl} rather than the API URL.\n * @param uploadUrl - The upload endpoint URL.\n * @param headers - The request headers including authorization and content metadata.\n * @param body - The file data to upload.\n * @param signal - An optional abort signal for cancellation.\n *\n * @returns The uploaded file version metadata.\n */\n async uploadFile(\n uploadUrl: string,\n headers: UploadFileHeaders,\n body: BodyInit,\n signal?: AbortSignal,\n ): Promise<FileVersion> {\n const reqHeaders: Record<string, string> = {\n Authorization: headers.authorization,\n 'X-Bz-File-Name': encodeFileName(headers.fileName),\n 'Content-Type': headers.contentType,\n 'Content-Length': String(headers.contentLength),\n 'X-Bz-Content-Sha1': headers.contentSha1,\n ...buildFileInfoHeaders(headers.fileInfo),\n }\n\n if (headers.lastModifiedMillis !== undefined) {\n reqHeaders['X-Bz-Info-src_last_modified_millis'] = String(headers.lastModifiedMillis)\n }\n if (headers.contentDisposition) {\n reqHeaders['X-Bz-Info-b2-content-disposition'] = headers.contentDisposition\n }\n if (headers.contentLanguage) {\n reqHeaders['X-Bz-Info-b2-content-language'] = headers.contentLanguage\n }\n if (headers.expires) {\n reqHeaders['X-Bz-Info-b2-expires'] = headers.expires\n }\n if (headers.cacheControl) {\n reqHeaders['X-Bz-Info-b2-cache-control'] = headers.cacheControl\n }\n if (headers.contentEncoding) {\n reqHeaders['X-Bz-Info-b2-content-encoding'] = headers.contentEncoding\n }\n\n applyEncryptionHeaders(reqHeaders, headers.serverSideEncryption)\n applyRetentionHeaders(reqHeaders, headers.fileRetention)\n applyLegalHoldHeader(reqHeaders, headers.legalHold)\n\n const response = await this.transport.send({\n url: uploadUrl,\n method: 'POST',\n headers: reqHeaders,\n body,\n ...(signal !== undefined ? { signal } : {}),\n })\n return normalizeFileVersionSha1(await response.json<FileVersion>())\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-file-names | b2_list_file_names}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The list of file names and optional continuation token.\n */\n async listFileNames(\n apiUrl: string,\n authToken: string,\n request: ListFileNamesRequest,\n ): Promise<ListFileNamesResponse> {\n return normalizeFileVersionListSha1(\n await this.postJson<ListFileNamesResponse>(apiUrl, authToken, 'b2_list_file_names', request),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-file-versions | b2_list_file_versions}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The list of file versions and optional continuation token.\n */\n async listFileVersions(\n apiUrl: string,\n authToken: string,\n request: ListFileVersionsRequest,\n ): Promise<ListFileVersionsResponse> {\n return normalizeFileVersionListSha1(\n await this.postJson<ListFileVersionsResponse>(\n apiUrl,\n authToken,\n 'b2_list_file_versions',\n request,\n ),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-file-info | b2_get_file_info}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The file version metadata.\n */\n async getFileInfo(\n apiUrl: string,\n authToken: string,\n request: GetFileInfoRequest,\n ): Promise<FileVersion> {\n return normalizeFileVersionSha1(\n await this.postJson<FileVersion>(apiUrl, authToken, 'b2_get_file_info', request),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-hide-file | b2_hide_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The hidden file version metadata.\n */\n async hideFile(\n apiUrl: string,\n authToken: string,\n request: HideFileRequest,\n ): Promise<FileVersion> {\n return normalizeFileVersionSha1(\n await this.postJson<FileVersion>(apiUrl, authToken, 'b2_hide_file', request),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-delete-file-version | b2_delete_file_version}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The deleted file version identifier.\n */\n async deleteFileVersion(\n apiUrl: string,\n authToken: string,\n request: DeleteFileVersionRequest,\n ): Promise<DeleteFileVersionResponse> {\n return this.postJson<DeleteFileVersionResponse>(\n apiUrl,\n authToken,\n 'b2_delete_file_version',\n request,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-copy-file | b2_copy_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The copied file version metadata.\n */\n async copyFile(\n apiUrl: string,\n authToken: string,\n request: CopyFileRequest,\n ): Promise<FileVersion> {\n return normalizeFileVersionSha1(\n await this.postJson<FileVersion>(apiUrl, authToken, 'b2_copy_file', request),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-copy-part | b2_copy_part}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The copied part metadata.\n */\n async copyPart(\n apiUrl: string,\n authToken: string,\n request: CopyPartRequest,\n ): Promise<CopyPartResponse> {\n return this.postJson<CopyPartResponse>(apiUrl, authToken, 'b2_copy_part', request)\n }\n\n // --- Large Files ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-start-large-file | b2_start_large_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The started large file metadata with file ID.\n */\n async startLargeFile(\n apiUrl: string,\n authToken: string,\n request: StartLargeFileRequest,\n ): Promise<StartLargeFileResponse> {\n return this.postJson<StartLargeFileResponse>(apiUrl, authToken, 'b2_start_large_file', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-upload-part-url | b2_get_upload_part_url}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The upload part URL and authorization token.\n */\n async getUploadPartUrl(\n apiUrl: string,\n authToken: string,\n request: GetUploadPartUrlRequest,\n ): Promise<GetUploadPartUrlResponse> {\n return this.postJson<GetUploadPartUrlResponse>(\n apiUrl,\n authToken,\n 'b2_get_upload_part_url',\n request,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-upload-part | b2_upload_part}.\n *\n * Posts directly to the `uploadUrl` obtained from {@link getUploadPartUrl}\n * rather than the API URL.\n * @param uploadUrl - The upload endpoint URL.\n * @param headers - The request headers including authorization and content metadata.\n * @param body - The file data to upload.\n * @param signal - An optional abort signal for cancellation.\n *\n * @returns The uploaded part metadata.\n */\n async uploadPart(\n uploadUrl: string,\n headers: UploadPartHeaders,\n body: BodyInit,\n signal?: AbortSignal,\n ): Promise<UploadPartResponse> {\n const reqHeaders: Record<string, string> = {\n Authorization: headers.authorization,\n 'X-Bz-Part-Number': String(headers.partNumber),\n 'Content-Length': String(headers.contentLength),\n 'X-Bz-Content-Sha1': headers.contentSha1,\n }\n\n applyEncryptionHeaders(reqHeaders, headers.serverSideEncryption)\n\n const response = await this.transport.send({\n url: uploadUrl,\n method: 'POST',\n headers: reqHeaders,\n body,\n ...(signal !== undefined ? { signal } : {}),\n })\n return response.json<UploadPartResponse>()\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-finish-large-file | b2_finish_large_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The completed file version metadata.\n */\n async finishLargeFile(\n apiUrl: string,\n authToken: string,\n request: FinishLargeFileRequest,\n ): Promise<FileVersion> {\n return normalizeFileVersionSha1(\n await this.postJson<FileVersion>(apiUrl, authToken, 'b2_finish_large_file', request),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-cancel-large-file | b2_cancel_large_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The cancelled large file metadata.\n */\n async cancelLargeFile(\n apiUrl: string,\n authToken: string,\n request: CancelLargeFileRequest,\n ): Promise<CancelLargeFileResponse> {\n return this.postJson<CancelLargeFileResponse>(\n apiUrl,\n authToken,\n 'b2_cancel_large_file',\n request,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-unfinished-large-files | b2_list_unfinished_large_files}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The list of unfinished large files and optional continuation token.\n */\n async listUnfinishedLargeFiles(\n apiUrl: string,\n authToken: string,\n request: ListUnfinishedLargeFilesRequest,\n ): Promise<ListUnfinishedLargeFilesResponse> {\n return this.postJson<ListUnfinishedLargeFilesResponse>(\n apiUrl,\n authToken,\n 'b2_list_unfinished_large_files',\n request,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-parts | b2_list_parts}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The list of uploaded parts and optional continuation token.\n */\n async listParts(\n apiUrl: string,\n authToken: string,\n request: ListPartsRequest,\n ): Promise<ListPartsResponse> {\n return this.postJson<ListPartsResponse>(apiUrl, authToken, 'b2_list_parts', request)\n }\n\n // --- Downloads ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-download-file-by-id | b2_download_file_by_id}.\n * @param downloadUrl - The B2 download base URL.\n * @param authToken - The authorization token.\n * @param fileId - The unique identifier of the file to download.\n * @param options - Optional download parameters for range requests and cancellation.\n *\n * @returns The response headers, streaming body, and HTTP status code.\n */\n async downloadFileById(\n downloadUrl: string,\n authToken: string,\n fileId: string,\n options?: DownloadFileOptions,\n ): Promise<{\n /** Response headers containing file metadata and B2 info headers. */\n headers: Headers\n /** Streaming response body, or `null` for HEAD-like responses. */\n body: ReadableStream<Uint8Array> | null\n /** HTTP status code (200 for full content, 206 for partial content). */\n status: number\n }> {\n const headers = buildDownloadRequestHeaders(authToken, options)\n const url = appendDownloadOverrides(\n `${downloadUrl}/b2api/v3/b2_download_file_by_id?fileId=${encodeURIComponent(fileId)}`,\n options,\n )\n\n const response = await this.transport.send({\n url,\n method: options?.method ?? 'GET',\n headers,\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n })\n\n return { headers: response.headers, body: response.body, status: response.status }\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-download-file-by-name | b2_download_file_by_name}.\n * @param downloadUrl - The B2 download base URL.\n * @param authToken - The authorization token.\n * @param bucketName - The name of the bucket containing the file.\n * @param fileName - The name of the file to download.\n * @param options - Optional download parameters for range requests and cancellation.\n *\n * @returns The response headers, streaming body, and HTTP status code.\n */\n async downloadFileByName(\n downloadUrl: string,\n authToken: string,\n bucketName: string,\n fileName: string,\n options?: DownloadFileOptions,\n ): Promise<{\n /** Response headers containing file metadata and B2 info headers. */\n headers: Headers\n /** Streaming response body, or `null` for HEAD-like responses. */\n body: ReadableStream<Uint8Array> | null\n /** HTTP status code (200 for full content, 206 for partial content). */\n status: number\n }> {\n const headers = buildDownloadRequestHeaders(authToken, options)\n const url = appendDownloadOverrides(\n `${downloadUrl}/file/${encodeURIComponent(bucketName)}/${encodeFileName(fileName)}`,\n options,\n )\n\n const response = await this.transport.send({\n url,\n method: options?.method ?? 'GET',\n headers,\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n })\n\n return { headers: response.headers, body: response.body, status: response.status }\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-download-authorization | b2_get_download_authorization}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The current session authorization token.\n * @param request - The API request parameters.\n *\n * @returns The download authorization token for the specified file prefix.\n */\n async getDownloadAuthorization(\n apiUrl: string,\n authToken: string,\n request: DownloadAuthorizationRequest,\n ): Promise<DownloadAuthorizationResponse> {\n return this.postJson<DownloadAuthorizationResponse>(\n apiUrl,\n authToken,\n 'b2_get_download_authorization',\n request,\n )\n }\n\n // --- Keys ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-create-key | b2_create_key}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The newly created application key with secret.\n */\n async createKey(\n apiUrl: string,\n authToken: string,\n request: CreateKeyRequest,\n ): Promise<FullApplicationKey> {\n return this.postJson<FullApplicationKey>(apiUrl, authToken, 'b2_create_key', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-keys | b2_list_keys}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The list of application keys and optional continuation token.\n */\n async listKeys(\n apiUrl: string,\n authToken: string,\n request: ListKeysRequest,\n ): Promise<ListKeysResponse> {\n return this.postJson<ListKeysResponse>(apiUrl, authToken, 'b2_list_keys', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-delete-key | b2_delete_key}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The deleted application key metadata.\n */\n async deleteKey(\n apiUrl: string,\n authToken: string,\n request: DeleteKeyRequest,\n ): Promise<ApplicationKey> {\n return this.postJson<ApplicationKey>(apiUrl, authToken, 'b2_delete_key', request)\n }\n\n // --- Retention / Legal Hold ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-update-file-retention | b2_update_file_retention}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The updated file retention settings.\n */\n async updateFileRetention(\n apiUrl: string,\n authToken: string,\n request: UpdateFileRetentionRequest,\n ): Promise<UpdateFileRetentionResponse> {\n return this.postJson<UpdateFileRetentionResponse>(\n apiUrl,\n authToken,\n 'b2_update_file_retention',\n request,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-update-file-legal-hold | b2_update_file_legal_hold}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The updated file legal hold status.\n */\n async updateFileLegalHold(\n apiUrl: string,\n authToken: string,\n request: UpdateFileLegalHoldRequest,\n ): Promise<UpdateFileLegalHoldResponse> {\n return this.postJson<UpdateFileLegalHoldResponse>(\n apiUrl,\n authToken,\n 'b2_update_file_legal_hold',\n request,\n )\n }\n\n // --- Notifications ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-bucket-notification-rules | b2_get_bucket_notification_rules}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The configured event notification rules for the specified bucket.\n */\n async getBucketNotificationRules(\n apiUrl: string,\n authToken: string,\n request: GetBucketNotificationRulesRequest,\n ): Promise<GetBucketNotificationRulesResponse> {\n return this.postJson<GetBucketNotificationRulesResponse>(\n apiUrl,\n authToken,\n 'b2_get_bucket_notification_rules',\n request,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-set-bucket-notification-rules | b2_set_bucket_notification_rules}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The updated bucket notification rules.\n */\n async setBucketNotificationRules(\n apiUrl: string,\n authToken: string,\n request: SetBucketNotificationRulesRequest,\n ): Promise<SetBucketNotificationRulesResponse> {\n return this.postJson<SetBucketNotificationRulesResponse>(\n apiUrl,\n authToken,\n 'b2_set_bucket_notification_rules',\n request,\n )\n }\n\n // --- Internal ---\n\n /**\n * Sends a JSON POST request to the specified B2 API endpoint.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param endpoint - The B2 API endpoint name.\n * @param body - The JSON request body.\n *\n * @returns The parsed JSON response.\n */\n private async postJson<T>(\n apiUrl: string,\n authToken: string,\n endpoint: string,\n body: unknown,\n ): Promise<T> {\n const response = await this.transport.send({\n url: `${apiUrl}/b2api/v3/${endpoint}`,\n method: 'POST',\n headers: {\n Authorization: authToken,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n })\n return response.json<T>()\n }\n}\n\n// --- Header helpers ---\n\nimport { EncryptionAlgorithm, EncryptionMode, type EncryptionSetting } from '../types/encryption.ts'\nimport type { FileRetentionValue, LegalHoldValue } from '../types/lock.ts'\n\n/**\n * Applies server-side encryption headers to the request.\n * @param headers - The mutable headers object to populate.\n * @param encryption - The encryption settings, or undefined to skip.\n */\nfunction applyEncryptionHeaders(\n headers: Record<string, string>,\n encryption: EncryptionSetting | undefined,\n): void {\n if (!encryption || encryption.mode === EncryptionMode.None) return\n if (encryption.mode === EncryptionMode.SseB2) {\n headers['X-Bz-Server-Side-Encryption'] = EncryptionAlgorithm.Aes256\n } else if (encryption.mode === EncryptionMode.SseC) {\n headers['X-Bz-Server-Side-Encryption-Customer-Algorithm'] = EncryptionAlgorithm.Aes256\n headers['X-Bz-Server-Side-Encryption-Customer-Key'] = encryption.customerKey\n headers['X-Bz-Server-Side-Encryption-Customer-Key-Md5'] = encryption.customerKeyMd5\n }\n}\n\n/**\n * SSE-C decryption parameters supplied to downloads of files that were\n * uploaded with customer-managed keys.\n */\nexport interface SseCDownloadKey {\n /** Encryption algorithm. Always `EncryptionAlgorithm.Aes256` (`'AES256'`). */\n readonly algorithm: EncryptionAlgorithm\n /** Base64-encoded customer-provided decryption key. */\n readonly customerKey: string\n /** Base64-encoded MD5 digest of the decryption key. */\n readonly customerKeyMd5: string\n}\n\n/**\n * Options accepted by {@link RawClient.downloadFileById} and\n * {@link RawClient.downloadFileByName}. Mirrors the B2 native API: range +\n * SSE-C decryption headers + the documented `b2Content*` response-header\n * overrides (query-string parameters on the request URL).\n */\nexport interface DownloadFileOptions {\n /** HTTP method. Defaults to `'GET'`. Use `'HEAD'` to fetch headers without the body. */\n readonly method?: 'GET' | 'HEAD'\n /** HTTP Range header value for partial content requests. */\n readonly range?: string\n /** SSE-C decryption parameters, required if the file was uploaded with SSE-C. */\n readonly serverSideEncryption?: SseCDownloadKey\n /** Override the `Content-Disposition` header in the download response. */\n readonly b2ContentDisposition?: string\n /** Override the `Content-Language` header in the download response. */\n readonly b2ContentLanguage?: string\n /** Override the `Content-Encoding` header in the download response. */\n readonly b2ContentEncoding?: string\n /** Override the `Content-Type` header in the download response. */\n readonly b2ContentType?: string\n /** Override the `Cache-Control` header in the download response. */\n readonly b2CacheControl?: string\n /** Override the `Expires` header in the download response. */\n readonly b2Expires?: string\n /** Signal to abort the download. */\n readonly signal?: AbortSignal\n}\n\nconst DOWNLOAD_OVERRIDE_PARAMS = [\n 'b2ContentDisposition',\n 'b2ContentLanguage',\n 'b2ContentEncoding',\n 'b2ContentType',\n 'b2CacheControl',\n 'b2Expires',\n] as const\n\n/**\n * Builds the HTTP request headers for a download: Authorization, optional\n * Range, and optional SSE-C decryption headers.\n *\n * @param authToken - The B2 session authorization token.\n * @param options - Caller-supplied download options.\n *\n * @returns The header map to send with the request.\n */\nfunction buildDownloadRequestHeaders(\n authToken: string,\n options: DownloadFileOptions | undefined,\n): Record<string, string> {\n const headers: Record<string, string> = { Authorization: authToken }\n if (options?.range) headers['Range'] = options.range\n if (options?.serverSideEncryption) {\n applyEncryptionHeaders(headers, {\n mode: EncryptionMode.SseC,\n ...options.serverSideEncryption,\n })\n }\n return headers\n}\n\n/**\n * Appends the documented `b2Content*` response-header overrides to a download\n * URL as query-string parameters. B2 echoes the values into the response\n * headers so callers can control content type, disposition, and caching.\n *\n * @param url - The base download URL.\n * @param options - Caller-supplied download options.\n *\n * @returns The URL with any override parameters appended.\n */\nfunction appendDownloadOverrides(url: string, options: DownloadFileOptions | undefined): string {\n if (!options) return url\n const params: string[] = []\n for (const key of DOWNLOAD_OVERRIDE_PARAMS) {\n const value = options[key]\n if (value !== undefined) {\n params.push(`${key}=${encodeURIComponent(value)}`)\n }\n }\n if (params.length === 0) return url\n const separator = url.includes('?') ? '&' : '?'\n return `${url}${separator}${params.join('&')}`\n}\n\n/**\n * Applies file retention headers to the request.\n * @param headers - The mutable headers object to populate.\n * @param retention - The retention settings, or undefined to skip.\n */\nfunction applyRetentionHeaders(\n headers: Record<string, string>,\n retention: FileRetentionValue | undefined,\n): void {\n if (!retention) return\n if (retention.mode) {\n headers['X-Bz-File-Retention-Mode'] = retention.mode\n }\n if (retention.retainUntilTimestamp) {\n headers['X-Bz-File-Retention-Retain-Until-Timestamp'] = String(retention.retainUntilTimestamp)\n }\n}\n\n/**\n * Applies the legal hold header to the request.\n * @param headers - The mutable headers object to populate.\n * @param legalHold - The legal hold value, or undefined to skip.\n */\nfunction applyLegalHoldHeader(\n headers: Record<string, string>,\n legalHold: LegalHoldValue | undefined,\n): void {\n if (!legalHold) return\n headers['X-Bz-File-Legal-Hold'] = legalHold\n}\n\nexport {\n encodeFileName,\n decodeFileName,\n buildFileInfoHeaders,\n parseFileInfoHeaders,\n} from './encoding.ts'\n"],"names":[],"mappings":";;;;AA+EO,MAAM,UAAU;AAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjB,YAAY,SAA2B;AACrC,SAAK,YAAY,QAAQ;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,iBACJ,kBACA,gBACA,WAAW,+BACwB;AACnC,UAAM,WAAW,MAAM,KAAK,UAAU,KAAK;AAAA,MACzC,KAAK,GAAG,QAAQ;AAAA,MAChB,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,SAAS,KAAK,GAAG,gBAAgB,IAAI,cAAc,EAAE,CAAC;AAAA,MAAA;AAAA,IACvE,CACD;AACD,WAAO,SAAS,KAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,aACJ,QACA,WACA,SACqB;AACrB,WAAO,KAAK,SAAqB,QAAQ,WAAW,oBAAoB,OAAO;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,aACJ,QACA,WACA,SACqB;AACrB,WAAO,KAAK,SAAqB,QAAQ,WAAW,oBAAoB,OAAO;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,YACJ,QACA,WACA,SAC8B;AAC9B,WAAO,KAAK,SAA8B,QAAQ,WAAW,mBAAmB,OAAO;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,aACJ,QACA,WACA,SACqB;AACrB,WAAO,KAAK,SAAqB,QAAQ,WAAW,oBAAoB,OAAO;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,aACJ,QACA,WACA,SAC+B;AAC/B,WAAO,KAAK,SAA+B,QAAQ,WAAW,qBAAqB,OAAO;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,WACJ,WACA,SACA,MACA,QACsB;AACtB,UAAM,aAAqC;AAAA,MACzC,eAAe,QAAQ;AAAA,MACvB,kBAAkB,eAAe,QAAQ,QAAQ;AAAA,MACjD,gBAAgB,QAAQ;AAAA,MACxB,kBAAkB,OAAO,QAAQ,aAAa;AAAA,MAC9C,qBAAqB,QAAQ;AAAA,MAC7B,GAAG,qBAAqB,QAAQ,QAAQ;AAAA,IAAA;AAG1C,QAAI,QAAQ,uBAAuB,QAAW;AAC5C,iBAAW,oCAAoC,IAAI,OAAO,QAAQ,kBAAkB;AAAA,IACtF;AACA,QAAI,QAAQ,oBAAoB;AAC9B,iBAAW,kCAAkC,IAAI,QAAQ;AAAA,IAC3D;AACA,QAAI,QAAQ,iBAAiB;AAC3B,iBAAW,+BAA+B,IAAI,QAAQ;AAAA,IACxD;AACA,QAAI,QAAQ,SAAS;AACnB,iBAAW,sBAAsB,IAAI,QAAQ;AAAA,IAC/C;AACA,QAAI,QAAQ,cAAc;AACxB,iBAAW,4BAA4B,IAAI,QAAQ;AAAA,IACrD;AACA,QAAI,QAAQ,iBAAiB;AAC3B,iBAAW,+BAA+B,IAAI,QAAQ;AAAA,IACxD;AAEA,2BAAuB,YAAY,QAAQ,oBAAoB;AAC/D,0BAAsB,YAAY,QAAQ,aAAa;AACvD,yBAAqB,YAAY,QAAQ,SAAS;AAElD,UAAM,WAAW,MAAM,KAAK,UAAU,KAAK;AAAA,MACzC,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,MACT;AAAA,MACA,GAAI,WAAW,SAAY,EAAE,WAAW,CAAA;AAAA,IAAC,CAC1C;AACD,WAAO,yBAAyB,MAAM,SAAS,MAAmB;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,cACJ,QACA,WACA,SACgC;AAChC,WAAO;AAAA,MACL,MAAM,KAAK,SAAgC,QAAQ,WAAW,sBAAsB,OAAO;AAAA,IAAA;AAAA,EAE/F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,iBACJ,QACA,WACA,SACmC;AACnC,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IACF;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,YACJ,QACA,WACA,SACsB;AACtB,WAAO;AAAA,MACL,MAAM,KAAK,SAAsB,QAAQ,WAAW,oBAAoB,OAAO;AAAA,IAAA;AAAA,EAEnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,SACJ,QACA,WACA,SACsB;AACtB,WAAO;AAAA,MACL,MAAM,KAAK,SAAsB,QAAQ,WAAW,gBAAgB,OAAO;AAAA,IAAA;AAAA,EAE/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,kBACJ,QACA,WACA,SACoC;AACpC,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,SACJ,QACA,WACA,SACsB;AACtB,WAAO;AAAA,MACL,MAAM,KAAK,SAAsB,QAAQ,WAAW,gBAAgB,OAAO;AAAA,IAAA;AAAA,EAE/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,SACJ,QACA,WACA,SAC2B;AAC3B,WAAO,KAAK,SAA2B,QAAQ,WAAW,gBAAgB,OAAO;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,eACJ,QACA,WACA,SACiC;AACjC,WAAO,KAAK,SAAiC,QAAQ,WAAW,uBAAuB,OAAO;AAAA,EAChG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,iBACJ,QACA,WACA,SACmC;AACnC,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,WACJ,WACA,SACA,MACA,QAC6B;AAC7B,UAAM,aAAqC;AAAA,MACzC,eAAe,QAAQ;AAAA,MACvB,oBAAoB,OAAO,QAAQ,UAAU;AAAA,MAC7C,kBAAkB,OAAO,QAAQ,aAAa;AAAA,MAC9C,qBAAqB,QAAQ;AAAA,IAAA;AAG/B,2BAAuB,YAAY,QAAQ,oBAAoB;AAE/D,UAAM,WAAW,MAAM,KAAK,UAAU,KAAK;AAAA,MACzC,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,SAAS;AAAA,MACT;AAAA,MACA,GAAI,WAAW,SAAY,EAAE,WAAW,CAAA;AAAA,IAAC,CAC1C;AACD,WAAO,SAAS,KAAA;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBACJ,QACA,WACA,SACsB;AACtB,WAAO;AAAA,MACL,MAAM,KAAK,SAAsB,QAAQ,WAAW,wBAAwB,OAAO;AAAA,IAAA;AAAA,EAEvF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBACJ,QACA,WACA,SACkC;AAClC,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,yBACJ,QACA,WACA,SAC2C;AAC3C,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,UACJ,QACA,WACA,SAC4B;AAC5B,WAAO,KAAK,SAA4B,QAAQ,WAAW,iBAAiB,OAAO;AAAA,EACrF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,iBACJ,aACA,WACA,QACA,SAQC;AACD,UAAM,UAAU,4BAA4B,WAAW,OAAO;AAC9D,UAAM,MAAM;AAAA,MACV,GAAG,WAAW,2CAA2C,mBAAmB,MAAM,CAAC;AAAA,MACnF;AAAA,IAAA;AAGF,UAAM,WAAW,MAAM,KAAK,UAAU,KAAK;AAAA,MACzC;AAAA,MACA,QAAQ,SAAS,UAAU;AAAA,MAC3B;AAAA,MACA,GAAI,SAAS,WAAW,SAAY,EAAE,QAAQ,QAAQ,WAAW,CAAA;AAAA,IAAC,CACnE;AAED,WAAO,EAAE,SAAS,SAAS,SAAS,MAAM,SAAS,MAAM,QAAQ,SAAS,OAAA;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,mBACJ,aACA,WACA,YACA,UACA,SAQC;AACD,UAAM,UAAU,4BAA4B,WAAW,OAAO;AAC9D,UAAM,MAAM;AAAA,MACV,GAAG,WAAW,SAAS,mBAAmB,UAAU,CAAC,IAAI,eAAe,QAAQ,CAAC;AAAA,MACjF;AAAA,IAAA;AAGF,UAAM,WAAW,MAAM,KAAK,UAAU,KAAK;AAAA,MACzC;AAAA,MACA,QAAQ,SAAS,UAAU;AAAA,MAC3B;AAAA,MACA,GAAI,SAAS,WAAW,SAAY,EAAE,QAAQ,QAAQ,WAAW,CAAA;AAAA,IAAC,CACnE;AAED,WAAO,EAAE,SAAS,SAAS,SAAS,MAAM,SAAS,MAAM,QAAQ,SAAS,OAAA;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,yBACJ,QACA,WACA,SACwC;AACxC,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,UACJ,QACA,WACA,SAC6B;AAC7B,WAAO,KAAK,SAA6B,QAAQ,WAAW,iBAAiB,OAAO;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,SACJ,QACA,WACA,SAC2B;AAC3B,WAAO,KAAK,SAA2B,QAAQ,WAAW,gBAAgB,OAAO;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,UACJ,QACA,WACA,SACyB;AACzB,WAAO,KAAK,SAAyB,QAAQ,WAAW,iBAAiB,OAAO;AAAA,EAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,oBACJ,QACA,WACA,SACsC;AACtC,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,oBACJ,QACA,WACA,SACsC;AACtC,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,2BACJ,QACA,WACA,SAC6C;AAC7C,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,2BACJ,QACA,WACA,SAC6C;AAC7C,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAc,SACZ,QACA,WACA,UACA,MACY;AACZ,UAAM,WAAW,MAAM,KAAK,UAAU,KAAK;AAAA,MACzC,KAAK,GAAG,MAAM,aAAa,QAAQ;AAAA,MACnC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe;AAAA,QACf,gBAAgB;AAAA,MAAA;AAAA,MAElB,MAAM,KAAK,UAAU,IAAI;AAAA,IAAA,CAC1B;AACD,WAAO,SAAS,KAAA;AAAA,EAClB;AACF;AAYA,SAAS,uBACP,SACA,YACM;AACN,MAAI,CAAC,cAAc,WAAW,SAAS,eAAe,KAAM;AAC5D,MAAI,WAAW,SAAS,eAAe,OAAO;AAC5C,YAAQ,6BAA6B,IAAI,oBAAoB;AAAA,EAC/D,WAAW,WAAW,SAAS,eAAe,MAAM;AAClD,YAAQ,gDAAgD,IAAI,oBAAoB;AAChF,YAAQ,0CAA0C,IAAI,WAAW;AACjE,YAAQ,8CAA8C,IAAI,WAAW;AAAA,EACvE;AACF;AA4CA,MAAM,2BAA2B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAWA,SAAS,4BACP,WACA,SACwB;AACxB,QAAM,UAAkC,EAAE,eAAe,UAAA;AACzD,MAAI,SAAS,MAAO,SAAQ,OAAO,IAAI,QAAQ;AAC/C,MAAI,SAAS,sBAAsB;AACjC,2BAAuB,SAAS;AAAA,MAC9B,MAAM,eAAe;AAAA,MACrB,GAAG,QAAQ;AAAA,IAAA,CACZ;AAAA,EACH;AACA,SAAO;AACT;AAYA,SAAS,wBAAwB,KAAa,SAAkD;AAC9F,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,SAAmB,CAAA;AACzB,aAAW,OAAO,0BAA0B;AAC1C,UAAM,QAAQ,QAAQ,GAAG;AACzB,QAAI,UAAU,QAAW;AACvB,aAAO,KAAK,GAAG,GAAG,IAAI,mBAAmB,KAAK,CAAC,EAAE;AAAA,IACnD;AAAA,EACF;AACA,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,YAAY,IAAI,SAAS,GAAG,IAAI,MAAM;AAC5C,SAAO,GAAG,GAAG,GAAG,SAAS,GAAG,OAAO,KAAK,GAAG,CAAC;AAC9C;AAOA,SAAS,sBACP,SACA,WACM;AACN,MAAI,CAAC,UAAW;AAChB,MAAI,UAAU,MAAM;AAClB,YAAQ,0BAA0B,IAAI,UAAU;AAAA,EAClD;AACA,MAAI,UAAU,sBAAsB;AAClC,YAAQ,4CAA4C,IAAI,OAAO,UAAU,oBAAoB;AAAA,EAC/F;AACF;AAOA,SAAS,qBACP,SACA,WACM;AACN,MAAI,CAAC,UAAW;AAChB,UAAQ,sBAAsB,IAAI;AACpC;"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/raw/index.ts"],"sourcesContent":["/**\n * Low-level 1:1 bindings for every B2 native API endpoint.\n *\n * Each method on {@link RawClient} maps directly to a single `b2_*` HTTP call\n * with fully typed request and response objects. No retry logic, no URL pooling,\n * no automatic reauthorization. Use this when you need precise control over\n * individual API calls; for most use cases prefer the high-level `B2Client`.\n *\n * @packageDocumentation\n */\n\nimport { assertSecureRealmUrl } from '../auth/realms.ts'\nimport { FinishLargeFileResponseBodyError, UploadResponseBodyError } from '../errors/index.ts'\nimport type { RetryOptions } from '../http/retry.ts'\nimport type { HttpTransport } from '../http/transport.ts'\nimport type {\n AllowedBucket,\n ApplicationKey,\n AuthorizeAccountResponse,\n BucketId,\n BucketInfo,\n CancelLargeFileRequest,\n CancelLargeFileResponse,\n CopyFileRequest,\n CopyPartRequest,\n CopyPartResponse,\n CreateBucketRequest,\n CreateKeyRequest,\n DeleteBucketRequest,\n DeleteFileVersionRequest,\n DeleteFileVersionResponse,\n DeleteKeyRequest,\n DownloadAuthorizationRequest,\n DownloadAuthorizationResponse,\n FileVersion,\n FinishLargeFileRequest,\n FullApplicationKey,\n GetBucketNotificationRulesRequest,\n GetBucketNotificationRulesResponse,\n GetFileInfoRequest,\n GetUploadPartUrlRequest,\n GetUploadPartUrlResponse,\n GetUploadUrlRequest,\n GetUploadUrlResponse,\n HideFileRequest,\n ListBucketsRequest,\n ListBucketsResponse,\n ListFileNamesRequest,\n ListFileNamesResponse,\n ListFileVersionsRequest,\n ListFileVersionsResponse,\n ListKeysRequest,\n ListKeysResponse,\n ListPartsRequest,\n ListPartsResponse,\n ListUnfinishedLargeFilesRequest,\n ListUnfinishedLargeFilesResponse,\n SetBucketNotificationRulesRequest,\n SetBucketNotificationRulesResponse,\n StartLargeFileRequest,\n StartLargeFileResponse,\n UpdateBucketRequest,\n UpdateFileLegalHoldRequest,\n UpdateFileLegalHoldResponse,\n UpdateFileRetentionRequest,\n UpdateFileRetentionResponse,\n} from '../types/index.ts'\nimport type { UploadFileHeaders, UploadPartHeaders, UploadPartResponse } from '../types/upload.ts'\nimport { normalizeFileVersionListSha1, normalizeFileVersionSha1 } from '../util/normalize.ts'\nimport { buildFileInfoHeaders, encodeFileName } from './encoding.ts'\n\n/** Configuration for constructing a {@link RawClient}. */\nexport interface RawClientOptions {\n /** The HTTP transport used to send requests (e.g., FetchTransport or RetryTransport). */\n readonly transport: HttpTransport\n}\n\n/** Optional request controls for {@link RawClient.listFileNames}. */\nexport type ListFileNamesOptions = RawRequestOptions\n\n/** Optional request controls for {@link RawClient.listFileVersions}. */\nexport type ListFileVersionsOptions = RawRequestOptions\n\n/** Optional controls for raw JSON API requests. */\nexport interface RawRequestOptions {\n /** Abort signal for cancelling the request. */\n readonly signal?: AbortSignal\n /** Per-request retry override. */\n readonly retry?: Partial<RetryOptions>\n}\n\n/**\n * @deprecated Use {@link RawRequestOptions}.\n */\nexport type JsonPostOptions = RawRequestOptions\n\n/** Optional request controls for {@link RawClient.finishLargeFile}. */\nexport type FinishLargeFileOptions = RawRequestOptions\n\n/** Optional request controls for {@link RawClient.copyPart}. */\nexport type CopyPartOptions = RawRequestOptions\n\n/** Optional request controls for {@link RawClient.startLargeFile}. */\nexport type StartLargeFileOptions = RawRequestOptions\n\n/** Optional request controls for {@link RawClient.uploadFile}. */\nexport type UploadFileOptions = RawRequestOptions\n\n/** Optional request controls for {@link RawClient.uploadPart}. */\nexport type UploadPartOptions = RawRequestOptions\n\nfunction normalizeRawRequestOptions(\n optionsOrSignal?: RawRequestOptions | AbortSignal,\n retry?: Partial<RetryOptions>,\n): RawRequestOptions | undefined {\n if (optionsOrSignal === undefined) {\n return retry === undefined ? undefined : { retry }\n }\n if (isAbortSignal(optionsOrSignal)) {\n return {\n signal: optionsOrSignal,\n ...(retry !== undefined ? { retry } : {}),\n }\n }\n return retry === undefined ? optionsOrSignal : { ...optionsOrSignal, retry }\n}\n\nfunction isAbortSignal(value: unknown): value is AbortSignal {\n // Back-compat only: legacy upload-URL overloads accepted an AbortSignal as\n // the fourth positional argument. Prefer the RawRequestOptions bag.\n return (\n typeof value === 'object' &&\n value !== null &&\n 'aborted' in value &&\n typeof (value as AbortSignal).addEventListener === 'function'\n )\n}\n\nfunction normalizeCreateKeyRequest(request: CreateKeyRequest): CreateKeyRequest {\n const { bucketId, ...withoutDeprecatedBucketId } = request\n if (bucketId !== undefined && withoutDeprecatedBucketId.bucketIds !== undefined) {\n throw new TypeError('createKey accepts either bucketIds or deprecated bucketId, not both')\n }\n if (bucketId === undefined) {\n return withoutDeprecatedBucketId\n }\n return { ...withoutDeprecatedBucketId, bucketIds: [bucketId] }\n}\n\nfunction singleBucketId(bucketIds: readonly BucketId[] | null): BucketId | null {\n return bucketIds?.length === 1 ? (bucketIds[0] ?? null) : null\n}\n\nfunction normalizeKeyResponse<T extends { readonly bucketIds: readonly BucketId[] | null }>(\n key: T,\n): T & { readonly bucketId: BucketId | null } {\n return { ...key, bucketId: singleBucketId(key.bucketIds) }\n}\n\ntype NormalizedAllowedInfo = AuthorizeAccountResponse['apiInfo']['storageApi']['allowed']\ntype NormalizedStorageApiInfo = AuthorizeAccountResponse['apiInfo']['storageApi']\n\ninterface WireAllowedInfo {\n readonly capabilities?: NormalizedAllowedInfo['capabilities']\n readonly buckets?: readonly AllowedBucket[] | null\n readonly bucketId?: BucketId | null\n readonly bucketName?: string | null\n readonly namePrefix?: string | null\n}\n\ntype WireStorageApiInfo = Omit<\n NormalizedStorageApiInfo,\n 'allowed' | 'bucketId' | 'bucketName' | 'infoType' | 'namePrefix'\n> & {\n readonly allowed?: WireAllowedInfo\n readonly capabilities?: NormalizedAllowedInfo['capabilities']\n readonly bucketId?: BucketId | null\n readonly bucketName?: string | null\n readonly infoType?: 'storageApi'\n readonly namePrefix?: string | null\n}\n\ntype WireAuthorizeAccountResponse = Omit<AuthorizeAccountResponse, 'apiInfo'> & {\n readonly apiInfo: Omit<AuthorizeAccountResponse['apiInfo'], 'storageApi'> & {\n readonly storageApi: WireStorageApiInfo\n }\n}\n\nfunction normalizeAllowedBuckets(storageApi: WireStorageApiInfo): readonly AllowedBucket[] | null {\n const allowed = storageApi.allowed\n if (allowed?.buckets !== undefined) {\n return allowed.buckets === null ? null : allowed.buckets.map((bucket) => ({ ...bucket }))\n }\n const bucketId = allowed?.bucketId ?? storageApi.bucketId ?? null\n if (bucketId === null) return null\n return [{ id: bucketId, name: allowed?.bucketName ?? storageApi.bucketName ?? null }]\n}\n\nfunction normalizeAuthorizeAccountResponse(\n response: WireAuthorizeAccountResponse,\n): AuthorizeAccountResponse {\n const storageApi = response.apiInfo.storageApi\n const allowed = storageApi.allowed\n const buckets = normalizeAllowedBuckets(storageApi)\n const singleBucket = buckets?.length === 1 ? buckets[0] : undefined\n const bucketId = singleBucket?.id ?? null\n const bucketName = singleBucket?.name ?? null\n const namePrefix = allowed?.namePrefix ?? storageApi.namePrefix ?? null\n const capabilities = allowed?.capabilities ?? storageApi.capabilities ?? []\n const { allowed: _wireAllowed, capabilities: _legacyCapabilities, ...storageApiBase } = storageApi\n\n return {\n ...response,\n apiInfo: {\n ...response.apiInfo,\n storageApi: {\n ...storageApiBase,\n bucketId,\n bucketName,\n downloadUrl: storageApi.downloadUrl,\n infoType: 'storageApi',\n namePrefix,\n allowed: {\n ...(allowed ?? {}),\n capabilities,\n buckets,\n bucketId,\n bucketName,\n namePrefix,\n },\n },\n },\n }\n}\n\nfunction uploadResponseBodyError(\n err: unknown,\n signal: AbortSignal | undefined,\n): UploadResponseBodyError {\n if (signal?.aborted === true) {\n throw signal.reason ?? new DOMException('Aborted', 'AbortError')\n }\n const message = err instanceof Error ? err.message : 'Upload response body could not be read'\n return new UploadResponseBodyError(message, { cause: err })\n}\n\n/**\n * Low-level client providing 1:1 bindings to all B2 native API endpoints.\n *\n * Each method maps directly to a single B2 API call. Most methods accept\n * `(apiUrl, authToken, request)` and return the JSON response. Upload and\n * download methods accept endpoint-specific parameters instead.\n */\nexport class RawClient {\n /** @internal */\n private readonly transport: HttpTransport\n\n /**\n * Creates a new RawClient with the given transport.\n * @param options - The constructor configuration.\n */\n constructor(options: RawClientOptions) {\n this.transport = options.transport\n }\n\n // --- Auth ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-authorize-account | b2_authorize_account}.\n * @param applicationKeyId - The application key ID for authentication.\n * @param applicationKey - The application key secret.\n * @param realmUrl - The B2 realm URL to authenticate against.\n *\n * @returns The authorization response with API URLs and credentials.\n */\n async authorizeAccount(\n applicationKeyId: string,\n applicationKey: string,\n realmUrl = 'https://api.backblazeb2.com',\n ): Promise<AuthorizeAccountResponse> {\n assertSecureRealmUrl(realmUrl)\n const response = await this.transport.send({\n url: `${realmUrl}/b2api/v4/b2_authorize_account`,\n method: 'GET',\n headers: {\n Authorization: `Basic ${btoa(`${applicationKeyId}:${applicationKey}`)}`,\n },\n })\n return normalizeAuthorizeAccountResponse(await response.json<WireAuthorizeAccountResponse>())\n }\n\n // --- Buckets ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-create-bucket | b2_create_bucket}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The created bucket metadata.\n */\n async createBucket(\n apiUrl: string,\n authToken: string,\n request: CreateBucketRequest,\n ): Promise<BucketInfo> {\n return this.postJson<BucketInfo>(apiUrl, authToken, 'b2_create_bucket', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-delete-bucket | b2_delete_bucket}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The deleted bucket metadata.\n */\n async deleteBucket(\n apiUrl: string,\n authToken: string,\n request: DeleteBucketRequest,\n ): Promise<BucketInfo> {\n return this.postJson<BucketInfo>(apiUrl, authToken, 'b2_delete_bucket', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-buckets | b2_list_buckets}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The list of matching buckets.\n */\n async listBuckets(\n apiUrl: string,\n authToken: string,\n request: ListBucketsRequest,\n ): Promise<ListBucketsResponse> {\n return this.postJson<ListBucketsResponse>(apiUrl, authToken, 'b2_list_buckets', request)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-update-bucket | b2_update_bucket}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The updated bucket metadata.\n */\n async updateBucket(\n apiUrl: string,\n authToken: string,\n request: UpdateBucketRequest,\n ): Promise<BucketInfo> {\n return this.postJson<BucketInfo>(apiUrl, authToken, 'b2_update_bucket', request)\n }\n\n // --- Files ---\n\n /**\n * Calls `b2_get_upload_url` with legacy positional request controls.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param signal - Optional abort signal for cancellation.\n * @param retry - Optional per-request retry override.\n *\n * @returns The upload URL and authorization token.\n *\n * @deprecated Use the options-bag overload: `getUploadUrl(apiUrl, authToken, request, { signal, retry })`.\n */\n async getUploadUrl(\n apiUrl: string,\n authToken: string,\n request: GetUploadUrlRequest,\n signal?: AbortSignal,\n retry?: Partial<RetryOptions>,\n ): Promise<GetUploadUrlResponse>\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-upload-url | b2_get_upload_url}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as cancellation and retry overrides.\n *\n * @returns The upload URL and authorization token.\n */\n async getUploadUrl(\n apiUrl: string,\n authToken: string,\n request: GetUploadUrlRequest,\n options?: RawRequestOptions,\n ): Promise<GetUploadUrlResponse>\n /**\n * Implementation for both upload URL request-control signatures.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param optionsOrSignal - Options bag or legacy abort signal.\n * @param retry - Optional legacy per-request retry override.\n *\n * @returns The upload URL and authorization token.\n */\n async getUploadUrl(\n apiUrl: string,\n authToken: string,\n request: GetUploadUrlRequest,\n optionsOrSignal?: RawRequestOptions | AbortSignal,\n retry?: Partial<RetryOptions>,\n ): Promise<GetUploadUrlResponse> {\n return this.postJson<GetUploadUrlResponse>(\n apiUrl,\n authToken,\n 'b2_get_upload_url',\n request,\n normalizeRawRequestOptions(optionsOrSignal, retry),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-upload-file | b2_upload_file}.\n *\n * Unlike most methods, this posts directly to the `uploadUrl` obtained\n * from {@link getUploadUrl} rather than the API URL.\n * @param uploadUrl - The upload endpoint URL.\n * @param headers - The request headers including authorization and content metadata.\n * @param body - The file data to upload.\n * @param signal - Optional legacy abort signal for cancellation.\n * @param retry - Optional legacy per-request retry override.\n *\n * @returns The uploaded file version metadata.\n *\n * @deprecated Use the options-bag overload: `uploadFile(uploadUrl, headers, body, { signal, retry })`.\n */\n async uploadFile(\n uploadUrl: string,\n headers: UploadFileHeaders,\n body: BodyInit,\n signal?: AbortSignal,\n retry?: Partial<RetryOptions>,\n ): Promise<FileVersion>\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-upload-file | b2_upload_file}.\n *\n * Unlike most methods, this posts directly to the `uploadUrl` obtained\n * from {@link getUploadUrl} rather than the API URL.\n * @param uploadUrl - The upload endpoint URL.\n * @param headers - The request headers including authorization and content metadata.\n * @param body - The file data to upload.\n * @param options - Optional request controls such as cancellation and retry overrides.\n *\n * @returns The uploaded file version metadata.\n */\n async uploadFile(\n uploadUrl: string,\n headers: UploadFileHeaders,\n body: BodyInit,\n options?: UploadFileOptions,\n ): Promise<FileVersion>\n /**\n * Implementation for both upload-file request-control signatures.\n * @param uploadUrl - The upload endpoint URL.\n * @param headers - The request headers including authorization and content metadata.\n * @param body - The file data to upload.\n * @param optionsOrSignal - Options bag or legacy abort signal.\n * @param retry - Optional legacy per-request retry override.\n *\n * @returns The uploaded file version metadata.\n */\n async uploadFile(\n uploadUrl: string,\n headers: UploadFileHeaders,\n body: BodyInit,\n optionsOrSignal?: UploadFileOptions | AbortSignal,\n retry?: Partial<RetryOptions>,\n ): Promise<FileVersion> {\n const options = normalizeRawRequestOptions(optionsOrSignal, retry)\n const reqHeaders: Record<string, string> = {\n Authorization: headers.authorization,\n 'X-Bz-File-Name': encodeFileName(headers.fileName),\n 'Content-Type': headers.contentType,\n 'Content-Length': String(headers.contentLength),\n 'X-Bz-Content-Sha1': headers.contentSha1,\n ...buildFileInfoHeaders(headers.fileInfo),\n }\n\n if (headers.lastModifiedMillis !== undefined) {\n reqHeaders['X-Bz-Info-src_last_modified_millis'] = String(headers.lastModifiedMillis)\n }\n if (headers.contentDisposition) {\n reqHeaders['X-Bz-Info-b2-content-disposition'] = headers.contentDisposition\n }\n if (headers.contentLanguage) {\n reqHeaders['X-Bz-Info-b2-content-language'] = headers.contentLanguage\n }\n if (headers.expires) {\n reqHeaders['X-Bz-Info-b2-expires'] = headers.expires\n }\n if (headers.cacheControl) {\n reqHeaders['X-Bz-Info-b2-cache-control'] = headers.cacheControl\n }\n if (headers.contentEncoding) {\n reqHeaders['X-Bz-Info-b2-content-encoding'] = headers.contentEncoding\n }\n\n applyEncryptionHeaders(reqHeaders, headers.serverSideEncryption)\n applyRetentionHeaders(reqHeaders, headers.fileRetention)\n applyLegalHoldHeader(reqHeaders, headers.legalHold)\n\n const response = await this.transport.send({\n url: uploadUrl,\n method: 'POST',\n headers: reqHeaders,\n body,\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n ...(options?.retry !== undefined ? { retry: options.retry } : {}),\n })\n try {\n return normalizeFileVersionSha1(await response.json<FileVersion>())\n } catch (err) {\n throw uploadResponseBodyError(err, options?.signal)\n }\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-file-names | b2_list_file_names}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as an abort signal.\n *\n * @returns The list of file names and optional continuation token.\n */\n async listFileNames(\n apiUrl: string,\n authToken: string,\n request: ListFileNamesRequest,\n options?: ListFileNamesOptions,\n ): Promise<ListFileNamesResponse> {\n return normalizeFileVersionListSha1(\n await this.postJson<ListFileNamesResponse>(\n apiUrl,\n authToken,\n 'b2_list_file_names',\n request,\n options,\n ),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-file-versions | b2_list_file_versions}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as an abort signal.\n *\n * @returns The list of file versions and optional continuation token.\n */\n async listFileVersions(\n apiUrl: string,\n authToken: string,\n request: ListFileVersionsRequest,\n options?: ListFileVersionsOptions,\n ): Promise<ListFileVersionsResponse> {\n return normalizeFileVersionListSha1(\n await this.postJson<ListFileVersionsResponse>(\n apiUrl,\n authToken,\n 'b2_list_file_versions',\n request,\n options,\n ),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-file-info | b2_get_file_info}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The file version metadata.\n */\n async getFileInfo(\n apiUrl: string,\n authToken: string,\n request: GetFileInfoRequest,\n ): Promise<FileVersion> {\n return normalizeFileVersionSha1(\n await this.postJson<FileVersion>(apiUrl, authToken, 'b2_get_file_info', request),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-hide-file | b2_hide_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as an abort signal.\n *\n * @returns The hidden file version metadata.\n */\n async hideFile(\n apiUrl: string,\n authToken: string,\n request: HideFileRequest,\n options?: { readonly signal?: AbortSignal },\n ): Promise<FileVersion> {\n return normalizeFileVersionSha1(\n await this.postJson<FileVersion>(apiUrl, authToken, 'b2_hide_file', request, options),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-delete-file-version | b2_delete_file_version}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as an abort signal.\n *\n * @returns The deleted file version identifier.\n */\n async deleteFileVersion(\n apiUrl: string,\n authToken: string,\n request: DeleteFileVersionRequest,\n options?: { readonly signal?: AbortSignal },\n ): Promise<DeleteFileVersionResponse> {\n return this.postJson<DeleteFileVersionResponse>(\n apiUrl,\n authToken,\n 'b2_delete_file_version',\n request,\n options,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-copy-file | b2_copy_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as an abort signal.\n *\n * @returns The copied file version metadata.\n */\n async copyFile(\n apiUrl: string,\n authToken: string,\n request: CopyFileRequest,\n options?: RawRequestOptions,\n ): Promise<FileVersion> {\n return normalizeFileVersionSha1(\n await this.postJson<FileVersion>(apiUrl, authToken, 'b2_copy_file', request, options),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-copy-part | b2_copy_part}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional abort and retry controls.\n *\n * @returns The copied part metadata.\n */\n async copyPart(\n apiUrl: string,\n authToken: string,\n request: CopyPartRequest,\n options?: CopyPartOptions,\n ): Promise<CopyPartResponse> {\n return this.postJson<CopyPartResponse>(apiUrl, authToken, 'b2_copy_part', request, options)\n }\n\n // --- Large Files ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-start-large-file | b2_start_large_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional abort and retry controls.\n *\n * @returns The started large file metadata with file ID.\n */\n async startLargeFile(\n apiUrl: string,\n authToken: string,\n request: StartLargeFileRequest,\n options?: StartLargeFileOptions,\n ): Promise<StartLargeFileResponse> {\n return this.postJson<StartLargeFileResponse>(\n apiUrl,\n authToken,\n 'b2_start_large_file',\n request,\n options,\n )\n }\n\n /**\n * Calls `b2_get_upload_part_url` with legacy positional request controls.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param signal - Optional abort signal for cancellation.\n * @param retry - Optional per-request retry override.\n *\n * @returns The upload part URL and authorization token.\n *\n * @deprecated Use the options-bag overload: `getUploadPartUrl(apiUrl, authToken, request, { signal, retry })`.\n */\n async getUploadPartUrl(\n apiUrl: string,\n authToken: string,\n request: GetUploadPartUrlRequest,\n signal?: AbortSignal,\n retry?: Partial<RetryOptions>,\n ): Promise<GetUploadPartUrlResponse>\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-upload-part-url | b2_get_upload_part_url}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as cancellation and retry overrides.\n *\n * @returns The upload part URL and authorization token.\n */\n async getUploadPartUrl(\n apiUrl: string,\n authToken: string,\n request: GetUploadPartUrlRequest,\n options?: RawRequestOptions,\n ): Promise<GetUploadPartUrlResponse>\n /**\n * Implementation for both upload part URL request-control signatures.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param optionsOrSignal - Options bag or legacy abort signal.\n * @param retry - Optional legacy per-request retry override.\n *\n * @returns The upload part URL and authorization token.\n */\n async getUploadPartUrl(\n apiUrl: string,\n authToken: string,\n request: GetUploadPartUrlRequest,\n optionsOrSignal?: RawRequestOptions | AbortSignal,\n retry?: Partial<RetryOptions>,\n ): Promise<GetUploadPartUrlResponse> {\n return this.postJson<GetUploadPartUrlResponse>(\n apiUrl,\n authToken,\n 'b2_get_upload_part_url',\n request,\n normalizeRawRequestOptions(optionsOrSignal, retry),\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-upload-part | b2_upload_part}.\n *\n * Posts directly to the `uploadUrl` obtained from {@link getUploadPartUrl}\n * rather than the API URL.\n * @param uploadUrl - The upload endpoint URL.\n * @param headers - The request headers including authorization and content metadata.\n * @param body - The file data to upload.\n * @param signal - Optional legacy abort signal for cancellation.\n * @param retry - Optional legacy per-request retry override.\n *\n * @returns The uploaded part metadata.\n *\n * @deprecated Use the options-bag overload: `uploadPart(uploadUrl, headers, body, { signal, retry })`.\n */\n async uploadPart(\n uploadUrl: string,\n headers: UploadPartHeaders,\n body: BodyInit,\n signal?: AbortSignal,\n retry?: Partial<RetryOptions>,\n ): Promise<UploadPartResponse>\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-upload-part | b2_upload_part}.\n *\n * Posts directly to the `uploadUrl` obtained from {@link getUploadPartUrl}\n * rather than the API URL.\n * @param uploadUrl - The upload endpoint URL.\n * @param headers - The request headers including authorization and content metadata.\n * @param body - The file data to upload.\n * @param options - Optional request controls such as cancellation and retry overrides.\n *\n * @returns The uploaded part metadata.\n */\n async uploadPart(\n uploadUrl: string,\n headers: UploadPartHeaders,\n body: BodyInit,\n options?: UploadPartOptions,\n ): Promise<UploadPartResponse>\n /**\n * Implementation for both upload-part request-control signatures.\n * @param uploadUrl - The upload endpoint URL.\n * @param headers - The request headers including authorization and content metadata.\n * @param body - The file data to upload.\n * @param optionsOrSignal - Options bag or legacy abort signal.\n * @param retry - Optional legacy per-request retry override.\n *\n * @returns The uploaded part metadata.\n */\n async uploadPart(\n uploadUrl: string,\n headers: UploadPartHeaders,\n body: BodyInit,\n optionsOrSignal?: UploadPartOptions | AbortSignal,\n retry?: Partial<RetryOptions>,\n ): Promise<UploadPartResponse> {\n const options = normalizeRawRequestOptions(optionsOrSignal, retry)\n const reqHeaders: Record<string, string> = {\n Authorization: headers.authorization,\n 'X-Bz-Part-Number': String(headers.partNumber),\n 'Content-Length': String(headers.contentLength),\n 'X-Bz-Content-Sha1': headers.contentSha1,\n }\n\n applyEncryptionHeaders(reqHeaders, headers.serverSideEncryption)\n\n const response = await this.transport.send({\n url: uploadUrl,\n method: 'POST',\n headers: reqHeaders,\n body,\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n ...(options?.retry !== undefined ? { retry: options.retry } : {}),\n })\n try {\n return await response.json<UploadPartResponse>()\n } catch (err) {\n throw uploadResponseBodyError(err, options?.signal)\n }\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-finish-large-file | b2_finish_large_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional abort and retry controls.\n *\n * @returns The completed file version metadata.\n */\n async finishLargeFile(\n apiUrl: string,\n authToken: string,\n request: FinishLargeFileRequest,\n options?: FinishLargeFileOptions,\n ): Promise<FileVersion> {\n const response = await this.transport.send({\n url: `${apiUrl}/b2api/v3/b2_finish_large_file`,\n method: 'POST',\n headers: {\n Authorization: authToken,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(request),\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n ...(options?.retry !== undefined ? { retry: options.retry } : {}),\n })\n\n let fileVersion: FileVersion\n try {\n fileVersion = await response.json<FileVersion>()\n } catch (err) {\n throw new FinishLargeFileResponseBodyError(\n err instanceof Error ? err.message : 'Finish large file response body could not be read',\n { cause: err, fileId: request.fileId },\n )\n }\n return normalizeFileVersionSha1(fileVersion)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-cancel-large-file | b2_cancel_large_file}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as cancellation and retry overrides.\n *\n * @returns The cancelled large file metadata.\n */\n async cancelLargeFile(\n apiUrl: string,\n authToken: string,\n request: CancelLargeFileRequest,\n options?: RawRequestOptions,\n ): Promise<CancelLargeFileResponse> {\n return this.postJson<CancelLargeFileResponse>(\n apiUrl,\n authToken,\n 'b2_cancel_large_file',\n request,\n options,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-unfinished-large-files | b2_list_unfinished_large_files}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as cancellation and retry.\n *\n * @returns The list of unfinished large files and optional continuation token.\n */\n async listUnfinishedLargeFiles(\n apiUrl: string,\n authToken: string,\n request: ListUnfinishedLargeFilesRequest,\n options?: RawRequestOptions,\n ): Promise<ListUnfinishedLargeFilesResponse> {\n return this.postJson<ListUnfinishedLargeFilesResponse>(\n apiUrl,\n authToken,\n 'b2_list_unfinished_large_files',\n request,\n options,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-parts | b2_list_parts}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n * @param options - Optional request controls such as cancellation and retry.\n *\n * @returns The list of uploaded parts and optional continuation token.\n */\n async listParts(\n apiUrl: string,\n authToken: string,\n request: ListPartsRequest,\n options?: RawRequestOptions,\n ): Promise<ListPartsResponse> {\n return this.postJson<ListPartsResponse>(apiUrl, authToken, 'b2_list_parts', request, options)\n }\n\n // --- Downloads ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-download-file-by-id | b2_download_file_by_id}.\n * @param downloadUrl - The B2 download base URL.\n * @param authToken - The authorization token.\n * @param fileId - The unique identifier of the file to download.\n * @param options - Optional download parameters for range requests and cancellation.\n *\n * @returns The response headers, streaming body, and HTTP status code.\n */\n async downloadFileById(\n downloadUrl: string,\n authToken: string,\n fileId: string,\n options?: DownloadFileOptions,\n ): Promise<{\n /** Response headers containing file metadata and B2 info headers. */\n headers: Headers\n /** Streaming response body, or `null` for HEAD-like responses. */\n body: ReadableStream<Uint8Array> | null\n /** HTTP status code (200 for full content, 206 for partial content). */\n status: number\n }> {\n const headers = buildDownloadRequestHeaders(authToken, options)\n const url = appendDownloadOverrides(\n `${downloadUrl}/b2api/v3/b2_download_file_by_id?fileId=${encodeURIComponent(fileId)}`,\n options,\n )\n\n const response = await this.transport.send({\n url,\n method: options?.method ?? 'GET',\n headers,\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n })\n\n return { headers: response.headers, body: response.body, status: response.status }\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-download-file-by-name | b2_download_file_by_name}.\n * @param downloadUrl - The B2 download base URL.\n * @param authToken - The authorization token.\n * @param bucketName - The name of the bucket containing the file.\n * @param fileName - The name of the file to download.\n * @param options - Optional download parameters for range requests and cancellation.\n *\n * @returns The response headers, streaming body, and HTTP status code.\n */\n async downloadFileByName(\n downloadUrl: string,\n authToken: string,\n bucketName: string,\n fileName: string,\n options?: DownloadFileOptions,\n ): Promise<{\n /** Response headers containing file metadata and B2 info headers. */\n headers: Headers\n /** Streaming response body, or `null` for HEAD-like responses. */\n body: ReadableStream<Uint8Array> | null\n /** HTTP status code (200 for full content, 206 for partial content). */\n status: number\n }> {\n const headers = buildDownloadRequestHeaders(authToken, options)\n const url = appendDownloadOverrides(\n `${downloadUrl}/file/${encodeURIComponent(bucketName)}/${encodeFileName(fileName)}`,\n options,\n )\n\n const response = await this.transport.send({\n url,\n method: options?.method ?? 'GET',\n headers,\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n })\n\n return { headers: response.headers, body: response.body, status: response.status }\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-download-authorization | b2_get_download_authorization}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The current session authorization token.\n * @param request - The API request parameters.\n *\n * @returns The download authorization token for the specified file prefix.\n */\n async getDownloadAuthorization(\n apiUrl: string,\n authToken: string,\n request: DownloadAuthorizationRequest,\n ): Promise<DownloadAuthorizationResponse> {\n return this.postJson<DownloadAuthorizationResponse>(\n apiUrl,\n authToken,\n 'b2_get_download_authorization',\n request,\n )\n }\n\n // --- Keys ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-create-key | b2_create_key}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The newly created application key with secret.\n */\n async createKey(\n apiUrl: string,\n authToken: string,\n request: CreateKeyRequest,\n ): Promise<FullApplicationKey> {\n const key = await this.postJson<FullApplicationKey>(\n apiUrl,\n authToken,\n 'b2_create_key',\n normalizeCreateKeyRequest(request),\n undefined,\n 'v4',\n )\n return normalizeKeyResponse(key)\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-list-keys | b2_list_keys}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The list of application keys and optional continuation token.\n */\n async listKeys(\n apiUrl: string,\n authToken: string,\n request: ListKeysRequest,\n ): Promise<ListKeysResponse> {\n const response = await this.postJson<ListKeysResponse>(\n apiUrl,\n authToken,\n 'b2_list_keys',\n request,\n undefined,\n 'v4',\n )\n return { ...response, keys: response.keys.map((key) => normalizeKeyResponse(key)) }\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-delete-key | b2_delete_key}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The deleted application key metadata.\n */\n async deleteKey(\n apiUrl: string,\n authToken: string,\n request: DeleteKeyRequest,\n ): Promise<ApplicationKey> {\n const key = await this.postJson<ApplicationKey>(\n apiUrl,\n authToken,\n 'b2_delete_key',\n request,\n undefined,\n 'v4',\n )\n return normalizeKeyResponse(key)\n }\n\n // --- Retention / Legal Hold ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-update-file-retention | b2_update_file_retention}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The updated file retention settings.\n */\n async updateFileRetention(\n apiUrl: string,\n authToken: string,\n request: UpdateFileRetentionRequest,\n ): Promise<UpdateFileRetentionResponse> {\n return this.postJson<UpdateFileRetentionResponse>(\n apiUrl,\n authToken,\n 'b2_update_file_retention',\n request,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-update-file-legal-hold | b2_update_file_legal_hold}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The updated file legal hold status.\n */\n async updateFileLegalHold(\n apiUrl: string,\n authToken: string,\n request: UpdateFileLegalHoldRequest,\n ): Promise<UpdateFileLegalHoldResponse> {\n return this.postJson<UpdateFileLegalHoldResponse>(\n apiUrl,\n authToken,\n 'b2_update_file_legal_hold',\n request,\n )\n }\n\n // --- Notifications ---\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-get-bucket-notification-rules | b2_get_bucket_notification_rules}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The configured event notification rules for the specified bucket.\n */\n async getBucketNotificationRules(\n apiUrl: string,\n authToken: string,\n request: GetBucketNotificationRulesRequest,\n ): Promise<GetBucketNotificationRulesResponse> {\n return this.postJson<GetBucketNotificationRulesResponse>(\n apiUrl,\n authToken,\n 'b2_get_bucket_notification_rules',\n request,\n )\n }\n\n /**\n * Calls {@link https://www.backblaze.com/apidocs/b2-set-bucket-notification-rules | b2_set_bucket_notification_rules}.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param request - The API request parameters.\n *\n * @returns The updated bucket notification rules.\n */\n async setBucketNotificationRules(\n apiUrl: string,\n authToken: string,\n request: SetBucketNotificationRulesRequest,\n ): Promise<SetBucketNotificationRulesResponse> {\n return this.postJson<SetBucketNotificationRulesResponse>(\n apiUrl,\n authToken,\n 'b2_set_bucket_notification_rules',\n request,\n )\n }\n\n // --- Internal ---\n\n /**\n * Sends a JSON POST request to the specified B2 API endpoint.\n * @param apiUrl - The B2 API base URL.\n * @param authToken - The authorization token.\n * @param endpoint - The B2 API endpoint name.\n * @param body - The JSON request body.\n * @param options - Optional abort and per-request retry settings.\n * @param apiVersion - B2 Native API version segment for this endpoint.\n *\n * @returns The parsed JSON response.\n */\n private async postJson<T>(\n apiUrl: string,\n authToken: string,\n endpoint: string,\n body: unknown,\n options?: RawRequestOptions,\n apiVersion: 'v3' | 'v4' = 'v3',\n ): Promise<T> {\n const response = await this.transport.send({\n url: `${apiUrl}/b2api/${apiVersion}/${endpoint}`,\n method: 'POST',\n headers: {\n Authorization: authToken,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n ...(options?.signal !== undefined ? { signal: options.signal } : {}),\n ...(options?.retry !== undefined ? { retry: options.retry } : {}),\n })\n return response.json<T>()\n }\n}\n\n// --- Header helpers ---\n\nimport { EncryptionAlgorithm, EncryptionMode, type EncryptionSetting } from '../types/encryption.ts'\nimport type { FileRetentionValue, LegalHoldValue } from '../types/lock.ts'\n\n/**\n * Applies server-side encryption headers to the request.\n * @param headers - The mutable headers object to populate.\n * @param encryption - The encryption settings, or undefined to skip.\n */\nfunction applyEncryptionHeaders(\n headers: Record<string, string>,\n encryption: EncryptionSetting | undefined,\n): void {\n if (!encryption || encryption.mode === EncryptionMode.None) return\n if (encryption.mode === EncryptionMode.SseB2) {\n headers['X-Bz-Server-Side-Encryption'] = EncryptionAlgorithm.Aes256\n } else if (encryption.mode === EncryptionMode.SseC) {\n headers['X-Bz-Server-Side-Encryption-Customer-Algorithm'] = EncryptionAlgorithm.Aes256\n headers['X-Bz-Server-Side-Encryption-Customer-Key'] = encryption.customerKey\n headers['X-Bz-Server-Side-Encryption-Customer-Key-Md5'] = encryption.customerKeyMd5\n }\n}\n\n/**\n * SSE-C decryption parameters supplied to downloads of files that were\n * uploaded with customer-managed keys.\n */\nexport interface SseCDownloadKey {\n /** Encryption algorithm. Always `EncryptionAlgorithm.Aes256` (`'AES256'`). */\n readonly algorithm: EncryptionAlgorithm\n /** Base64-encoded customer-provided decryption key. */\n readonly customerKey: string\n /** Base64-encoded MD5 digest of the decryption key. */\n readonly customerKeyMd5: string\n}\n\n/**\n * Options accepted by {@link RawClient.downloadFileById} and\n * {@link RawClient.downloadFileByName}. Mirrors the B2 native API: range +\n * SSE-C decryption headers + the documented `b2Content*` response-header\n * overrides (query-string parameters on the request URL).\n */\nexport interface DownloadFileOptions {\n /** HTTP method. Defaults to `'GET'`. Use `'HEAD'` to fetch headers without the body. */\n readonly method?: 'GET' | 'HEAD'\n /** HTTP Range header value for partial content requests. */\n readonly range?: string\n /** SSE-C decryption parameters, required if the file was uploaded with SSE-C. */\n readonly serverSideEncryption?: SseCDownloadKey\n /** Override the `Content-Disposition` header in the download response. */\n readonly b2ContentDisposition?: string\n /** Override the `Content-Language` header in the download response. */\n readonly b2ContentLanguage?: string\n /** Override the `Content-Encoding` header in the download response. */\n readonly b2ContentEncoding?: string\n /** Override the `Content-Type` header in the download response. */\n readonly b2ContentType?: string\n /** Override the `Cache-Control` header in the download response. */\n readonly b2CacheControl?: string\n /** Override the `Expires` header in the download response. */\n readonly b2Expires?: string\n /** Signal to abort the download. */\n readonly signal?: AbortSignal\n}\n\nconst DOWNLOAD_OVERRIDE_PARAMS = [\n 'b2ContentDisposition',\n 'b2ContentLanguage',\n 'b2ContentEncoding',\n 'b2ContentType',\n 'b2CacheControl',\n 'b2Expires',\n] as const\n\n/**\n * Builds the HTTP request headers for a download: Authorization, optional\n * Range, and optional SSE-C decryption headers.\n *\n * @param authToken - The B2 session authorization token.\n * @param options - Caller-supplied download options.\n *\n * @returns The header map to send with the request.\n */\nfunction buildDownloadRequestHeaders(\n authToken: string,\n options: DownloadFileOptions | undefined,\n): Record<string, string> {\n const headers: Record<string, string> = { Authorization: authToken }\n if (options?.range) headers['Range'] = options.range\n if (options?.serverSideEncryption) {\n applyEncryptionHeaders(headers, {\n mode: EncryptionMode.SseC,\n ...options.serverSideEncryption,\n })\n }\n return headers\n}\n\n/**\n * Appends the documented `b2Content*` response-header overrides to a download\n * URL as query-string parameters. B2 echoes the values into the response\n * headers so callers can control content type, disposition, and caching.\n *\n * @param url - The base download URL.\n * @param options - Caller-supplied download options.\n *\n * @returns The URL with any override parameters appended.\n */\nfunction appendDownloadOverrides(url: string, options: DownloadFileOptions | undefined): string {\n if (!options) return url\n const params: string[] = []\n for (const key of DOWNLOAD_OVERRIDE_PARAMS) {\n const value = options[key]\n if (value !== undefined) {\n params.push(`${key}=${encodeURIComponent(value)}`)\n }\n }\n if (params.length === 0) return url\n const separator = url.includes('?') ? '&' : '?'\n return `${url}${separator}${params.join('&')}`\n}\n\n/**\n * Applies file retention headers to the request.\n * @param headers - The mutable headers object to populate.\n * @param retention - The retention settings, or undefined to skip.\n */\nfunction applyRetentionHeaders(\n headers: Record<string, string>,\n retention: FileRetentionValue | undefined,\n): void {\n if (!retention) return\n if (retention.mode) {\n headers['X-Bz-File-Retention-Mode'] = retention.mode\n }\n if (retention.retainUntilTimestamp) {\n headers['X-Bz-File-Retention-Retain-Until-Timestamp'] = String(retention.retainUntilTimestamp)\n }\n}\n\n/**\n * Applies the legal hold header to the request.\n * @param headers - The mutable headers object to populate.\n * @param legalHold - The legal hold value, or undefined to skip.\n */\nfunction applyLegalHoldHeader(\n headers: Record<string, string>,\n legalHold: LegalHoldValue | undefined,\n): void {\n if (!legalHold) return\n headers['X-Bz-File-Legal-Hold'] = legalHold\n}\n\nexport {\n buildFileInfoHeaders,\n decodeFileName,\n encodeFileName,\n parseFileInfoHeaders,\n} from './encoding.ts'\n"],"mappings":"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"}
package/dist/s3/index.cjs CHANGED
@@ -1,23 +1,360 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_url_redaction = require("../internal/url-redaction.cjs");
3
+ const require_encoding = require("../raw/encoding.cjs");
4
+ const require_url_guard = require("../http/url-guard.cjs");
5
+ const require_http = require("../util/http.cjs");
6
+ const require_validation = require("./validation.cjs");
7
+ const require_sigv4 = require("./sigv4.cjs");
8
+ //#region src/s3/index.ts
9
+ var HTTP_HEADER_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
10
+ var HTTP_MEDIA_TYPE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+\/[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
11
+ var DEFAULT_NATIVE_DOWNLOAD_URL_EXPIRES_IN = 3600;
12
+ var TRUSTED_NATIVE_DOWNLOAD_HOST_SUFFIXES = [
13
+ "backblazeb2.com",
14
+ "backblaze.com",
15
+ "backblaze.net",
16
+ "b2-staging.io"
17
+ ];
18
+ var BROWSER_EXECUTABLE_CONTENT_TYPES = /* @__PURE__ */ new Set([
19
+ "text/html",
20
+ "application/xhtml+xml",
21
+ "image/svg+xml",
22
+ "application/javascript",
23
+ "text/javascript",
24
+ "application/x-javascript",
25
+ "text/x-javascript",
26
+ "application/ecmascript",
27
+ "text/ecmascript",
28
+ "application/x-ecmascript",
29
+ "text/x-ecmascript",
30
+ "text/xml",
31
+ "application/xml"
32
+ ]);
33
+ /**
34
+ * Server-side opt-in token for unsafe S3 presign options.
35
+ *
36
+ * Use this token as the value for `allowBrowserExecutableContentType`,
37
+ * `allowBrowserExecutableResponseContentType`, or
38
+ * `allowInlineResponseContentDisposition` only when active content or inline
39
+ * rendering from the storage origin is intentional and trusted.
40
+ */
41
+ var trustedUnsafeS3PresignOptIn = Object.freeze({ __trustedUnsafeS3PresignOptIn: "trustedUnsafeS3PresignOptIn" });
42
+ /**
43
+ * Derives an S3-compatible client configuration from B2 authorization state.
44
+ * Pass the result to `new S3Client(config)` from `@aws-sdk/client-s3`.
45
+ *
46
+ * Non-standard, custom, or proxied endpoints require an explicit `region`; set
47
+ * it before deploying this SDK to those endpoints. The SDK no longer falls back
48
+ * to `us-west-004` because that can mis-sign requests.
49
+ *
50
+ * @param config - B2 auth state, application key credentials, and optional region override.
51
+ *
52
+ * @returns Configuration ready for the AWS S3 SDK.
53
+ *
54
+ * @example
55
+ * ```ts
56
+ * const { B2_APPLICATION_KEY_ID, B2_APPLICATION_KEY } = process.env
57
+ * if (!B2_APPLICATION_KEY_ID || !B2_APPLICATION_KEY) throw new Error('Missing B2 credentials')
58
+ * const s3 = new S3Client(createS3ClientConfig({
59
+ * accountInfo: client.accountInfo,
60
+ * applicationKeyId: B2_APPLICATION_KEY_ID,
61
+ * applicationKey: B2_APPLICATION_KEY,
62
+ * }))
63
+ * ```
64
+ */
3
65
  function createS3ClientConfig(config) {
4
- const s3Url = config.accountInfo.getS3ApiUrl();
5
- const regionMatch = s3Url.match(/s3\.([^.]+)\.backblazeb2\.com/);
6
- const region = config.region ?? regionMatch?.[1] ?? "us-west-004";
7
- return {
8
- endpoint: s3Url,
9
- region,
10
- credentials: {
11
- accessKeyId: config.applicationKeyId,
12
- secretAccessKey: config.applicationKey
13
- },
14
- forcePathStyle: true
15
- };
16
- }
17
- function presignGetObjectUrl(downloadUrl, bucketName, fileName, authorizationToken, validDurationInSeconds = 3600) {
18
- const expires = Math.floor(Date.now() / 1e3) + validDurationInSeconds;
19
- return `${downloadUrl}/file/${encodeURIComponent(bucketName)}/${encodeURIComponent(fileName)}?Authorization=${encodeURIComponent(authorizationToken)}&expires=${expires}`;
66
+ const s3Url = config.accountInfo.getS3ApiUrl();
67
+ const region = config.region ?? deriveRequiredS3Region(s3Url);
68
+ assertNonEmptyStringOption("applicationKeyId", config.applicationKeyId);
69
+ assertNonEmptyStringOption("applicationKey", config.applicationKey);
70
+ assertNonEmptyStringOption("region", region);
71
+ assertSigV4CredentialScopeComponent("applicationKeyId", config.applicationKeyId);
72
+ assertSigV4CredentialScopeComponent("region", region);
73
+ return {
74
+ endpoint: s3Url,
75
+ region,
76
+ credentials: {
77
+ accessKeyId: config.applicationKeyId,
78
+ secretAccessKey: config.applicationKey
79
+ },
80
+ forcePathStyle: true
81
+ };
20
82
  }
83
+ /**
84
+ * Extracts the B2 S3 region from a standard B2 S3 endpoint.
85
+ *
86
+ * Custom endpoints cannot be inferred safely. Pass `region` explicitly to
87
+ * {@link createS3ClientConfig}, {@link presignS3GetObjectUrl}, or
88
+ * {@link presignS3PutObjectUrl} when this returns `null`.
89
+ *
90
+ * @param endpoint - The S3 endpoint URL.
91
+ *
92
+ * @returns The derived region, or `null` when the endpoint is not a standard B2 S3 URL.
93
+ */
94
+ function deriveS3RegionFromEndpoint(endpoint) {
95
+ let hostname;
96
+ try {
97
+ hostname = new URL(endpoint).hostname.toLowerCase();
98
+ } catch {
99
+ return null;
100
+ }
101
+ return /^s3\.([a-z0-9-]+)\.backblazeb2\.com$/.exec(hostname)?.[1] ?? null;
102
+ }
103
+ /**
104
+ * Generates an AWS Signature Version 4 presigned GET URL for B2's S3-compatible API.
105
+ *
106
+ * This helper signs internally and does not pass the B2 application key to
107
+ * runtime peer dependencies. Response override options are signed into the URL
108
+ * and control headers served from the storage origin; do not populate them from
109
+ * untrusted input without an allow-list. Presign success does not prove the URL
110
+ * will be accepted later; keep URL-generating hosts clock-synchronized and
111
+ * check clock skew when downstream use returns SigV4 403 errors.
112
+ *
113
+ * @param options - B2 auth state, S3 credentials, target object, and signing options.
114
+ *
115
+ * @returns The presigned URL string.
116
+ */
117
+ async function presignS3GetObjectUrl(options) {
118
+ const query = [["x-id", "GetObject"]];
119
+ if (options.versionId !== void 0) {
120
+ assertSafeQueryValue("versionId", options.versionId);
121
+ query.push(["versionId", options.versionId]);
122
+ }
123
+ if (options.responseCacheControl !== void 0) {
124
+ assertSafeResponseOverride("responseCacheControl", options.responseCacheControl);
125
+ query.push(["response-cache-control", options.responseCacheControl]);
126
+ }
127
+ if (options.responseContentDisposition !== void 0) {
128
+ assertSafeResponseContentDisposition(options.responseContentDisposition, isTrustedUnsafeS3PresignOptIn(options.allowInlineResponseContentDisposition));
129
+ query.push(["response-content-disposition", options.responseContentDisposition]);
130
+ }
131
+ if (options.responseContentEncoding !== void 0) {
132
+ assertSafeResponseOverride("responseContentEncoding", options.responseContentEncoding);
133
+ query.push(["response-content-encoding", options.responseContentEncoding]);
134
+ }
135
+ if (options.responseContentLanguage !== void 0) {
136
+ assertSafeResponseOverride("responseContentLanguage", options.responseContentLanguage);
137
+ query.push(["response-content-language", options.responseContentLanguage]);
138
+ }
139
+ if (options.responseContentType !== void 0) {
140
+ if (isTrustedUnsafeS3PresignOptIn(options.allowBrowserExecutableResponseContentType)) assertSafeContentTypeValue("responseContentType", options.responseContentType, "response header value");
141
+ else assertSafeResponseContentType(options.responseContentType);
142
+ query.push(["response-content-type", options.responseContentType]);
143
+ }
144
+ if (options.responseExpires !== void 0) query.push(["response-expires", normalizeResponseExpires(options.responseExpires)]);
145
+ return await require_sigv4.presignS3Request("GET", createSigV4PresignOptions(options), query, []);
146
+ }
147
+ /**
148
+ * Returns a B2-native download-authorization URL, not an S3 presigned URL.
149
+ *
150
+ * This deprecated helper preserves the legacy positional output contract where
151
+ * the whole file name is encoded as one URL component, including `/` as `%2F`.
152
+ * It keeps the legacy string-building contract for callers that relied on
153
+ * custom/local download URLs or permissive inputs. Use
154
+ * {@link createNativeDownloadAuthorizationUrl} for strict validation.
155
+ *
156
+ * @param downloadUrl - The B2 download URL from authorization.
157
+ * @param bucketName - The bucket containing the file.
158
+ * @param fileName - The file name (path) to download.
159
+ * @param authorizationToken - A download authorization token from `b2_get_download_authorization`.
160
+ * @param validDurationInSeconds - Compatibility-only value for the non-authoritative `expires` query.
161
+ *
162
+ * @returns The B2 native download-authorization URL string.
163
+ *
164
+ * @deprecated Use {@link createNativeDownloadAuthorizationUrl} for B2 native
165
+ * download-token URLs, or {@link presignS3GetObjectUrl} for real S3-compatible
166
+ * AWS Signature Version 4 presigned GET URLs.
167
+ */
168
+ function presignGetObjectUrl(downloadUrl, bucketName, fileName, authorizationToken, validDurationInSeconds) {
169
+ const expires = Math.floor(Date.now() / 1e3) + (validDurationInSeconds ?? DEFAULT_NATIVE_DOWNLOAD_URL_EXPIRES_IN);
170
+ return `${downloadUrl}/file/${encodeURIComponent(bucketName)}/${encodeURIComponent(fileName)}?Authorization=${encodeURIComponent(authorizationToken)}&expires=${expires}`;
171
+ }
172
+ /**
173
+ * Generates an AWS Signature Version 4 presigned PUT URL for browser or
174
+ * third-party uploads through B2's S3-compatible API.
175
+ *
176
+ * This helper signs internally and does not pass the B2 application key to
177
+ * runtime peer dependencies. A presigned PUT URL is a replayable bearer
178
+ * credential for writing one key until expiry. Retried PUTs can create
179
+ * duplicate B2 file versions when a response is lost after B2 stored the object.
180
+ * Use unique keys or reconcile uploaded file IDs/checksums, and configure
181
+ * lifecycle/version cleanup where duplicate versions must be removed
182
+ * automatically. If `contentType` and `contentLength` are omitted, the holder
183
+ * can choose any content type, including browser-executable types, and any size
184
+ * accepted by B2; bind both values before handing URLs to untrusted uploaders
185
+ * to limit financial-DoS and content-type smuggling risk.
186
+ *
187
+ * @param options - B2 auth state, S3 credentials, target object, and signing options.
188
+ *
189
+ * @returns The presigned URL string.
190
+ */
191
+ async function presignS3PutObjectUrl(options) {
192
+ const headers = [];
193
+ if (options.contentType !== void 0) {
194
+ if (isTrustedUnsafeS3PresignOptIn(options.allowBrowserExecutableContentType)) assertSafeContentTypeValue("contentType", options.contentType, "stored object Content-Type");
195
+ else assertSafePutContentType(options.contentType);
196
+ headers.push(["content-type", options.contentType]);
197
+ }
198
+ if (options.contentLength !== void 0) headers.push(["content-length", normalizeContentLength(options.contentLength)]);
199
+ headers.push(...normalizeMetadataHeaders(options.metadata));
200
+ return await require_sigv4.presignS3Request("PUT", createSigV4PresignOptions(options), [["x-id", "PutObject"]], headers);
201
+ }
202
+ /**
203
+ * Generates an AWS Signature Version 4 presigned PUT URL for B2's
204
+ * S3-compatible API.
205
+ *
206
+ * @param options - B2 auth state, S3 credentials, target object, and signing options.
207
+ *
208
+ * @returns The presigned URL string.
209
+ *
210
+ * @deprecated Use {@link presignS3PutObjectUrl}; this alias is retained for
211
+ * pre-release callers that adopted the shorter name.
212
+ */
213
+ async function presignPutObjectUrl(options) {
214
+ return await presignS3PutObjectUrl(options);
215
+ }
216
+ /**
217
+ * Constructs a B2-native download URL using a token from `b2_get_download_authorization`.
218
+ * This is not an S3 presigned URL.
219
+ *
220
+ * The token lifetime is fixed when `b2_get_download_authorization` creates the
221
+ * token. `validDurationInSeconds` is retained only for compatibility with the
222
+ * legacy `presignGetObjectUrl` helper's decorative `expires` query parameter;
223
+ * changing it here does not shorten or extend access.
224
+ * Because the returned URL carries a bearer token, `downloadUrl` must be an
225
+ * HTTPS Backblaze download origin without userinfo, path, query, or fragment.
226
+ *
227
+ * @param downloadUrl - The B2 download URL from authorization (e.g., `https://f004.backblazeb2.com`).
228
+ * @param bucketName - The bucket containing the file.
229
+ * @param fileName - The file name (path) to download.
230
+ * @param authorizationToken - A download authorization token from `b2_get_download_authorization`.
231
+ * @param validDurationInSeconds - Compatibility-only value for the non-authoritative `expires` query.
232
+ *
233
+ * @returns The B2 native download-authorization URL string, not an S3 presigned URL.
234
+ */
235
+ function createNativeDownloadAuthorizationUrl(downloadUrl, bucketName, fileName, authorizationToken, validDurationInSeconds = DEFAULT_NATIVE_DOWNLOAD_URL_EXPIRES_IN) {
236
+ return buildNativeDownloadAuthorizationUrl(downloadUrl, bucketName, fileName, authorizationToken, validDurationInSeconds, require_encoding.encodeFileName, require_validation.assertNativeDownloadFileName);
237
+ }
238
+ function deriveRequiredS3Region(endpoint) {
239
+ const region = deriveS3RegionFromEndpoint(endpoint);
240
+ if (region !== null) return region;
241
+ throw new Error(`Unable to derive B2 S3 region from endpoint "${require_url_redaction.redactUrlForError(endpoint, { invalidUrlLabel: "<invalid S3 endpoint URL>" })}". Pass an explicit \`region\` option before deploying custom or proxied endpoints.`);
242
+ }
243
+ function createSigV4PresignOptions(options) {
244
+ const clientConfig = createS3ClientConfig(options);
245
+ return {
246
+ endpoint: clientConfig.endpoint,
247
+ region: clientConfig.region,
248
+ accessKeyId: clientConfig.credentials.accessKeyId,
249
+ secretAccessKey: clientConfig.credentials.secretAccessKey,
250
+ bucketName: options.bucketName,
251
+ fileName: options.fileName,
252
+ ...options.expiresIn !== void 0 ? { expiresIn: options.expiresIn } : {}
253
+ };
254
+ }
255
+ function normalizeContentLength(contentLength) {
256
+ if (!Number.isSafeInteger(contentLength) || contentLength < 0) throw new RangeError(`contentLength must be a non-negative safe integer; received ${String(contentLength)}.`);
257
+ return String(contentLength);
258
+ }
259
+ function normalizeValidDurationInSeconds(validDurationInSeconds) {
260
+ if (!Number.isSafeInteger(validDurationInSeconds) || validDurationInSeconds < 0) throw new RangeError(`validDurationInSeconds must be a non-negative safe integer; received ${String(validDurationInSeconds)}.`);
261
+ return validDurationInSeconds;
262
+ }
263
+ function assertNonEmptyStringOption(name, value) {
264
+ if (typeof value !== "string" || value.trim().length === 0) throw new TypeError(`${name} must be a non-empty string.`);
265
+ }
266
+ function assertSigV4CredentialScopeComponent(name, value) {
267
+ if (/[\s/]/u.test(value) || require_http.hasHttpHeaderControlCharacter(value)) throw new TypeError(`${name} must not contain whitespace, control characters, or "/" because it is embedded in the SigV4 credential scope.`);
268
+ }
269
+ function isTrustedUnsafeS3PresignOptIn(value) {
270
+ return value === trustedUnsafeS3PresignOptIn;
271
+ }
272
+ function buildNativeDownloadAuthorizationUrl(downloadUrl, bucketName, fileName, authorizationToken, validDurationInSeconds, encodeFileNameForUrl, assertFileName) {
273
+ const baseUrl = parseNativeDownloadBaseUrl(downloadUrl);
274
+ require_validation.assertSafeBucketName(bucketName);
275
+ assertFileName(fileName);
276
+ const expires = Math.floor(Date.now() / 1e3) + normalizeValidDurationInSeconds(validDurationInSeconds);
277
+ return `${baseUrl}/file/${encodeURIComponent(bucketName)}/${encodeFileNameForUrl(fileName)}?Authorization=${encodeURIComponent(authorizationToken)}&expires=${expires}`;
278
+ }
279
+ function parseNativeDownloadBaseUrl(downloadUrl) {
280
+ let base;
281
+ try {
282
+ base = new URL(downloadUrl);
283
+ } catch {
284
+ throw new TypeError(`Native download-authorization URLs require a valid https: downloadUrl; received "${require_url_redaction.redactUrlForError(downloadUrl, { invalidUrlLabel: "<invalid downloadUrl>" })}".`);
285
+ }
286
+ if (base.protocol !== "https:") throw new TypeError(`Native download-authorization URLs require an https: downloadUrl; received "${require_url_redaction.redactUrlForError(base)}".`);
287
+ if (base.username !== "" || base.password !== "") throw new TypeError("Native download-authorization URLs must not include userinfo.");
288
+ if (base.search !== "" || base.hash !== "") throw new TypeError("Native download-authorization URLs must not include query or fragment.");
289
+ if (base.pathname !== "" && base.pathname !== "/") throw new TypeError("Native download-authorization URLs must not include a path.");
290
+ if (!isTrustedNativeDownloadHost(base.hostname)) throw new TypeError(`Native download-authorization URLs require a Backblaze download host; received "${require_url_redaction.redactUrlForError(base)}".`);
291
+ return base.origin;
292
+ }
293
+ function normalizeMetadataHeaders(metadata) {
294
+ const headers = [];
295
+ const seenKeys = /* @__PURE__ */ new Set();
296
+ for (const [key, value] of Object.entries(metadata ?? {})) {
297
+ if (!HTTP_HEADER_TOKEN.test(key)) throw new TypeError(`metadata key "${key}" must be a non-empty valid HTTP header token.`);
298
+ if (typeof value !== "string") throw new TypeError(`metadata value for "${key}" must be a string.`);
299
+ const lowerKey = key.toLowerCase();
300
+ if (seenKeys.has(lowerKey)) throw new TypeError(`metadata key "${key}" must not differ only by case.`);
301
+ seenKeys.add(lowerKey);
302
+ headers.push([`x-amz-meta-${lowerKey}`, value]);
303
+ }
304
+ return headers;
305
+ }
306
+ function normalizeResponseExpires(responseExpires) {
307
+ if (!Number.isFinite(responseExpires.getTime())) throw new RangeError("responseExpires must be a valid Date.");
308
+ return responseExpires.toUTCString();
309
+ }
310
+ function assertSafeResponseOverride(name, value) {
311
+ assertSafeHeaderValue(name, value, "response header value");
312
+ }
313
+ function assertSafeQueryValue(name, value) {
314
+ if (require_http.hasHttpHeaderControlCharacter(value)) throw new TypeError(`${name} must not contain control characters because it becomes a query parameter.`);
315
+ }
316
+ function assertSafeHeaderValue(name, value, target) {
317
+ if (require_http.hasHttpHeaderControlCharacter(value)) throw new TypeError(`${name} must not contain control characters because it becomes a ${target}.`);
318
+ }
319
+ function assertSafeResponseContentType(contentType) {
320
+ assertNonExecutableContentType("responseContentType", contentType, "response header value", "allow-list a safe content type before signing response overrides");
321
+ }
322
+ function assertSafePutContentType(contentType) {
323
+ assertNonExecutableContentType("contentType", contentType, "stored object Content-Type", "pass allowBrowserExecutableContentType only when active content is intentional");
324
+ }
325
+ function assertSafeResponseContentDisposition(contentDisposition, allowInline) {
326
+ assertSafeResponseOverride("responseContentDisposition", contentDisposition);
327
+ const disposition = contentDisposition.split(";", 1)[0]?.trim().toLowerCase();
328
+ if (!allowInline && disposition === "inline") throw new TypeError("responseContentDisposition must not force inline rendering; use an attachment disposition for response overrides.");
329
+ }
330
+ function mediaTypeFor(contentType) {
331
+ return contentType.split(";", 1)[0]?.trim().toLowerCase() ?? "";
332
+ }
333
+ function assertSafeContentTypeValue(name, contentType, target) {
334
+ assertSafeHeaderValue(name, contentType, target);
335
+ const mediaType = mediaTypeFor(contentType);
336
+ if (mediaType.length === 0) throw new TypeError(`${name} must include a non-empty media type.`);
337
+ if (!HTTP_MEDIA_TYPE.test(mediaType)) throw new TypeError(`${name} must include a valid media type.`);
338
+ return mediaType;
339
+ }
340
+ function assertNonExecutableContentType(name, contentType, target, guidance) {
341
+ const mediaType = assertSafeContentTypeValue(name, contentType, target);
342
+ if (isBrowserExecutableContentType(mediaType)) throw new TypeError(`${name} "${mediaType}" can execute in browsers; ${guidance}.`);
343
+ }
344
+ function isBrowserExecutableContentType(mediaType) {
345
+ return BROWSER_EXECUTABLE_CONTENT_TYPES.has(mediaType) || mediaType.endsWith("+xml");
346
+ }
347
+ function isTrustedNativeDownloadHost(hostname) {
348
+ return TRUSTED_NATIVE_DOWNLOAD_HOST_SUFFIXES.some((suffix) => require_url_guard.hostMatchesAllowedSuffix(hostname, suffix));
349
+ }
350
+ //#endregion
351
+ exports.createNativeDownloadAuthorizationUrl = createNativeDownloadAuthorizationUrl;
21
352
  exports.createS3ClientConfig = createS3ClientConfig;
353
+ exports.deriveS3RegionFromEndpoint = deriveS3RegionFromEndpoint;
22
354
  exports.presignGetObjectUrl = presignGetObjectUrl;
23
- //# sourceMappingURL=index.cjs.map
355
+ exports.presignPutObjectUrl = presignPutObjectUrl;
356
+ exports.presignS3GetObjectUrl = presignS3GetObjectUrl;
357
+ exports.presignS3PutObjectUrl = presignS3PutObjectUrl;
358
+ exports.trustedUnsafeS3PresignOptIn = trustedUnsafeS3PresignOptIn;
359
+
360
+ //# sourceMappingURL=index.cjs.map