@backblaze-labs/b2-sdk 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (590) hide show
  1. package/CHANGELOG.md +86 -1
  2. package/README.md +38 -7
  3. package/dist/_virtual/_b2-sdk-version-json.cjs +1 -1
  4. package/dist/_virtual/_b2-sdk-version-json.js +1 -1
  5. package/dist/auth/file.cjs.map +1 -1
  6. package/dist/auth/reauth-coalescer.cjs +65 -0
  7. package/dist/auth/reauth-coalescer.cjs.map +1 -0
  8. package/dist/auth/reauth-coalescer.d.cts +34 -0
  9. package/dist/auth/reauth-coalescer.d.cts.map +1 -0
  10. package/dist/auth/reauth-coalescer.d.ts +34 -0
  11. package/dist/auth/reauth-coalescer.d.ts.map +1 -0
  12. package/dist/auth/reauth-coalescer.js +65 -0
  13. package/dist/auth/reauth-coalescer.js.map +1 -0
  14. package/dist/backup/client.cjs +206 -0
  15. package/dist/backup/client.cjs.map +1 -0
  16. package/dist/backup/client.d.cts +238 -0
  17. package/dist/backup/client.d.cts.map +1 -0
  18. package/dist/backup/client.d.ts +238 -0
  19. package/dist/backup/client.d.ts.map +1 -0
  20. package/dist/backup/client.js +206 -0
  21. package/dist/backup/client.js.map +1 -0
  22. package/dist/backup/index.cjs +15 -0
  23. package/dist/backup/index.d.cts +22 -0
  24. package/dist/backup/index.d.cts.map +1 -0
  25. package/dist/backup/index.d.ts +22 -0
  26. package/dist/backup/index.d.ts.map +1 -0
  27. package/dist/backup/index.js +7 -0
  28. package/dist/backup/raw.cjs +168 -0
  29. package/dist/backup/raw.cjs.map +1 -0
  30. package/dist/backup/raw.d.cts +122 -0
  31. package/dist/backup/raw.d.cts.map +1 -0
  32. package/dist/backup/raw.d.ts +122 -0
  33. package/dist/backup/raw.d.ts.map +1 -0
  34. package/dist/backup/raw.js +168 -0
  35. package/dist/backup/raw.js.map +1 -0
  36. package/dist/bucket-validation.cjs +111 -0
  37. package/dist/bucket-validation.cjs.map +1 -0
  38. package/dist/bucket-validation.d.cts +27 -0
  39. package/dist/bucket-validation.d.cts.map +1 -0
  40. package/dist/bucket-validation.d.ts +27 -0
  41. package/dist/bucket-validation.d.ts.map +1 -0
  42. package/dist/bucket-validation.js +109 -0
  43. package/dist/bucket-validation.js.map +1 -0
  44. package/dist/bucket.cjs +125 -74
  45. package/dist/bucket.cjs.map +1 -1
  46. package/dist/bucket.d.cts +156 -61
  47. package/dist/bucket.d.cts.map +1 -1
  48. package/dist/bucket.d.ts +156 -61
  49. package/dist/bucket.d.ts.map +1 -1
  50. package/dist/bucket.js +125 -74
  51. package/dist/bucket.js.map +1 -1
  52. package/dist/client.cjs +29 -8
  53. package/dist/client.cjs.map +1 -1
  54. package/dist/client.d.cts +30 -9
  55. package/dist/client.d.cts.map +1 -1
  56. package/dist/client.d.ts +30 -9
  57. package/dist/client.d.ts.map +1 -1
  58. package/dist/client.js +29 -8
  59. package/dist/client.js.map +1 -1
  60. package/dist/copy/large.cjs +5 -3
  61. package/dist/copy/large.cjs.map +1 -1
  62. package/dist/copy/large.d.cts.map +1 -1
  63. package/dist/copy/large.d.ts.map +1 -1
  64. package/dist/copy/large.js +5 -3
  65. package/dist/copy/large.js.map +1 -1
  66. package/dist/download/checksum.cjs +6 -2
  67. package/dist/download/checksum.cjs.map +1 -1
  68. package/dist/download/checksum.js +6 -2
  69. package/dist/download/checksum.js.map +1 -1
  70. package/dist/download/parallel.cjs +52 -15
  71. package/dist/download/parallel.cjs.map +1 -1
  72. package/dist/download/parallel.d.cts +8 -1
  73. package/dist/download/parallel.d.cts.map +1 -1
  74. package/dist/download/parallel.d.ts +8 -1
  75. package/dist/download/parallel.d.ts.map +1 -1
  76. package/dist/download/parallel.js +52 -15
  77. package/dist/download/parallel.js.map +1 -1
  78. package/dist/download/single.cjs +179 -19
  79. package/dist/download/single.cjs.map +1 -1
  80. package/dist/download/single.d.cts +10 -4
  81. package/dist/download/single.d.cts.map +1 -1
  82. package/dist/download/single.d.ts +10 -4
  83. package/dist/download/single.d.ts.map +1 -1
  84. package/dist/download/single.js +179 -19
  85. package/dist/download/single.js.map +1 -1
  86. package/dist/errors/index.cjs +196 -3
  87. package/dist/errors/index.cjs.map +1 -1
  88. package/dist/errors/index.d.cts +134 -0
  89. package/dist/errors/index.d.cts.map +1 -1
  90. package/dist/errors/index.d.ts +134 -0
  91. package/dist/errors/index.d.ts.map +1 -1
  92. package/dist/errors/index.js +183 -4
  93. package/dist/errors/index.js.map +1 -1
  94. package/dist/http/non-idempotent-mutations.cjs +38 -0
  95. package/dist/http/non-idempotent-mutations.cjs.map +1 -0
  96. package/dist/http/non-idempotent-mutations.d.cts +25 -0
  97. package/dist/http/non-idempotent-mutations.d.cts.map +1 -0
  98. package/dist/http/non-idempotent-mutations.d.ts +25 -0
  99. package/dist/http/non-idempotent-mutations.d.ts.map +1 -0
  100. package/dist/http/non-idempotent-mutations.js +35 -0
  101. package/dist/http/non-idempotent-mutations.js.map +1 -0
  102. package/dist/http/retry.cjs +1 -1
  103. package/dist/http/retry.cjs.map +1 -1
  104. package/dist/http/retry.js +1 -1
  105. package/dist/http/retry.js.map +1 -1
  106. package/dist/http/transport.cjs +62 -23
  107. package/dist/http/transport.cjs.map +1 -1
  108. package/dist/http/transport.d.cts +30 -3
  109. package/dist/http/transport.d.cts.map +1 -1
  110. package/dist/http/transport.d.ts +30 -3
  111. package/dist/http/transport.d.ts.map +1 -1
  112. package/dist/http/transport.js +60 -22
  113. package/dist/http/transport.js.map +1 -1
  114. package/dist/http/user-agent.cjs +12 -1
  115. package/dist/http/user-agent.cjs.map +1 -1
  116. package/dist/http/user-agent.d.cts +8 -0
  117. package/dist/http/user-agent.d.cts.map +1 -1
  118. package/dist/http/user-agent.d.ts +8 -0
  119. package/dist/http/user-agent.d.ts.map +1 -1
  120. package/dist/http/user-agent.js +13 -3
  121. package/dist/http/user-agent.js.map +1 -1
  122. package/dist/index.cjs +50 -2
  123. package/dist/index.d.cts +15 -12
  124. package/dist/index.d.cts.map +1 -1
  125. package/dist/index.d.ts +15 -12
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +13 -10
  128. package/dist/notifications/index.cjs +3 -0
  129. package/dist/notifications/index.d.cts +2 -0
  130. package/dist/notifications/index.d.cts.map +1 -1
  131. package/dist/notifications/index.d.ts +2 -0
  132. package/dist/notifications/index.d.ts.map +1 -1
  133. package/dist/notifications/index.js +2 -1
  134. package/dist/object.cjs +13 -2
  135. package/dist/object.cjs.map +1 -1
  136. package/dist/object.d.cts +11 -3
  137. package/dist/object.d.cts.map +1 -1
  138. package/dist/object.d.ts +11 -3
  139. package/dist/object.d.ts.map +1 -1
  140. package/dist/object.js +13 -2
  141. package/dist/object.js.map +1 -1
  142. package/dist/partner/account-info.d.cts +43 -0
  143. package/dist/partner/account-info.d.cts.map +1 -0
  144. package/dist/partner/account-info.d.ts +43 -0
  145. package/dist/partner/account-info.d.ts.map +1 -0
  146. package/dist/partner/auth-clone.cjs +64 -0
  147. package/dist/partner/auth-clone.cjs.map +1 -0
  148. package/dist/partner/auth-clone.d.cts +27 -0
  149. package/dist/partner/auth-clone.d.cts.map +1 -0
  150. package/dist/partner/auth-clone.d.ts +27 -0
  151. package/dist/partner/auth-clone.d.ts.map +1 -0
  152. package/dist/partner/auth-clone.js +63 -0
  153. package/dist/partner/auth-clone.js.map +1 -0
  154. package/dist/partner/auth-core.cjs +156 -0
  155. package/dist/partner/auth-core.cjs.map +1 -0
  156. package/dist/partner/auth-core.d.cts +111 -0
  157. package/dist/partner/auth-core.d.cts.map +1 -0
  158. package/dist/partner/auth-core.d.ts +111 -0
  159. package/dist/partner/auth-core.d.ts.map +1 -0
  160. package/dist/partner/auth-core.js +156 -0
  161. package/dist/partner/auth-core.js.map +1 -0
  162. package/dist/partner/auth-shape.cjs +36 -0
  163. package/dist/partner/auth-shape.cjs.map +1 -0
  164. package/dist/partner/auth-shape.d.cts +12 -0
  165. package/dist/partner/auth-shape.d.cts.map +1 -0
  166. package/dist/partner/auth-shape.d.ts +12 -0
  167. package/dist/partner/auth-shape.d.ts.map +1 -0
  168. package/dist/partner/auth-shape.js +36 -0
  169. package/dist/partner/auth-shape.js.map +1 -0
  170. package/dist/partner/client.cjs +270 -0
  171. package/dist/partner/client.cjs.map +1 -0
  172. package/dist/partner/client.d.cts +357 -0
  173. package/dist/partner/client.d.cts.map +1 -0
  174. package/dist/partner/client.d.ts +357 -0
  175. package/dist/partner/client.d.ts.map +1 -0
  176. package/dist/partner/client.js +270 -0
  177. package/dist/partner/client.js.map +1 -0
  178. package/dist/partner/endpoint-url.cjs +109 -0
  179. package/dist/partner/endpoint-url.cjs.map +1 -0
  180. package/dist/partner/endpoint-url.d.cts +74 -0
  181. package/dist/partner/endpoint-url.d.cts.map +1 -0
  182. package/dist/partner/endpoint-url.d.ts +74 -0
  183. package/dist/partner/endpoint-url.d.ts.map +1 -0
  184. package/dist/partner/endpoint-url.js +106 -0
  185. package/dist/partner/endpoint-url.js.map +1 -0
  186. package/dist/partner/in-memory.cjs +135 -0
  187. package/dist/partner/in-memory.cjs.map +1 -0
  188. package/dist/partner/in-memory.d.cts +99 -0
  189. package/dist/partner/in-memory.d.cts.map +1 -0
  190. package/dist/partner/in-memory.d.ts +99 -0
  191. package/dist/partner/in-memory.d.ts.map +1 -0
  192. package/dist/partner/in-memory.js +135 -0
  193. package/dist/partner/in-memory.js.map +1 -0
  194. package/dist/partner/index.cjs +27 -0
  195. package/dist/partner/index.d.cts +32 -0
  196. package/dist/partner/index.d.cts.map +1 -0
  197. package/dist/partner/index.d.ts +32 -0
  198. package/dist/partner/index.d.ts.map +1 -0
  199. package/dist/partner/index.js +9 -0
  200. package/dist/partner/raw.cjs +400 -0
  201. package/dist/partner/raw.cjs.map +1 -0
  202. package/dist/partner/raw.d.cts +220 -0
  203. package/dist/partner/raw.d.cts.map +1 -0
  204. package/dist/partner/raw.d.ts +220 -0
  205. package/dist/partner/raw.d.ts.map +1 -0
  206. package/dist/partner/raw.js +398 -0
  207. package/dist/partner/raw.js.map +1 -0
  208. package/dist/partner/redaction-placeholders.cjs +10 -0
  209. package/dist/partner/redaction-placeholders.cjs.map +1 -0
  210. package/dist/partner/redaction-placeholders.d.cts +5 -0
  211. package/dist/partner/redaction-placeholders.d.cts.map +1 -0
  212. package/dist/partner/redaction-placeholders.d.ts +5 -0
  213. package/dist/partner/redaction-placeholders.d.ts.map +1 -0
  214. package/dist/partner/redaction-placeholders.js +9 -0
  215. package/dist/partner/redaction-placeholders.js.map +1 -0
  216. package/dist/partner/redaction.cjs +292 -0
  217. package/dist/partner/redaction.cjs.map +1 -0
  218. package/dist/partner/redaction.d.cts +158 -0
  219. package/dist/partner/redaction.d.cts.map +1 -0
  220. package/dist/partner/redaction.d.ts +158 -0
  221. package/dist/partner/redaction.d.ts.map +1 -0
  222. package/dist/partner/redaction.js +281 -0
  223. package/dist/partner/redaction.js.map +1 -0
  224. package/dist/raw/encoding.cjs +29 -10
  225. package/dist/raw/encoding.cjs.map +1 -1
  226. package/dist/raw/encoding.d.cts +3 -2
  227. package/dist/raw/encoding.d.cts.map +1 -1
  228. package/dist/raw/encoding.d.ts +3 -2
  229. package/dist/raw/encoding.d.ts.map +1 -1
  230. package/dist/raw/encoding.js +29 -10
  231. package/dist/raw/encoding.js.map +1 -1
  232. package/dist/raw/index.cjs +131 -44
  233. package/dist/raw/index.cjs.map +1 -1
  234. package/dist/raw/index.d.cts +21 -15
  235. package/dist/raw/index.d.cts.map +1 -1
  236. package/dist/raw/index.d.ts +21 -15
  237. package/dist/raw/index.d.ts.map +1 -1
  238. package/dist/raw/index.js +114 -45
  239. package/dist/raw/index.js.map +1 -1
  240. package/dist/raw/url.cjs +111 -0
  241. package/dist/raw/url.cjs.map +1 -0
  242. package/dist/raw/url.d.cts +41 -0
  243. package/dist/raw/url.d.cts.map +1 -0
  244. package/dist/raw/url.d.ts +41 -0
  245. package/dist/raw/url.d.ts.map +1 -0
  246. package/dist/raw/url.js +110 -0
  247. package/dist/raw/url.js.map +1 -0
  248. package/dist/s3/sigv4.cjs +15 -10
  249. package/dist/s3/sigv4.cjs.map +1 -1
  250. package/dist/s3/sigv4.js +15 -10
  251. package/dist/s3/sigv4.js.map +1 -1
  252. package/dist/simulator/index.cjs +1579 -257
  253. package/dist/simulator/index.cjs.map +1 -1
  254. package/dist/simulator/index.d.cts +124 -11
  255. package/dist/simulator/index.d.cts.map +1 -1
  256. package/dist/simulator/index.d.ts +124 -11
  257. package/dist/simulator/index.d.ts.map +1 -1
  258. package/dist/simulator/index.js +1568 -262
  259. package/dist/simulator/index.js.map +1 -1
  260. package/dist/simulator/partner-capabilities.cjs +77 -0
  261. package/dist/simulator/partner-capabilities.cjs.map +1 -0
  262. package/dist/simulator/partner-capabilities.d.cts +53 -0
  263. package/dist/simulator/partner-capabilities.d.cts.map +1 -0
  264. package/dist/simulator/partner-capabilities.d.ts +53 -0
  265. package/dist/simulator/partner-capabilities.d.ts.map +1 -0
  266. package/dist/simulator/partner-capabilities.js +73 -0
  267. package/dist/simulator/partner-capabilities.js.map +1 -0
  268. package/dist/simulator/partner.cjs +713 -0
  269. package/dist/simulator/partner.cjs.map +1 -0
  270. package/dist/simulator/partner.d.cts +186 -0
  271. package/dist/simulator/partner.d.cts.map +1 -0
  272. package/dist/simulator/partner.d.ts +186 -0
  273. package/dist/simulator/partner.d.ts.map +1 -0
  274. package/dist/simulator/partner.js +713 -0
  275. package/dist/simulator/partner.js.map +1 -0
  276. package/dist/simulator/validation.cjs +732 -25
  277. package/dist/simulator/validation.cjs.map +1 -1
  278. package/dist/simulator/validation.d.cts +145 -6
  279. package/dist/simulator/validation.d.cts.map +1 -1
  280. package/dist/simulator/validation.d.ts +145 -6
  281. package/dist/simulator/validation.d.ts.map +1 -1
  282. package/dist/simulator/validation.js +705 -26
  283. package/dist/simulator/validation.js.map +1 -1
  284. package/dist/streams/file-source.cjs +2 -2
  285. package/dist/streams/file-source.cjs.map +1 -1
  286. package/dist/streams/file-source.js +2 -2
  287. package/dist/streams/file-source.js.map +1 -1
  288. package/dist/streams/hash.cjs +246 -13
  289. package/dist/streams/hash.cjs.map +1 -1
  290. package/dist/streams/hash.d.cts +37 -12
  291. package/dist/streams/hash.d.cts.map +1 -1
  292. package/dist/streams/hash.d.ts +37 -12
  293. package/dist/streams/hash.d.ts.map +1 -1
  294. package/dist/streams/hash.js +246 -15
  295. package/dist/streams/hash.js.map +1 -1
  296. package/dist/streams/index.cjs +3 -1
  297. package/dist/streams/index.d.cts +1 -1
  298. package/dist/streams/index.d.cts.map +1 -1
  299. package/dist/streams/index.d.ts +1 -1
  300. package/dist/streams/index.d.ts.map +1 -1
  301. package/dist/streams/index.js +3 -3
  302. package/dist/streams/progress.cjs +63 -4
  303. package/dist/streams/progress.cjs.map +1 -1
  304. package/dist/streams/progress.d.cts +28 -2
  305. package/dist/streams/progress.d.cts.map +1 -1
  306. package/dist/streams/progress.d.ts +28 -2
  307. package/dist/streams/progress.d.ts.map +1 -1
  308. package/dist/streams/progress.js +63 -4
  309. package/dist/streams/progress.js.map +1 -1
  310. package/dist/streams/source.cjs +2 -1
  311. package/dist/streams/source.cjs.map +1 -1
  312. package/dist/streams/source.js +2 -1
  313. package/dist/streams/source.js.map +1 -1
  314. package/dist/sync/b2-sha1-reader.cjs +6 -2
  315. package/dist/sync/b2-sha1-reader.cjs.map +1 -1
  316. package/dist/sync/b2-sha1-reader.d.cts.map +1 -1
  317. package/dist/sync/b2-sha1-reader.d.ts.map +1 -1
  318. package/dist/sync/b2-sha1-reader.js +6 -2
  319. package/dist/sync/b2-sha1-reader.js.map +1 -1
  320. package/dist/sync/download-staging.cjs +156 -43
  321. package/dist/sync/download-staging.cjs.map +1 -1
  322. package/dist/sync/download-staging.d.cts +26 -2
  323. package/dist/sync/download-staging.d.cts.map +1 -1
  324. package/dist/sync/download-staging.d.ts +26 -2
  325. package/dist/sync/download-staging.d.ts.map +1 -1
  326. package/dist/sync/download-staging.js +155 -44
  327. package/dist/sync/download-staging.js.map +1 -1
  328. package/dist/sync/filters.cjs.map +1 -1
  329. package/dist/sync/filters.js.map +1 -1
  330. package/dist/sync/index.d.cts +1 -1
  331. package/dist/sync/index.d.cts.map +1 -1
  332. package/dist/sync/index.d.ts +1 -1
  333. package/dist/sync/index.d.ts.map +1 -1
  334. package/dist/sync/local-file-io.cjs +15 -6
  335. package/dist/sync/local-file-io.cjs.map +1 -1
  336. package/dist/sync/local-file-io.d.cts +3 -0
  337. package/dist/sync/local-file-io.d.cts.map +1 -1
  338. package/dist/sync/local-file-io.d.ts +3 -0
  339. package/dist/sync/local-file-io.d.ts.map +1 -1
  340. package/dist/sync/local-file-io.js +15 -6
  341. package/dist/sync/local-file-io.js.map +1 -1
  342. package/dist/sync/local-sha1.cjs +6 -15
  343. package/dist/sync/local-sha1.cjs.map +1 -1
  344. package/dist/sync/local-sha1.d.cts +0 -8
  345. package/dist/sync/local-sha1.d.cts.map +1 -1
  346. package/dist/sync/local-sha1.d.ts +0 -8
  347. package/dist/sync/local-sha1.d.ts.map +1 -1
  348. package/dist/sync/local-sha1.js +7 -15
  349. package/dist/sync/local-sha1.js.map +1 -1
  350. package/dist/sync/pairing.cjs +1 -0
  351. package/dist/sync/pairing.cjs.map +1 -1
  352. package/dist/sync/pairing.js +1 -0
  353. package/dist/sync/pairing.js.map +1 -1
  354. package/dist/sync/policies/compare.cjs +5 -3
  355. package/dist/sync/policies/compare.cjs.map +1 -1
  356. package/dist/sync/policies/compare.d.cts.map +1 -1
  357. package/dist/sync/policies/compare.d.ts.map +1 -1
  358. package/dist/sync/policies/compare.js +6 -4
  359. package/dist/sync/policies/compare.js.map +1 -1
  360. package/dist/sync/policies/index.cjs +4 -10
  361. package/dist/sync/policies/index.cjs.map +1 -1
  362. package/dist/sync/policies/index.js +4 -10
  363. package/dist/sync/policies/index.js.map +1 -1
  364. package/dist/sync/scanners/b2.cjs +4 -2
  365. package/dist/sync/scanners/b2.cjs.map +1 -1
  366. package/dist/sync/scanners/b2.d.cts.map +1 -1
  367. package/dist/sync/scanners/b2.d.ts.map +1 -1
  368. package/dist/sync/scanners/b2.js +4 -2
  369. package/dist/sync/scanners/b2.js.map +1 -1
  370. package/dist/sync/scanners/local.cjs +150 -33
  371. package/dist/sync/scanners/local.cjs.map +1 -1
  372. package/dist/sync/scanners/local.d.cts +6 -0
  373. package/dist/sync/scanners/local.d.cts.map +1 -1
  374. package/dist/sync/scanners/local.d.ts +6 -0
  375. package/dist/sync/scanners/local.d.ts.map +1 -1
  376. package/dist/sync/scanners/local.js +150 -33
  377. package/dist/sync/scanners/local.js.map +1 -1
  378. package/dist/sync/synchronizer.cjs +79 -31
  379. package/dist/sync/synchronizer.cjs.map +1 -1
  380. package/dist/sync/synchronizer.d.cts +1 -0
  381. package/dist/sync/synchronizer.d.cts.map +1 -1
  382. package/dist/sync/synchronizer.d.ts +1 -0
  383. package/dist/sync/synchronizer.d.ts.map +1 -1
  384. package/dist/sync/synchronizer.js +79 -31
  385. package/dist/sync/synchronizer.js.map +1 -1
  386. package/dist/sync/types.d.cts +19 -3
  387. package/dist/sync/types.d.cts.map +1 -1
  388. package/dist/sync/types.d.ts +19 -3
  389. package/dist/sync/types.d.ts.map +1 -1
  390. package/dist/types/auth.cjs +4 -0
  391. package/dist/types/auth.cjs.map +1 -1
  392. package/dist/types/auth.d.cts +4 -0
  393. package/dist/types/auth.d.cts.map +1 -1
  394. package/dist/types/auth.d.ts +4 -0
  395. package/dist/types/auth.d.ts.map +1 -1
  396. package/dist/types/auth.js +4 -0
  397. package/dist/types/auth.js.map +1 -1
  398. package/dist/types/backup.d.cts +85 -0
  399. package/dist/types/backup.d.cts.map +1 -0
  400. package/dist/types/backup.d.ts +85 -0
  401. package/dist/types/backup.d.ts.map +1 -0
  402. package/dist/types/bucket.cjs +81 -11
  403. package/dist/types/bucket.cjs.map +1 -1
  404. package/dist/types/bucket.d.cts +194 -41
  405. package/dist/types/bucket.d.cts.map +1 -1
  406. package/dist/types/bucket.d.ts +194 -41
  407. package/dist/types/bucket.d.ts.map +1 -1
  408. package/dist/types/bucket.js +67 -12
  409. package/dist/types/bucket.js.map +1 -1
  410. package/dist/types/download.cjs +62 -0
  411. package/dist/types/download.cjs.map +1 -0
  412. package/dist/types/download.d.cts +100 -16
  413. package/dist/types/download.d.cts.map +1 -1
  414. package/dist/types/download.d.ts +100 -16
  415. package/dist/types/download.d.ts.map +1 -1
  416. package/dist/types/download.js +61 -0
  417. package/dist/types/download.js.map +1 -0
  418. package/dist/types/encryption.cjs +76 -229
  419. package/dist/types/encryption.cjs.map +1 -1
  420. package/dist/types/encryption.d.cts +48 -6
  421. package/dist/types/encryption.d.cts.map +1 -1
  422. package/dist/types/encryption.d.ts +48 -6
  423. package/dist/types/encryption.d.ts.map +1 -1
  424. package/dist/types/encryption.js +74 -229
  425. package/dist/types/encryption.js.map +1 -1
  426. package/dist/types/errors.cjs +9 -0
  427. package/dist/types/errors.cjs.map +1 -1
  428. package/dist/types/errors.d.cts +1 -1
  429. package/dist/types/errors.d.cts.map +1 -1
  430. package/dist/types/errors.d.ts +1 -1
  431. package/dist/types/errors.d.ts.map +1 -1
  432. package/dist/types/errors.js +9 -0
  433. package/dist/types/errors.js.map +1 -1
  434. package/dist/types/file.cjs +3 -0
  435. package/dist/types/file.cjs.map +1 -1
  436. package/dist/types/file.d.cts +140 -18
  437. package/dist/types/file.d.cts.map +1 -1
  438. package/dist/types/file.d.ts +140 -18
  439. package/dist/types/file.d.ts.map +1 -1
  440. package/dist/types/file.js +3 -1
  441. package/dist/types/file.js.map +1 -1
  442. package/dist/types/ids.cjs +30 -0
  443. package/dist/types/ids.cjs.map +1 -1
  444. package/dist/types/ids.d.cts +32 -0
  445. package/dist/types/ids.d.cts.map +1 -1
  446. package/dist/types/ids.d.ts +32 -0
  447. package/dist/types/ids.d.ts.map +1 -1
  448. package/dist/types/ids.js +28 -1
  449. package/dist/types/ids.js.map +1 -1
  450. package/dist/types/index.d.cts +16 -12
  451. package/dist/types/index.d.cts.map +1 -1
  452. package/dist/types/index.d.ts +16 -12
  453. package/dist/types/index.d.ts.map +1 -1
  454. package/dist/types/key.d.cts +4 -3
  455. package/dist/types/key.d.cts.map +1 -1
  456. package/dist/types/key.d.ts +4 -3
  457. package/dist/types/key.d.ts.map +1 -1
  458. package/dist/types/lock.cjs.map +1 -1
  459. package/dist/types/lock.d.cts +14 -0
  460. package/dist/types/lock.d.cts.map +1 -1
  461. package/dist/types/lock.d.ts +14 -0
  462. package/dist/types/lock.d.ts.map +1 -1
  463. package/dist/types/lock.js.map +1 -1
  464. package/dist/types/notifications.cjs +31 -1
  465. package/dist/types/notifications.cjs.map +1 -1
  466. package/dist/types/notifications.d.cts +31 -4
  467. package/dist/types/notifications.d.cts.map +1 -1
  468. package/dist/types/notifications.d.ts +31 -4
  469. package/dist/types/notifications.d.ts.map +1 -1
  470. package/dist/types/notifications.js +30 -2
  471. package/dist/types/notifications.js.map +1 -1
  472. package/dist/types/partner.cjs +32 -0
  473. package/dist/types/partner.cjs.map +1 -0
  474. package/dist/types/partner.d.cts +386 -0
  475. package/dist/types/partner.d.cts.map +1 -0
  476. package/dist/types/partner.d.ts +386 -0
  477. package/dist/types/partner.d.ts.map +1 -0
  478. package/dist/types/partner.js +29 -0
  479. package/dist/types/partner.js.map +1 -0
  480. package/dist/types/upload.d.cts +35 -18
  481. package/dist/types/upload.d.cts.map +1 -1
  482. package/dist/types/upload.d.ts +35 -18
  483. package/dist/types/upload.d.ts.map +1 -1
  484. package/dist/upload/abort-scope.cjs +0 -45
  485. package/dist/upload/abort-scope.cjs.map +1 -1
  486. package/dist/upload/abort-scope.d.cts +0 -22
  487. package/dist/upload/abort-scope.d.cts.map +1 -1
  488. package/dist/upload/abort-scope.d.ts +0 -22
  489. package/dist/upload/abort-scope.d.ts.map +1 -1
  490. package/dist/upload/abort-scope.js +1 -44
  491. package/dist/upload/abort-scope.js.map +1 -1
  492. package/dist/upload/finish.cjs +3 -8
  493. package/dist/upload/finish.cjs.map +1 -1
  494. package/dist/upload/finish.d.cts.map +1 -1
  495. package/dist/upload/finish.d.ts.map +1 -1
  496. package/dist/upload/finish.js +1 -6
  497. package/dist/upload/finish.js.map +1 -1
  498. package/dist/upload/large.cjs +15 -8
  499. package/dist/upload/large.cjs.map +1 -1
  500. package/dist/upload/large.d.cts +31 -8
  501. package/dist/upload/large.d.cts.map +1 -1
  502. package/dist/upload/large.d.ts +31 -8
  503. package/dist/upload/large.d.ts.map +1 -1
  504. package/dist/upload/large.js +15 -8
  505. package/dist/upload/large.js.map +1 -1
  506. package/dist/upload/options.cjs.map +1 -1
  507. package/dist/upload/options.d.cts +24 -0
  508. package/dist/upload/options.d.cts.map +1 -1
  509. package/dist/upload/options.d.ts +24 -0
  510. package/dist/upload/options.d.ts.map +1 -1
  511. package/dist/upload/options.js.map +1 -1
  512. package/dist/upload/resume.cjs +6 -4
  513. package/dist/upload/resume.cjs.map +1 -1
  514. package/dist/upload/resume.d.cts +9 -5
  515. package/dist/upload/resume.d.cts.map +1 -1
  516. package/dist/upload/resume.d.ts +9 -5
  517. package/dist/upload/resume.d.ts.map +1 -1
  518. package/dist/upload/resume.js +6 -4
  519. package/dist/upload/resume.js.map +1 -1
  520. package/dist/upload/retry.cjs +25 -13
  521. package/dist/upload/retry.cjs.map +1 -1
  522. package/dist/upload/retry.d.cts.map +1 -1
  523. package/dist/upload/retry.d.ts.map +1 -1
  524. package/dist/upload/retry.js +25 -13
  525. package/dist/upload/retry.js.map +1 -1
  526. package/dist/upload/single.cjs +35 -30
  527. package/dist/upload/single.cjs.map +1 -1
  528. package/dist/upload/single.d.cts +12 -0
  529. package/dist/upload/single.d.cts.map +1 -1
  530. package/dist/upload/single.d.ts +12 -0
  531. package/dist/upload/single.d.ts.map +1 -1
  532. package/dist/upload/single.js +35 -30
  533. package/dist/upload/single.js.map +1 -1
  534. package/dist/upload/stream.cjs +18 -5
  535. package/dist/upload/stream.cjs.map +1 -1
  536. package/dist/upload/stream.d.cts +12 -0
  537. package/dist/upload/stream.d.cts.map +1 -1
  538. package/dist/upload/stream.d.ts +12 -0
  539. package/dist/upload/stream.d.ts.map +1 -1
  540. package/dist/upload/stream.js +15 -2
  541. package/dist/upload/stream.js.map +1 -1
  542. package/dist/util/abort.cjs +114 -0
  543. package/dist/util/abort.cjs.map +1 -0
  544. package/dist/util/abort.d.cts +65 -0
  545. package/dist/util/abort.d.cts.map +1 -0
  546. package/dist/util/abort.d.ts +65 -0
  547. package/dist/util/abort.d.ts.map +1 -0
  548. package/dist/util/abort.js +109 -0
  549. package/dist/util/abort.js.map +1 -0
  550. package/dist/util/defaults.cjs +3 -0
  551. package/dist/util/defaults.cjs.map +1 -1
  552. package/dist/util/defaults.d.cts +2 -0
  553. package/dist/util/defaults.d.cts.map +1 -1
  554. package/dist/util/defaults.d.ts +2 -0
  555. package/dist/util/defaults.d.ts.map +1 -1
  556. package/dist/util/defaults.js +3 -1
  557. package/dist/util/defaults.js.map +1 -1
  558. package/dist/util/md5.cjs +211 -0
  559. package/dist/util/md5.cjs.map +1 -0
  560. package/dist/util/md5.d.cts +43 -0
  561. package/dist/util/md5.d.cts.map +1 -0
  562. package/dist/util/md5.d.ts +43 -0
  563. package/dist/util/md5.d.ts.map +1 -0
  564. package/dist/util/md5.js +209 -0
  565. package/dist/util/md5.js.map +1 -0
  566. package/dist/util/normalize.cjs +5 -5
  567. package/dist/util/normalize.cjs.map +1 -1
  568. package/dist/util/normalize.d.cts +7 -7
  569. package/dist/util/normalize.d.cts.map +1 -1
  570. package/dist/util/normalize.d.ts +7 -7
  571. package/dist/util/normalize.d.ts.map +1 -1
  572. package/dist/util/normalize.js +5 -5
  573. package/dist/util/normalize.js.map +1 -1
  574. package/dist/util/paginator.cjs +7 -1
  575. package/dist/util/paginator.cjs.map +1 -1
  576. package/dist/util/paginator.d.cts +3 -1
  577. package/dist/util/paginator.d.cts.map +1 -1
  578. package/dist/util/paginator.d.ts +3 -1
  579. package/dist/util/paginator.d.ts.map +1 -1
  580. package/dist/util/paginator.js +7 -1
  581. package/dist/util/paginator.js.map +1 -1
  582. package/dist/version.cjs +56 -4
  583. package/dist/version.cjs.map +1 -1
  584. package/dist/version.d.cts +53 -4
  585. package/dist/version.d.cts.map +1 -1
  586. package/dist/version.d.ts +53 -4
  587. package/dist/version.d.ts.map +1 -1
  588. package/dist/version.js +52 -5
  589. package/dist/version.js.map +1 -1
  590. package/package.json +47 -18
@@ -27,8 +27,20 @@ export interface UploadFileOptions extends UploadRetryOptions {
27
27
  readonly legalHold?: LegalHoldValue;
28
28
  /** Override the last-modified timestamp (epoch millis). */
29
29
  readonly lastModifiedMillis?: number;
30
+ /**
31
+ * B2 upload timestamp override in milliseconds since epoch.
32
+ * Sets the file version `uploadTimestamp`; distinct from `lastModifiedMillis` metadata.
33
+ * Requires B2 account enablement for Custom Upload Timestamp.
34
+ */
35
+ readonly customUploadTimestamp?: number;
30
36
  /** Callback invoked with upload progress updates. */
31
37
  readonly onProgress?: ProgressListener;
38
+ /**
39
+ * Minimum milliseconds between byte-only progress callbacks. Defaults to
40
+ * the SDK's 100 ms progress interval; set to 0 for per-chunk callbacks.
41
+ * Part-completion progress callbacks are always emitted immediately.
42
+ */
43
+ readonly progressIntervalMillis?: number;
32
44
  /** Signal to abort the upload. */
33
45
  readonly signal?: AbortSignal;
34
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../src/upload/single.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,KAAK,gBAAgB,EAAmB,MAAM,wBAAwB,CAAA;AAC/E,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,sBAAsB,CAAA;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAE1E,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,YAAY,CAAA;AAEnB,mEAAmE;AACnE,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,uCAAuC;IACvC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD,oDAAoD;IACpD,QAAQ,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAC3C,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAA;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IACpC,qDAAqD;IACrD,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CA6DtB"}
1
+ {"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../src/upload/single.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,KAAK,gBAAgB,EAAmB,MAAM,wBAAwB,CAAA;AAC/E,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,sBAAsB,CAAA;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAE1E,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,YAAY,CAAA;AAEnB,mEAAmE;AACnE,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,uCAAuC;IACvC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD,oDAAoD;IACpD,QAAQ,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAC3C,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAA;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IACpC;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;IACvC,qDAAqD;IACrD,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;IACxC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CA4EtB"}
@@ -27,8 +27,20 @@ export interface UploadFileOptions extends UploadRetryOptions {
27
27
  readonly legalHold?: LegalHoldValue;
28
28
  /** Override the last-modified timestamp (epoch millis). */
29
29
  readonly lastModifiedMillis?: number;
30
+ /**
31
+ * B2 upload timestamp override in milliseconds since epoch.
32
+ * Sets the file version `uploadTimestamp`; distinct from `lastModifiedMillis` metadata.
33
+ * Requires B2 account enablement for Custom Upload Timestamp.
34
+ */
35
+ readonly customUploadTimestamp?: number;
30
36
  /** Callback invoked with upload progress updates. */
31
37
  readonly onProgress?: ProgressListener;
38
+ /**
39
+ * Minimum milliseconds between byte-only progress callbacks. Defaults to
40
+ * the SDK's 100 ms progress interval; set to 0 for per-chunk callbacks.
41
+ * Part-completion progress callbacks are always emitted immediately.
42
+ */
43
+ readonly progressIntervalMillis?: number;
32
44
  /** Signal to abort the upload. */
33
45
  readonly signal?: AbortSignal;
34
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../src/upload/single.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,KAAK,gBAAgB,EAAmB,MAAM,wBAAwB,CAAA;AAC/E,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,sBAAsB,CAAA;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAE1E,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,YAAY,CAAA;AAEnB,mEAAmE;AACnE,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,uCAAuC;IACvC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD,oDAAoD;IACpD,QAAQ,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAC3C,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAA;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IACpC,qDAAqD;IACrD,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CA6DtB"}
1
+ {"version":3,"file":"single.d.ts","sourceRoot":"","sources":["../../src/upload/single.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EAAE,KAAK,gBAAgB,EAAmB,MAAM,wBAAwB,CAAA;AAC/E,OAAO,EAAE,KAAK,aAAa,EAAwB,MAAM,sBAAsB,CAAA;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAE1E,OAAO,EAGL,KAAK,kBAAkB,EAExB,MAAM,YAAY,CAAA;AAEnB,mEAAmE;AACnE,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,uCAAuC;IACvC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD,oDAAoD;IACpD,QAAQ,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAC3C,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAA;IACnC,2DAA2D;IAC3D,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAA;IACpC;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;IACvC,qDAAqD;IACrD,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;IACxC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CA4EtB"}
@@ -26,37 +26,42 @@ async function uploadSmallFile(raw, accountInfo, options) {
26
26
  const sha1 = new IncrementalSha1();
27
27
  await sha1.update(data);
28
28
  const sha1Hex = await sha1.digest();
29
- const tracker = new ProgressTracker(options.onProgress, data.byteLength, 1);
30
- const result = await withFreshUploadUrlRetry({
31
- fileName: options.fileName,
32
- partNumber: null,
33
- retry: options.retry,
34
- signal: options.signal,
35
- onUploadRetry: options.onUploadRetry,
36
- retryResponseBodyFailures: resolveRetryResponseBodyFailures(options.retryResponseBodyFailures),
37
- checkout: () => accountInfo.checkoutUploadUrl(options.bucketId),
38
- fetchFresh: () => fetchFreshUploadUrl(raw, accountInfo, options.bucketId, options.signal),
39
- returnEntry: (entry) => accountInfo.returnUploadUrl(options.bucketId, entry),
40
- evictEntry: (entry) => accountInfo.evictUploadUrl(options.bucketId, entry),
41
- upload: (entry) => raw.uploadFile(entry.uploadUrl, {
42
- authorization: entry.authorizationToken,
29
+ const tracker = new ProgressTracker(options.onProgress, data.byteLength, 1, { ...options.progressIntervalMillis !== void 0 ? { minIntervalMs: options.progressIntervalMillis } : {} });
30
+ try {
31
+ const result = await withFreshUploadUrlRetry({
43
32
  fileName: options.fileName,
44
- contentType: options.contentType ?? "b2/x-auto",
45
- contentLength: data.byteLength,
46
- contentSha1: sha1Hex,
47
- ...options.fileInfo !== void 0 ? { fileInfo: options.fileInfo } : {},
48
- ...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {},
49
- ...options.fileRetention !== void 0 ? { fileRetention: options.fileRetention } : {},
50
- ...options.legalHold !== void 0 ? { legalHold: options.legalHold } : {},
51
- ...options.lastModifiedMillis !== void 0 ? { lastModifiedMillis: options.lastModifiedMillis } : {}
52
- }, data, {
53
- ...options.signal !== void 0 ? { signal: options.signal } : {},
54
- ...options.retry !== void 0 ? { retry: options.retry } : {}
55
- })
56
- });
57
- tracker.addBytes(data.byteLength);
58
- tracker.completePart();
59
- return result;
33
+ partNumber: null,
34
+ retry: options.retry,
35
+ signal: options.signal,
36
+ onUploadRetry: options.onUploadRetry,
37
+ retryResponseBodyFailures: resolveRetryResponseBodyFailures(options.retryResponseBodyFailures),
38
+ checkout: () => accountInfo.checkoutUploadUrl(options.bucketId),
39
+ fetchFresh: () => fetchFreshUploadUrl(raw, accountInfo, options.bucketId, options.signal),
40
+ returnEntry: (entry) => accountInfo.returnUploadUrl(options.bucketId, entry),
41
+ evictEntry: (entry) => accountInfo.evictUploadUrl(options.bucketId, entry),
42
+ upload: (entry) => raw.uploadFile(entry.uploadUrl, {
43
+ authorization: entry.authorizationToken,
44
+ fileName: options.fileName,
45
+ contentType: options.contentType ?? "b2/x-auto",
46
+ contentLength: data.byteLength,
47
+ contentSha1: sha1Hex,
48
+ ...options.fileInfo !== void 0 ? { fileInfo: options.fileInfo } : {},
49
+ ...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {},
50
+ ...options.fileRetention !== void 0 ? { fileRetention: options.fileRetention } : {},
51
+ ...options.legalHold !== void 0 ? { legalHold: options.legalHold } : {},
52
+ ...options.lastModifiedMillis !== void 0 ? { lastModifiedMillis: options.lastModifiedMillis } : {},
53
+ ...options.customUploadTimestamp !== void 0 ? { customUploadTimestamp: options.customUploadTimestamp } : {}
54
+ }, data, {
55
+ ...options.signal !== void 0 ? { signal: options.signal } : {},
56
+ ...options.retry !== void 0 ? { retry: options.retry } : {}
57
+ })
58
+ });
59
+ tracker.addBytes(data.byteLength);
60
+ tracker.completePart();
61
+ return result;
62
+ } finally {
63
+ tracker.dispose();
64
+ }
60
65
  }
61
66
  async function readSmallFileSource(source, signal) {
62
67
  signal?.throwIfAborted();
@@ -1 +1 @@
1
- {"version":3,"file":"single.js","names":[],"sources":["../../src/upload/single.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport { IncrementalSha1 } from '../streams/hash.ts'\nimport { type ProgressListener, ProgressTracker } from '../streams/progress.ts'\nimport { type ContentSource, collectStreamExactly } from '../streams/source.ts'\nimport type { EncryptionSetting } from '../types/encryption.ts'\nimport type { FileVersion } from '../types/file.ts'\nimport type { BucketId } from '../types/ids.ts'\nimport type { FileRetentionValue, LegalHoldValue } from '../types/lock.ts'\nimport { DEFAULT_CONTENT_TYPE } from '../util/defaults.ts'\nimport {\n fetchFreshUploadUrl,\n resolveRetryResponseBodyFailures,\n type UploadRetryOptions,\n withFreshUploadUrlRetry,\n} from './retry.ts'\n\n/** Options for uploading a small file in a single HTTP request. */\nexport interface UploadFileOptions extends UploadRetryOptions {\n /** Target bucket for the upload. */\n readonly bucketId: BucketId\n /** Full B2 file name including any path prefix. */\n readonly fileName: string\n /** Content to upload. */\n readonly source: ContentSource\n /** MIME type. Defaults to `b2/x-auto` for server-side detection. */\n readonly contentType?: string\n /** Custom file info key/value pairs stored with the file. */\n readonly fileInfo?: Record<string, string>\n /** Server-side encryption settings. */\n readonly serverSideEncryption?: EncryptionSetting\n /** File retention policy applied at upload time. */\n readonly fileRetention?: FileRetentionValue\n /** Legal hold status applied at upload time. */\n readonly legalHold?: LegalHoldValue\n /** Override the last-modified timestamp (epoch millis). */\n readonly lastModifiedMillis?: number\n /** Callback invoked with upload progress updates. */\n readonly onProgress?: ProgressListener\n /** Signal to abort the upload. */\n readonly signal?: AbortSignal\n}\n\n/**\n * Uploads a file in a single HTTP request (suitable for files up to ~100 MB).\n *\n * The entire file content is read into memory, SHA-1 hashed, and sent in one\n * `b2_upload_file` call. For files larger than the recommended part size, use\n * {@link uploadLargeFile} which splits the file into parts uploaded in parallel.\n *\n * Upload URLs are pooled via {@link AccountInfo} and recycled on success or\n * evicted on failure.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state (tokens, URLs, upload URL pool).\n * @param options - Upload parameters.\n *\n * @returns The resulting {@link FileVersion} metadata.\n */\nexport async function uploadSmallFile(\n raw: RawClient,\n accountInfo: AccountInfo,\n options: UploadFileOptions,\n): Promise<FileVersion> {\n const data = await readSmallFileSource(options.source, options.signal)\n if (data.byteLength !== options.source.size) {\n throw new Error(\n `uploadSmallFile: source byte count does not match advertised size ` +\n `(expected ${options.source.size} bytes, got ${data.byteLength} bytes).`,\n )\n }\n const sha1 = new IncrementalSha1()\n await sha1.update(data)\n const sha1Hex = await sha1.digest()\n\n // Single-request uploads send the whole payload in one shot, so the\n // tracker reports a single \"part\" worth of progress: one byte burst at\n // completion and a parts-completed transition from 0 → 1. The tracker\n // is created (rather than calling the listener directly) so consumers\n // see the same {bytesTransferred, totalBytes, partsCompleted,\n // totalParts, elapsedMs} shape they get from `uploadLargeFile`.\n const tracker = new ProgressTracker(options.onProgress, data.byteLength, 1)\n\n const result = await withFreshUploadUrlRetry({\n fileName: options.fileName,\n partNumber: null,\n retry: options.retry,\n signal: options.signal,\n onUploadRetry: options.onUploadRetry,\n retryResponseBodyFailures: resolveRetryResponseBodyFailures(options.retryResponseBodyFailures),\n checkout: () => accountInfo.checkoutUploadUrl(options.bucketId),\n fetchFresh: () => fetchFreshUploadUrl(raw, accountInfo, options.bucketId, options.signal),\n returnEntry: (entry) => accountInfo.returnUploadUrl(options.bucketId, entry),\n evictEntry: (entry) => accountInfo.evictUploadUrl(options.bucketId, entry),\n upload: (entry) =>\n raw.uploadFile(\n entry.uploadUrl,\n {\n authorization: entry.authorizationToken,\n fileName: options.fileName,\n contentType: options.contentType ?? DEFAULT_CONTENT_TYPE,\n contentLength: data.byteLength,\n contentSha1: sha1Hex,\n ...(options.fileInfo !== undefined ? { fileInfo: options.fileInfo } : {}),\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n ...(options.fileRetention !== undefined ? { fileRetention: options.fileRetention } : {}),\n ...(options.legalHold !== undefined ? { legalHold: options.legalHold } : {}),\n ...(options.lastModifiedMillis !== undefined\n ? { lastModifiedMillis: options.lastModifiedMillis }\n : {}),\n },\n data,\n {\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.retry !== undefined ? { retry: options.retry } : {}),\n },\n ),\n })\n\n tracker.addBytes(data.byteLength)\n tracker.completePart()\n return result\n}\n\nasync function readSmallFileSource(\n source: ContentSource,\n signal: AbortSignal | undefined,\n): Promise<Uint8Array<ArrayBuffer>> {\n signal?.throwIfAborted()\n if (!source.canSlice) {\n return collectStreamExactly(source.stream(), source.size, signal)\n }\n const data = new Uint8Array(\n await (signal === undefined ? source.toArrayBuffer() : source.toArrayBuffer({ signal })),\n )\n signal?.throwIfAborted()\n return data\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA2DA,eAAsB,gBACpB,KACA,aACA,SACsB;CACtB,MAAM,OAAO,MAAM,oBAAoB,QAAQ,QAAQ,QAAQ,MAAM;CACrE,IAAI,KAAK,eAAe,QAAQ,OAAO,MACrC,MAAM,IAAI,MACR,+EACe,QAAQ,OAAO,KAAK,cAAc,KAAK,WAAW,SACnE;CAEF,MAAM,OAAO,IAAI,gBAAgB;CACjC,MAAM,KAAK,OAAO,IAAI;CACtB,MAAM,UAAU,MAAM,KAAK,OAAO;CAQlC,MAAM,UAAU,IAAI,gBAAgB,QAAQ,YAAY,KAAK,YAAY,CAAC;CAE1E,MAAM,SAAS,MAAM,wBAAwB;EAC3C,UAAU,QAAQ;EAClB,YAAY;EACZ,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAChB,eAAe,QAAQ;EACvB,2BAA2B,iCAAiC,QAAQ,yBAAyB;EAC7F,gBAAgB,YAAY,kBAAkB,QAAQ,QAAQ;EAC9D,kBAAkB,oBAAoB,KAAK,aAAa,QAAQ,UAAU,QAAQ,MAAM;EACxF,cAAc,UAAU,YAAY,gBAAgB,QAAQ,UAAU,KAAK;EAC3E,aAAa,UAAU,YAAY,eAAe,QAAQ,UAAU,KAAK;EACzE,SAAS,UACP,IAAI,WACF,MAAM,WACN;GACE,eAAe,MAAM;GACrB,UAAU,QAAQ;GAClB,aAAa,QAAQ,eAAA;GACrB,eAAe,KAAK;GACpB,aAAa;GACb,GAAI,QAAQ,aAAa,KAAA,IAAY,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;GACvE,GAAI,QAAQ,yBAAyB,KAAA,IACjC,EAAE,sBAAsB,QAAQ,qBAAqB,IACrD,CAAC;GACL,GAAI,QAAQ,kBAAkB,KAAA,IAAY,EAAE,eAAe,QAAQ,cAAc,IAAI,CAAC;GACtF,GAAI,QAAQ,cAAc,KAAA,IAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;GAC1E,GAAI,QAAQ,uBAAuB,KAAA,IAC/B,EAAE,oBAAoB,QAAQ,mBAAmB,IACjD,CAAC;EACP,GACA,MACA;GACE,GAAI,QAAQ,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;GACjE,GAAI,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;EAChE,CACF;CACJ,CAAC;CAED,QAAQ,SAAS,KAAK,UAAU;CAChC,QAAQ,aAAa;CACrB,OAAO;AACT;AAEA,eAAe,oBACb,QACA,QACkC;CAClC,QAAQ,eAAe;CACvB,IAAI,CAAC,OAAO,UACV,OAAO,qBAAqB,OAAO,OAAO,GAAG,OAAO,MAAM,MAAM;CAElE,MAAM,OAAO,IAAI,WACf,OAAO,WAAW,KAAA,IAAY,OAAO,cAAc,IAAI,OAAO,cAAc,EAAE,OAAO,CAAC,EACxF;CACA,QAAQ,eAAe;CACvB,OAAO;AACT"}
1
+ {"version":3,"file":"single.js","names":[],"sources":["../../src/upload/single.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport { IncrementalSha1 } from '../streams/hash.ts'\nimport { type ProgressListener, ProgressTracker } from '../streams/progress.ts'\nimport { type ContentSource, collectStreamExactly } from '../streams/source.ts'\nimport type { EncryptionSetting } from '../types/encryption.ts'\nimport type { FileVersion } from '../types/file.ts'\nimport type { BucketId } from '../types/ids.ts'\nimport type { FileRetentionValue, LegalHoldValue } from '../types/lock.ts'\nimport { DEFAULT_CONTENT_TYPE } from '../util/defaults.ts'\nimport {\n fetchFreshUploadUrl,\n resolveRetryResponseBodyFailures,\n type UploadRetryOptions,\n withFreshUploadUrlRetry,\n} from './retry.ts'\n\n/** Options for uploading a small file in a single HTTP request. */\nexport interface UploadFileOptions extends UploadRetryOptions {\n /** Target bucket for the upload. */\n readonly bucketId: BucketId\n /** Full B2 file name including any path prefix. */\n readonly fileName: string\n /** Content to upload. */\n readonly source: ContentSource\n /** MIME type. Defaults to `b2/x-auto` for server-side detection. */\n readonly contentType?: string\n /** Custom file info key/value pairs stored with the file. */\n readonly fileInfo?: Record<string, string>\n /** Server-side encryption settings. */\n readonly serverSideEncryption?: EncryptionSetting\n /** File retention policy applied at upload time. */\n readonly fileRetention?: FileRetentionValue\n /** Legal hold status applied at upload time. */\n readonly legalHold?: LegalHoldValue\n /** Override the last-modified timestamp (epoch millis). */\n readonly lastModifiedMillis?: number\n /**\n * B2 upload timestamp override in milliseconds since epoch.\n * Sets the file version `uploadTimestamp`; distinct from `lastModifiedMillis` metadata.\n * Requires B2 account enablement for Custom Upload Timestamp.\n */\n readonly customUploadTimestamp?: number\n /** Callback invoked with upload progress updates. */\n readonly onProgress?: ProgressListener\n /**\n * Minimum milliseconds between byte-only progress callbacks. Defaults to\n * the SDK's 100 ms progress interval; set to 0 for per-chunk callbacks.\n * Part-completion progress callbacks are always emitted immediately.\n */\n readonly progressIntervalMillis?: number\n /** Signal to abort the upload. */\n readonly signal?: AbortSignal\n}\n\n/**\n * Uploads a file in a single HTTP request (suitable for files up to ~100 MB).\n *\n * The entire file content is read into memory, SHA-1 hashed, and sent in one\n * `b2_upload_file` call. For files larger than the recommended part size, use\n * {@link uploadLargeFile} which splits the file into parts uploaded in parallel.\n *\n * Upload URLs are pooled via {@link AccountInfo} and recycled on success or\n * evicted on failure.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state (tokens, URLs, upload URL pool).\n * @param options - Upload parameters.\n *\n * @returns The resulting {@link FileVersion} metadata.\n */\nexport async function uploadSmallFile(\n raw: RawClient,\n accountInfo: AccountInfo,\n options: UploadFileOptions,\n): Promise<FileVersion> {\n const data = await readSmallFileSource(options.source, options.signal)\n if (data.byteLength !== options.source.size) {\n throw new Error(\n `uploadSmallFile: source byte count does not match advertised size ` +\n `(expected ${options.source.size} bytes, got ${data.byteLength} bytes).`,\n )\n }\n const sha1 = new IncrementalSha1()\n await sha1.update(data)\n const sha1Hex = await sha1.digest()\n\n // Single-request uploads send the whole payload in one shot, so the\n // tracker reports a single \"part\" worth of progress: one byte burst at\n // completion and a parts-completed transition from 0 → 1. The tracker\n // is created (rather than calling the listener directly) so consumers\n // see the same {bytesTransferred, totalBytes, partsCompleted,\n // totalParts, elapsedMs} shape they get from `uploadLargeFile`.\n const tracker = new ProgressTracker(options.onProgress, data.byteLength, 1, {\n ...(options.progressIntervalMillis !== undefined\n ? { minIntervalMs: options.progressIntervalMillis }\n : {}),\n })\n\n try {\n const result = await withFreshUploadUrlRetry({\n fileName: options.fileName,\n partNumber: null,\n retry: options.retry,\n signal: options.signal,\n onUploadRetry: options.onUploadRetry,\n retryResponseBodyFailures: resolveRetryResponseBodyFailures(\n options.retryResponseBodyFailures,\n ),\n checkout: () => accountInfo.checkoutUploadUrl(options.bucketId),\n fetchFresh: () => fetchFreshUploadUrl(raw, accountInfo, options.bucketId, options.signal),\n returnEntry: (entry) => accountInfo.returnUploadUrl(options.bucketId, entry),\n evictEntry: (entry) => accountInfo.evictUploadUrl(options.bucketId, entry),\n upload: (entry) =>\n raw.uploadFile(\n entry.uploadUrl,\n {\n authorization: entry.authorizationToken,\n fileName: options.fileName,\n contentType: options.contentType ?? DEFAULT_CONTENT_TYPE,\n contentLength: data.byteLength,\n contentSha1: sha1Hex,\n ...(options.fileInfo !== undefined ? { fileInfo: options.fileInfo } : {}),\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n ...(options.fileRetention !== undefined\n ? { fileRetention: options.fileRetention }\n : {}),\n ...(options.legalHold !== undefined ? { legalHold: options.legalHold } : {}),\n ...(options.lastModifiedMillis !== undefined\n ? { lastModifiedMillis: options.lastModifiedMillis }\n : {}),\n ...(options.customUploadTimestamp !== undefined\n ? { customUploadTimestamp: options.customUploadTimestamp }\n : {}),\n },\n data,\n {\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.retry !== undefined ? { retry: options.retry } : {}),\n },\n ),\n })\n\n tracker.addBytes(data.byteLength)\n tracker.completePart()\n return result\n } finally {\n tracker.dispose()\n }\n}\n\nasync function readSmallFileSource(\n source: ContentSource,\n signal: AbortSignal | undefined,\n): Promise<Uint8Array<ArrayBuffer>> {\n signal?.throwIfAborted()\n if (!source.canSlice) {\n return collectStreamExactly(source.stream(), source.size, signal)\n }\n const data = new Uint8Array(\n await (signal === undefined ? source.toArrayBuffer() : source.toArrayBuffer({ signal })),\n )\n signal?.throwIfAborted()\n return data\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuEA,eAAsB,gBACpB,KACA,aACA,SACsB;CACtB,MAAM,OAAO,MAAM,oBAAoB,QAAQ,QAAQ,QAAQ,MAAM;CACrE,IAAI,KAAK,eAAe,QAAQ,OAAO,MACrC,MAAM,IAAI,MACR,+EACe,QAAQ,OAAO,KAAK,cAAc,KAAK,WAAW,SACnE;CAEF,MAAM,OAAO,IAAI,gBAAgB;CACjC,MAAM,KAAK,OAAO,IAAI;CACtB,MAAM,UAAU,MAAM,KAAK,OAAO;CAQlC,MAAM,UAAU,IAAI,gBAAgB,QAAQ,YAAY,KAAK,YAAY,GAAG,EAC1E,GAAI,QAAQ,2BAA2B,KAAA,IACnC,EAAE,eAAe,QAAQ,uBAAuB,IAChD,CAAC,EACP,CAAC;CAED,IAAI;EACF,MAAM,SAAS,MAAM,wBAAwB;GAC3C,UAAU,QAAQ;GAClB,YAAY;GACZ,OAAO,QAAQ;GACf,QAAQ,QAAQ;GAChB,eAAe,QAAQ;GACvB,2BAA2B,iCACzB,QAAQ,yBACV;GACA,gBAAgB,YAAY,kBAAkB,QAAQ,QAAQ;GAC9D,kBAAkB,oBAAoB,KAAK,aAAa,QAAQ,UAAU,QAAQ,MAAM;GACxF,cAAc,UAAU,YAAY,gBAAgB,QAAQ,UAAU,KAAK;GAC3E,aAAa,UAAU,YAAY,eAAe,QAAQ,UAAU,KAAK;GACzE,SAAS,UACP,IAAI,WACF,MAAM,WACN;IACE,eAAe,MAAM;IACrB,UAAU,QAAQ;IAClB,aAAa,QAAQ,eAAA;IACrB,eAAe,KAAK;IACpB,aAAa;IACb,GAAI,QAAQ,aAAa,KAAA,IAAY,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;IACvE,GAAI,QAAQ,yBAAyB,KAAA,IACjC,EAAE,sBAAsB,QAAQ,qBAAqB,IACrD,CAAC;IACL,GAAI,QAAQ,kBAAkB,KAAA,IAC1B,EAAE,eAAe,QAAQ,cAAc,IACvC,CAAC;IACL,GAAI,QAAQ,cAAc,KAAA,IAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;IAC1E,GAAI,QAAQ,uBAAuB,KAAA,IAC/B,EAAE,oBAAoB,QAAQ,mBAAmB,IACjD,CAAC;IACL,GAAI,QAAQ,0BAA0B,KAAA,IAClC,EAAE,uBAAuB,QAAQ,sBAAsB,IACvD,CAAC;GACP,GACA,MACA;IACE,GAAI,QAAQ,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;IACjE,GAAI,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;GAChE,CACF;EACJ,CAAC;EAED,QAAQ,SAAS,KAAK,UAAU;EAChC,QAAQ,aAAa;EACrB,OAAO;CACT,UAAU;EACR,QAAQ,QAAQ;CAClB;AACF;AAEA,eAAe,oBACb,QACA,QACkC;CAClC,QAAQ,eAAe;CACvB,IAAI,CAAC,OAAO,UACV,OAAO,qBAAqB,OAAO,OAAO,GAAG,OAAO,MAAM,MAAM;CAElE,MAAM,OAAO,IAAI,WACf,OAAO,WAAW,KAAA,IAAY,OAAO,cAAc,IAAI,OAAO,cAAc,EAAE,OAAO,CAAC,EACxF;CACA,QAAQ,eAAe;CACvB,OAAO;AACT"}
@@ -1,6 +1,7 @@
1
1
  const require_abort_scope = require("./abort-scope.cjs");
2
2
  const require_cancel = require("./cancel.cjs");
3
3
  const require_concurrency = require("./concurrency.cjs");
4
+ const require_abort = require("../util/abort.cjs");
4
5
  const require_finish = require("./finish.cjs");
5
6
  require("../util/defaults.cjs");
6
7
  const require_progress = require("../streams/progress.cjs");
@@ -29,7 +30,7 @@ function createWriteStream(raw, accountInfo, options) {
29
30
  const recommendedPartSize = accountInfo.getRecommendedPartSize();
30
31
  const partSize = Math.max(options.partSize ?? recommendedPartSize, minPartSize);
31
32
  const concurrency = options.concurrency ?? 4;
32
- const tracker = new require_progress.ProgressTracker(options.onProgress, null, null);
33
+ const tracker = new require_progress.ProgressTracker(options.onProgress, null, null, { ...options.progressIntervalMillis !== void 0 ? { minIntervalMs: options.progressIntervalMillis } : {} });
33
34
  const sem = new require_concurrency.Semaphore(concurrency);
34
35
  const abortScope = require_abort_scope.createAbortScope(options.signal);
35
36
  let largeFileId = null;
@@ -50,6 +51,7 @@ function createWriteStream(raw, accountInfo, options) {
50
51
  fileName: options.fileName,
51
52
  contentType: options.contentType ?? "b2/x-auto",
52
53
  fileInfo: options.fileInfo ?? {},
54
+ ...options.customUploadTimestamp !== void 0 ? { customUploadTimestamp: String(options.customUploadTimestamp) } : {},
53
55
  ...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {}
54
56
  }, {
55
57
  signal: abortScope.signal,
@@ -60,7 +62,7 @@ function createWriteStream(raw, accountInfo, options) {
60
62
  return largeFileId;
61
63
  });
62
64
  const started = startPromise;
63
- return require_abort_scope.raceWithAbort(started, abortScope.signal).catch((err) => {
65
+ return require_abort.raceWithAbort(started, abortScope.signal).catch((err) => {
64
66
  if (abortScope.signal.aborted) scheduleCancelLargeFileAfterStart(started);
65
67
  throw err;
66
68
  });
@@ -94,6 +96,7 @@ function createWriteStream(raw, accountInfo, options) {
94
96
  function markErrored(err) {
95
97
  const error = require_to_error.toError(err);
96
98
  errored = error;
99
+ tracker.dispose();
97
100
  abortScope.abort(error);
98
101
  return error;
99
102
  }
@@ -114,7 +117,7 @@ function createWriteStream(raw, accountInfo, options) {
114
117
  settled.then(() => "settled"),
115
118
  startPromise.then(() => "start-settled", () => "start-settled"),
116
119
  abortWaiter.promise.then(() => "aborted")
117
- ]) === "aborted" && largeFileId === null) throw require_abort_scope.abortReason(abortScope.signal);
120
+ ]) === "aborted" && largeFileId === null) throw require_abort.abortReason(abortScope.signal);
118
121
  return await settled;
119
122
  } finally {
120
123
  abortWaiter.dispose();
@@ -148,6 +151,7 @@ function createWriteStream(raw, accountInfo, options) {
148
151
  }
149
152
  }
150
153
  async function waitForInflightPartsToSettle(timeoutMs = require_cancel.DEFAULT_CLEANUP_TIMEOUT_MS) {
154
+ /* v8 ignore next -- only called after a large file exists, which requires at least one part */
151
155
  if (inflight.length === 0) return;
152
156
  let timeout;
153
157
  try {
@@ -155,15 +159,18 @@ function createWriteStream(raw, accountInfo, options) {
155
159
  timeout = setTimeout(resolve, timeoutMs);
156
160
  })]);
157
161
  } finally {
162
+ /* v8 ignore next -- setTimeout is assigned synchronously when the race promise is built */
158
163
  if (timeout !== void 0) clearTimeout(timeout);
159
164
  }
160
165
  }
161
166
  async function dispatchPart() {
167
+ /* v8 ignore next -- callers guard on pendingBytes before dispatching the final part */
162
168
  if (pending.length === 0) return;
163
169
  await acquirePartSlot();
164
170
  let data;
165
171
  if (pending.length === 1) {
166
172
  const head = pending[0];
173
+ /* v8 ignore next -- pending is never sparse; this narrows noUncheckedIndexedAccess */
167
174
  if (!head) {
168
175
  sem.release();
169
176
  return;
@@ -220,11 +227,13 @@ function createWriteStream(raw, accountInfo, options) {
220
227
  signal: abortScope.signal,
221
228
  ...options.retry !== void 0 ? { retry: options.retry } : {}
222
229
  });
230
+ tracker.dispose();
223
231
  abortScope.dispose();
224
232
  resolveDone(result);
225
233
  } catch (err) {
226
234
  const closeError = require_to_error.toError(err);
227
235
  if (errored === null) errored = closeError;
236
+ tracker.dispose();
228
237
  abortScope.abort(errored);
229
238
  const observedError = errored;
230
239
  const fileIdToCancel = largeFileId;
@@ -258,6 +267,7 @@ function createWriteStream(raw, accountInfo, options) {
258
267
  await waitForInflightPartsToSettle();
259
268
  await require_cancel.cancelLargeFileBestEffort(raw, accountInfo, fileIdToCancel, cleanupWriteStreamOptions(options));
260
269
  }
270
+ tracker.dispose();
261
271
  abortScope.dispose();
262
272
  rejectDone(abortError);
263
273
  }
@@ -286,6 +296,7 @@ function carveExact(chunks, size) {
286
296
  let written = 0;
287
297
  while (written < size && chunks.length > 0) {
288
298
  const head = chunks[0];
299
+ /* v8 ignore next -- chunks is never sparse; this narrows noUncheckedIndexedAccess */
289
300
  if (!head) break;
290
301
  const need = size - written;
291
302
  if (head.byteLength <= need) {
@@ -301,17 +312,19 @@ function carveExact(chunks, size) {
301
312
  return out;
302
313
  }
303
314
  function waitForAbort(signal) {
315
+ /* v8 ignore next -- callers check abort before entering the start/close wait race */
304
316
  if (signal.aborted) return {
305
- promise: Promise.resolve(require_abort_scope.abortReason(signal)),
317
+ promise: Promise.resolve(require_abort.abortReason(signal)),
306
318
  dispose() {}
307
319
  };
308
320
  let onAbort;
309
321
  return {
310
322
  promise: new Promise((resolve) => {
311
- onAbort = () => resolve(require_abort_scope.abortReason(signal));
323
+ onAbort = () => resolve(require_abort.abortReason(signal));
312
324
  signal.addEventListener("abort", onAbort, { once: true });
313
325
  }),
314
326
  dispose() {
327
+ /* v8 ignore next -- listener is assigned synchronously with promise construction */
315
328
  if (onAbort !== void 0) signal.removeEventListener("abort", onAbort);
316
329
  }
317
330
  };
@@ -1 +1 @@
1
- {"version":3,"file":"stream.cjs","names":[],"sources":["../../src/upload/stream.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport { IncrementalSha1 } from '../streams/hash.ts'\nimport type { ProgressListener } from '../streams/progress.ts'\nimport { ProgressTracker } from '../streams/progress.ts'\nimport type { EncryptionSetting } from '../types/encryption.ts'\nimport type { FileVersion } from '../types/file.ts'\nimport type { BucketId, LargeFileId } from '../types/ids.ts'\nimport { DEFAULT_CONTENT_TYPE, DEFAULT_TRANSFER_CONCURRENCY } from '../util/defaults.ts'\nimport { toError } from '../util/to-error.ts'\nimport { abortReason, createAbortScope, raceWithAbort } from './abort-scope.ts'\nimport {\n type CleanupFailureOptions,\n cancelLargeFileBestEffort,\n DEFAULT_CLEANUP_TIMEOUT_MS,\n resolveLargeFileErrorAfterCleanup,\n} from './cancel.ts'\nimport { Semaphore } from './concurrency.ts'\nimport { finishLargeFileWithAbortReconciliation } from './finish.ts'\nimport {\n resolveRetryResponseBodyFailures,\n type UploadRetryOptions,\n uploadPartWithFreshUrl,\n} from './retry.ts'\n\n/** Options for creating a streaming multipart upload sink. */\nexport interface CreateWriteStreamOptions extends UploadRetryOptions, CleanupFailureOptions {\n /** Target bucket for the upload. */\n readonly bucketId: BucketId\n /** Destination file name in the bucket. */\n readonly fileName: string\n /** MIME type. Defaults to `b2/x-auto`. */\n readonly contentType?: string\n /** Custom file info stored with the file. */\n readonly fileInfo?: Record<string, string>\n /** Server-side encryption applied to each part. */\n readonly serverSideEncryption?: EncryptionSetting\n /**\n * Target part size in bytes. The stream buffers writes until this many bytes\n * are accumulated, then ships a part. Must be at least the account's\n * absolute minimum part size; the implementation will raise it if too small.\n */\n readonly partSize?: number\n /** Maximum number of parts uploaded in parallel. Defaults to 4. */\n readonly concurrency?: number\n /** Callback invoked with upload progress events. `totalBytes` is `null` (size unknown). */\n readonly onProgress?: ProgressListener\n /** Aborts the upload and cancels the unfinished large file. */\n readonly signal?: AbortSignal\n}\n\n/**\n * Handle returned by `B2Object.createWriteStream`: the Web `WritableStream` to\n * pipe data into, plus a promise that resolves with the finished\n * {@link FileVersion} once the stream is closed and all parts have been\n * uploaded.\n */\nexport interface UploadWriteHandle {\n /** Web `WritableStream` sink to pipe data into. */\n readonly writable: WritableStream<Uint8Array>\n /** Resolves with the finalized file version when the stream closes successfully. */\n readonly done: Promise<FileVersion>\n}\n\n/**\n * Creates a {@link WritableStream} that streams data into a B2 multipart upload.\n *\n * Buffers incoming chunks until `partSize` bytes are accumulated, ships each\n * complete part through the standard multipart engine, and finalizes the file\n * once the stream is closed. Honours backpressure via the queue's bounded\n * concurrency. Streaming uploads do not support resume because the total size\n * and per-part hashes aren't known in advance; use {@link uploadLargeFile} with\n * a buffered source when resume is required.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state (tokens, URLs, part URL pool).\n * @param options - Streaming upload parameters.\n *\n * @returns A {@link UploadWriteHandle} with the writable sink and a completion promise.\n */\nexport function createWriteStream(\n raw: RawClient,\n accountInfo: AccountInfo,\n options: CreateWriteStreamOptions,\n): UploadWriteHandle {\n const minPartSize = accountInfo.getAbsoluteMinimumPartSize()\n const recommendedPartSize = accountInfo.getRecommendedPartSize()\n const partSize = Math.max(options.partSize ?? recommendedPartSize, minPartSize)\n const concurrency = options.concurrency ?? DEFAULT_TRANSFER_CONCURRENCY\n const tracker = new ProgressTracker(options.onProgress, null, null)\n const sem = new Semaphore(concurrency)\n const abortScope = createAbortScope(options.signal)\n\n let largeFileId: LargeFileId | null = null\n let startPromise: Promise<LargeFileId> | null = null\n let cancelAfterStartScheduled = false\n let nextPartNumber = 1\n let pendingBytes = 0\n const pending: Uint8Array[] = []\n const partSha1s: string[] = []\n const inflight: Promise<void>[] = []\n let errored: Error | null = null\n\n // ES2024 `Promise.withResolvers()` exposes the resolve/reject pair as\n // properties of the returned object, avoiding the `let resolve!:` /\n // `let reject!:` non-null-assertion pattern needed before this API\n // existed. Available in Node 22 (our minimum), Bun, Deno, modern\n // browsers, and Cloudflare Workers.\n const {\n promise: done,\n resolve: resolveDone,\n reject: rejectDone,\n } = Promise.withResolvers<FileVersion>()\n // Attach a no-op rejection handler so a `done` that rejects before the\n // caller observes it never surfaces as a process-level unhandled rejection.\n // The error is not swallowed: `close()`/`abort()` also reject the writable\n // (so `pipeTo`/`getWriter().close()` throw), and any later `await done` /\n // `done.then(onRejected)` the caller attaches still sees the rejection —\n // extra handlers on the same promise all fire. Mirrors the\n // `task.catch(() => {})` pattern used for inflight part uploads below, and\n // keeps the engine well-behaved under Bun and Node's strict\n // unhandled-rejection mode.\n done.catch(() => {})\n\n function ensureStarted(): Promise<LargeFileId> {\n if (largeFileId !== null) return Promise.resolve(largeFileId)\n if (startPromise === null) {\n const rawStart = raw.startLargeFile(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n {\n bucketId: options.bucketId,\n fileName: options.fileName,\n contentType: options.contentType ?? DEFAULT_CONTENT_TYPE,\n fileInfo: options.fileInfo ?? {},\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n },\n {\n signal: abortScope.signal,\n ...(options.retry !== undefined ? { retry: options.retry } : {}),\n },\n )\n startPromise = rawStart.then((resp) => {\n largeFileId = resp.fileId\n if (abortScope.signal.aborted || errored !== null) {\n cancelStartedLargeFile(largeFileId)\n }\n return largeFileId\n })\n }\n const started = startPromise\n return raceWithAbort(started, abortScope.signal).catch((err) => {\n if (abortScope.signal.aborted) scheduleCancelLargeFileAfterStart(started)\n throw err\n })\n }\n\n async function shipPart(data: Uint8Array, partNumber: number): Promise<void> {\n if (errored !== null) throw errored\n abortScope.signal.throwIfAborted()\n const fileId = await ensureStarted()\n if (errored !== null) throw errored\n abortScope.signal.throwIfAborted()\n\n const sha1 = new IncrementalSha1()\n await sha1.update(data)\n const sha1Hex = await sha1.digest()\n abortScope.signal.throwIfAborted()\n\n const result = await uploadPartWithFreshUrl(raw, accountInfo, fileId, {\n fileName: options.fileName,\n partNumber,\n data: data as BodyInit,\n contentLength: data.byteLength,\n contentSha1: sha1Hex,\n retry: options.retry,\n signal: abortScope.signal,\n onUploadRetry: options.onUploadRetry,\n retryResponseBodyFailures: resolveRetryResponseBodyFailures(\n options.retryResponseBodyFailures,\n ),\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n })\n partSha1s[partNumber - 1] = result.contentSha1\n tracker.addBytes(data.byteLength)\n tracker.completePart()\n }\n\n function markErrored(err: unknown): Error {\n const error = toError(err)\n errored = error\n abortScope.abort(error)\n return error\n }\n\n function cancelStartedLargeFile(fileId: LargeFileId): void {\n if (cancelAfterStartScheduled) return\n cancelAfterStartScheduled = true\n void cancelLargeFileBestEffort(raw, accountInfo, fileId, cleanupWriteStreamOptions(options))\n }\n\n function scheduleCancelLargeFileAfterStart(started: Promise<LargeFileId>): void {\n void started\n .then((fileId) => cancelStartedLargeFile(fileId))\n .catch(() => {\n // If start failed, no file ID is available to cancel.\n })\n }\n\n async function settleInflightForClose(): Promise<PromiseSettledResult<void>[]> {\n const settled = Promise.allSettled(inflight)\n if (startPromise === null || largeFileId !== null) return await settled\n\n const abortWaiter = waitForAbort(abortScope.signal)\n try {\n const first = await Promise.race([\n settled.then(() => 'settled' as const),\n startPromise.then(\n () => 'start-settled' as const,\n () => 'start-settled' as const,\n ),\n abortWaiter.promise.then(() => 'aborted' as const),\n ])\n if (first === 'aborted' && largeFileId === null) {\n throw abortReason(abortScope.signal)\n }\n return await settled\n } finally {\n abortWaiter.dispose()\n }\n }\n\n function startPartWithAcquiredSlot(data: Uint8Array, partNumber: number): void {\n const task = (async () => {\n try {\n await shipPart(data, partNumber)\n } catch (err) {\n markErrored(err)\n throw err\n } finally {\n sem.release()\n }\n })()\n inflight.push(task)\n // Swallow rejection here; we check `errored` later.\n task.catch(() => {})\n }\n\n async function acquirePartSlot(): Promise<void> {\n await sem.acquire()\n if (errored !== null) {\n sem.release()\n throw errored\n }\n try {\n abortScope.signal.throwIfAborted()\n } catch (err) {\n sem.release()\n throw err\n }\n }\n\n async function waitForInflightPartsToSettle(\n timeoutMs = DEFAULT_CLEANUP_TIMEOUT_MS,\n ): Promise<void> {\n if (inflight.length === 0) return\n let timeout: ReturnType<typeof setTimeout> | undefined\n try {\n await Promise.race([\n Promise.allSettled(inflight).then(() => undefined),\n new Promise<void>((resolve) => {\n timeout = setTimeout(resolve, timeoutMs)\n }),\n ])\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n }\n }\n\n async function dispatchPart(): Promise<void> {\n if (pending.length === 0) return\n await acquirePartSlot()\n let data: Uint8Array\n if (pending.length === 1) {\n const head = pending[0]\n if (!head) {\n sem.release()\n return\n }\n data = head\n } else {\n const total = pending.reduce((sum, chunk) => sum + chunk.byteLength, 0)\n data = new Uint8Array(total)\n let offset = 0\n for (const chunk of pending) {\n data.set(chunk, offset)\n offset += chunk.byteLength\n }\n }\n pending.length = 0\n pendingBytes = 0\n const partNumber = nextPartNumber++\n startPartWithAcquiredSlot(data, partNumber)\n }\n\n const writable = new WritableStream<Uint8Array>({\n async write(chunk: Uint8Array): Promise<void> {\n if (errored) throw errored\n abortScope.signal.throwIfAborted()\n if (chunk.byteLength === 0) return\n\n pending.push(chunk)\n pendingBytes += chunk.byteLength\n while (pendingBytes >= partSize) {\n await acquirePartSlot()\n if (errored) {\n sem.release()\n throw errored\n }\n // Pull exactly partSize bytes off the front\n const carved = carveExact(pending, partSize)\n const partNumber = nextPartNumber++\n pendingBytes -= partSize\n startPartWithAcquiredSlot(carved, partNumber)\n }\n },\n\n async close(): Promise<void> {\n try {\n if (errored) throw errored\n abortScope.signal.throwIfAborted()\n\n // Ship any remaining bytes as the last part. If the total fit in one\n // single buffered batch (no parts shipped yet), we have to use the\n // multipart path anyway since we already called startLargeFile lazily.\n if (pendingBytes > 0) {\n await dispatchPart()\n }\n\n const settled = await settleInflightForClose()\n const rejected = settled.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n )\n if (rejected !== undefined && errored === null) {\n markErrored(rejected.reason)\n }\n if (errored) throw errored\n\n if (largeFileId === null) {\n // Stream closed before any data was written. Start an empty large\n // file? B2 requires at least 2 parts. Reject — callers shouldn't\n // close an empty stream.\n throw new Error('createWriteStream closed without any data written.')\n }\n\n const result = await finishLargeFileWithAbortReconciliation(raw, accountInfo, {\n fileId: largeFileId,\n bucketId: options.bucketId,\n fileName: options.fileName,\n partSha1s,\n signal: abortScope.signal,\n ...(options.retry !== undefined ? { retry: options.retry } : {}),\n })\n abortScope.dispose()\n resolveDone(result)\n } catch (err) {\n const closeError = toError(err)\n if (errored === null) errored = closeError\n abortScope.abort(errored)\n const observedError = errored\n const fileIdToCancel = largeFileId\n if (fileIdToCancel === null && startPromise !== null) {\n // Mirror writer.abort(): close() must not wait for non-abortable\n // b2_start_large_file. If a file ID arrives later, cancel it in the\n // background.\n scheduleCancelLargeFileAfterStart(startPromise)\n abortScope.dispose()\n rejectDone(observedError)\n throw observedError\n }\n await Promise.allSettled(inflight)\n // Capture into a const so the cancel closure sees a non-null\n // `fileId`; closures don't observe the outer `!== null` narrowing\n // because the variable is mutable across the lambda boundary.\n let finalError: unknown = observedError\n if (fileIdToCancel !== null) {\n finalError = await resolveLargeFileErrorAfterCleanup(observedError, raw, accountInfo, {\n fileId: fileIdToCancel,\n bucketId: options.bucketId,\n fileName: options.fileName,\n signal: options.signal,\n onCleanupFailure: options.onCleanupFailure,\n })\n }\n abortScope.dispose()\n rejectDone(finalError)\n throw finalError\n }\n },\n\n async abort(reason: unknown): Promise<void> {\n const abortError = markErrored(reason)\n pending.length = 0\n pendingBytes = 0\n const fileIdToCancel = largeFileId\n if (fileIdToCancel === null && startPromise !== null) {\n // Do not await an in-flight start request here. A stalled\n // b2_start_large_file must not make writer.abort() hang; if it later\n // returns a file ID, cancel it best-effort in the background.\n scheduleCancelLargeFileAfterStart(startPromise)\n }\n if (fileIdToCancel !== null) {\n await waitForInflightPartsToSettle()\n await cancelLargeFileBestEffort(\n raw,\n accountInfo,\n fileIdToCancel,\n cleanupWriteStreamOptions(options),\n )\n }\n abortScope.dispose()\n rejectDone(abortError)\n },\n })\n\n return { writable, done }\n}\n\nfunction cleanupWriteStreamOptions(options: CreateWriteStreamOptions): {\n readonly signal?: AbortSignal\n} & CleanupFailureOptions {\n return {\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.onCleanupFailure !== undefined\n ? { onCleanupFailure: options.onCleanupFailure }\n : {}),\n }\n}\n\n/**\n * Removes exactly `size` bytes from the front of `chunks` (mutates) and returns\n * them as a contiguous Uint8Array. Any trailing remainder of the last chunk\n * stays at the front of `chunks` for the next part.\n *\n * @param chunks - Queue of pending chunks. Modified in place.\n * @param size - Number of bytes to carve off the front.\n *\n * @returns A new Uint8Array containing exactly `size` bytes.\n */\nfunction carveExact(chunks: Uint8Array[], size: number): Uint8Array {\n const out = new Uint8Array(size)\n let written = 0\n while (written < size && chunks.length > 0) {\n const head = chunks[0]\n if (!head) break\n const need = size - written\n if (head.byteLength <= need) {\n out.set(head, written)\n written += head.byteLength\n chunks.shift()\n } else {\n out.set(head.subarray(0, need), written)\n chunks[0] = head.subarray(need)\n written += need\n }\n }\n return out\n}\n\nfunction waitForAbort(signal: AbortSignal): {\n readonly promise: Promise<unknown>\n dispose(): void\n} {\n if (signal.aborted) {\n return {\n promise: Promise.resolve(abortReason(signal)),\n dispose() {},\n }\n }\n\n let onAbort: (() => void) | undefined\n const promise = new Promise<unknown>((resolve) => {\n onAbort = () => resolve(abortReason(signal))\n signal.addEventListener('abort', onAbort, { once: true })\n })\n\n return {\n promise,\n dispose() {\n if (onAbort !== undefined) signal.removeEventListener('abort', onAbort)\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"stream.cjs","names":[],"sources":["../../src/upload/stream.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport { IncrementalSha1 } from '../streams/hash.ts'\nimport type { ProgressListener } from '../streams/progress.ts'\nimport { ProgressTracker } from '../streams/progress.ts'\nimport type { EncryptionSetting } from '../types/encryption.ts'\nimport type { FileVersion } from '../types/file.ts'\nimport type { BucketId, LargeFileId } from '../types/ids.ts'\nimport { abortReason, raceWithAbort } from '../util/abort.ts'\nimport { DEFAULT_CONTENT_TYPE, DEFAULT_TRANSFER_CONCURRENCY } from '../util/defaults.ts'\nimport { toError } from '../util/to-error.ts'\nimport { createAbortScope } from './abort-scope.ts'\nimport {\n type CleanupFailureOptions,\n cancelLargeFileBestEffort,\n DEFAULT_CLEANUP_TIMEOUT_MS,\n resolveLargeFileErrorAfterCleanup,\n} from './cancel.ts'\nimport { Semaphore } from './concurrency.ts'\nimport { finishLargeFileWithAbortReconciliation } from './finish.ts'\nimport {\n resolveRetryResponseBodyFailures,\n type UploadRetryOptions,\n uploadPartWithFreshUrl,\n} from './retry.ts'\n\n/** Options for creating a streaming multipart upload sink. */\nexport interface CreateWriteStreamOptions extends UploadRetryOptions, CleanupFailureOptions {\n /** Target bucket for the upload. */\n readonly bucketId: BucketId\n /** Destination file name in the bucket. */\n readonly fileName: string\n /** MIME type. Defaults to `b2/x-auto`. */\n readonly contentType?: string\n /** Custom file info stored with the file. */\n readonly fileInfo?: Record<string, string>\n /** Server-side encryption applied to each part. */\n readonly serverSideEncryption?: EncryptionSetting\n /**\n * B2 upload timestamp override in milliseconds since epoch.\n * Sets the file version `uploadTimestamp`; distinct from `src_last_modified_millis` metadata.\n * Requires B2 account enablement for Custom Upload Timestamp.\n */\n readonly customUploadTimestamp?: number\n /**\n * Target part size in bytes. The stream buffers writes until this many bytes\n * are accumulated, then ships a part. Must be at least the account's\n * absolute minimum part size; the implementation will raise it if too small.\n */\n readonly partSize?: number\n /** Maximum number of parts uploaded in parallel. Defaults to 4. */\n readonly concurrency?: number\n /** Callback invoked with upload progress events. `totalBytes` is `null` (size unknown). */\n readonly onProgress?: ProgressListener\n /**\n * Minimum milliseconds between byte-only progress callbacks. Defaults to\n * the SDK's 100 ms progress interval; set to 0 for per-chunk callbacks.\n * Part-completion progress callbacks are always emitted immediately.\n */\n readonly progressIntervalMillis?: number\n /** Aborts the upload and cancels the unfinished large file. */\n readonly signal?: AbortSignal\n}\n\n/**\n * Handle returned by `B2Object.createWriteStream`: the Web `WritableStream` to\n * pipe data into, plus a promise that resolves with the finished\n * {@link FileVersion} once the stream is closed and all parts have been\n * uploaded.\n */\nexport interface UploadWriteHandle {\n /** Web `WritableStream` sink to pipe data into. */\n readonly writable: WritableStream<Uint8Array>\n /** Resolves with the finalized file version when the stream closes successfully. */\n readonly done: Promise<FileVersion>\n}\n\n/**\n * Creates a {@link WritableStream} that streams data into a B2 multipart upload.\n *\n * Buffers incoming chunks until `partSize` bytes are accumulated, ships each\n * complete part through the standard multipart engine, and finalizes the file\n * once the stream is closed. Honours backpressure via the queue's bounded\n * concurrency. Streaming uploads do not support resume because the total size\n * and per-part hashes aren't known in advance; use {@link uploadLargeFile} with\n * a buffered source when resume is required.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state (tokens, URLs, part URL pool).\n * @param options - Streaming upload parameters.\n *\n * @returns A {@link UploadWriteHandle} with the writable sink and a completion promise.\n */\nexport function createWriteStream(\n raw: RawClient,\n accountInfo: AccountInfo,\n options: CreateWriteStreamOptions,\n): UploadWriteHandle {\n const minPartSize = accountInfo.getAbsoluteMinimumPartSize()\n const recommendedPartSize = accountInfo.getRecommendedPartSize()\n const partSize = Math.max(options.partSize ?? recommendedPartSize, minPartSize)\n const concurrency = options.concurrency ?? DEFAULT_TRANSFER_CONCURRENCY\n const tracker = new ProgressTracker(options.onProgress, null, null, {\n ...(options.progressIntervalMillis !== undefined\n ? { minIntervalMs: options.progressIntervalMillis }\n : {}),\n })\n const sem = new Semaphore(concurrency)\n const abortScope = createAbortScope(options.signal)\n\n let largeFileId: LargeFileId | null = null\n let startPromise: Promise<LargeFileId> | null = null\n let cancelAfterStartScheduled = false\n let nextPartNumber = 1\n let pendingBytes = 0\n const pending: Uint8Array[] = []\n const partSha1s: string[] = []\n const inflight: Promise<void>[] = []\n let errored: Error | null = null\n\n // ES2024 `Promise.withResolvers()` exposes the resolve/reject pair as\n // properties of the returned object, avoiding the `let resolve!:` /\n // `let reject!:` non-null-assertion pattern needed before this API\n // existed. Available in Node 22 (our minimum), Bun, Deno, modern\n // browsers, and Cloudflare Workers.\n const {\n promise: done,\n resolve: resolveDone,\n reject: rejectDone,\n } = Promise.withResolvers<FileVersion>()\n // Attach a no-op rejection handler so a `done` that rejects before the\n // caller observes it never surfaces as a process-level unhandled rejection.\n // The error is not swallowed: `close()`/`abort()` also reject the writable\n // (so `pipeTo`/`getWriter().close()` throw), and any later `await done` /\n // `done.then(onRejected)` the caller attaches still sees the rejection —\n // extra handlers on the same promise all fire. Mirrors the\n // `task.catch(() => {})` pattern used for inflight part uploads below, and\n // keeps the engine well-behaved under Bun and Node's strict\n // unhandled-rejection mode.\n done.catch(() => {})\n\n function ensureStarted(): Promise<LargeFileId> {\n if (largeFileId !== null) return Promise.resolve(largeFileId)\n if (startPromise === null) {\n const rawStart = raw.startLargeFile(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n {\n bucketId: options.bucketId,\n fileName: options.fileName,\n contentType: options.contentType ?? DEFAULT_CONTENT_TYPE,\n fileInfo: options.fileInfo ?? {},\n ...(options.customUploadTimestamp !== undefined\n ? { customUploadTimestamp: String(options.customUploadTimestamp) }\n : {}),\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n },\n {\n signal: abortScope.signal,\n ...(options.retry !== undefined ? { retry: options.retry } : {}),\n },\n )\n startPromise = rawStart.then((resp) => {\n largeFileId = resp.fileId\n if (abortScope.signal.aborted || errored !== null) {\n cancelStartedLargeFile(largeFileId)\n }\n return largeFileId\n })\n }\n const started = startPromise\n return raceWithAbort(started, abortScope.signal).catch((err) => {\n if (abortScope.signal.aborted) scheduleCancelLargeFileAfterStart(started)\n throw err\n })\n }\n\n async function shipPart(data: Uint8Array, partNumber: number): Promise<void> {\n if (errored !== null) throw errored\n abortScope.signal.throwIfAborted()\n const fileId = await ensureStarted()\n if (errored !== null) throw errored\n abortScope.signal.throwIfAborted()\n\n const sha1 = new IncrementalSha1()\n await sha1.update(data)\n const sha1Hex = await sha1.digest()\n abortScope.signal.throwIfAborted()\n\n const result = await uploadPartWithFreshUrl(raw, accountInfo, fileId, {\n fileName: options.fileName,\n partNumber,\n data: data as BodyInit,\n contentLength: data.byteLength,\n contentSha1: sha1Hex,\n retry: options.retry,\n signal: abortScope.signal,\n onUploadRetry: options.onUploadRetry,\n retryResponseBodyFailures: resolveRetryResponseBodyFailures(\n options.retryResponseBodyFailures,\n ),\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n })\n partSha1s[partNumber - 1] = result.contentSha1\n tracker.addBytes(data.byteLength)\n tracker.completePart()\n }\n\n function markErrored(err: unknown): Error {\n const error = toError(err)\n errored = error\n tracker.dispose()\n abortScope.abort(error)\n return error\n }\n\n function cancelStartedLargeFile(fileId: LargeFileId): void {\n if (cancelAfterStartScheduled) return\n cancelAfterStartScheduled = true\n void cancelLargeFileBestEffort(raw, accountInfo, fileId, cleanupWriteStreamOptions(options))\n }\n\n function scheduleCancelLargeFileAfterStart(started: Promise<LargeFileId>): void {\n void started\n .then((fileId) => cancelStartedLargeFile(fileId))\n .catch(() => {\n // If start failed, no file ID is available to cancel.\n })\n }\n\n async function settleInflightForClose(): Promise<PromiseSettledResult<void>[]> {\n const settled = Promise.allSettled(inflight)\n if (startPromise === null || largeFileId !== null) return await settled\n\n const abortWaiter = waitForAbort(abortScope.signal)\n try {\n const first = await Promise.race([\n settled.then(() => 'settled' as const),\n startPromise.then(\n () => 'start-settled' as const,\n () => 'start-settled' as const,\n ),\n abortWaiter.promise.then(() => 'aborted' as const),\n ])\n if (first === 'aborted' && largeFileId === null) {\n throw abortReason(abortScope.signal)\n }\n return await settled\n } finally {\n abortWaiter.dispose()\n }\n }\n\n function startPartWithAcquiredSlot(data: Uint8Array, partNumber: number): void {\n const task = (async () => {\n try {\n await shipPart(data, partNumber)\n } catch (err) {\n markErrored(err)\n throw err\n } finally {\n sem.release()\n }\n })()\n inflight.push(task)\n // Swallow rejection here; we check `errored` later.\n task.catch(() => {})\n }\n\n async function acquirePartSlot(): Promise<void> {\n await sem.acquire()\n if (errored !== null) {\n sem.release()\n throw errored\n }\n try {\n abortScope.signal.throwIfAborted()\n } catch (err) {\n sem.release()\n throw err\n }\n }\n\n async function waitForInflightPartsToSettle(\n timeoutMs = DEFAULT_CLEANUP_TIMEOUT_MS,\n ): Promise<void> {\n /* v8 ignore next -- only called after a large file exists, which requires at least one part */\n if (inflight.length === 0) return\n let timeout: ReturnType<typeof setTimeout> | undefined\n try {\n await Promise.race([\n Promise.allSettled(inflight).then(() => undefined),\n new Promise<void>((resolve) => {\n timeout = setTimeout(resolve, timeoutMs)\n }),\n ])\n } finally {\n /* v8 ignore next -- setTimeout is assigned synchronously when the race promise is built */\n if (timeout !== undefined) clearTimeout(timeout)\n }\n }\n\n async function dispatchPart(): Promise<void> {\n /* v8 ignore next -- callers guard on pendingBytes before dispatching the final part */\n if (pending.length === 0) return\n await acquirePartSlot()\n let data: Uint8Array\n if (pending.length === 1) {\n const head = pending[0]\n /* v8 ignore next -- pending is never sparse; this narrows noUncheckedIndexedAccess */\n if (!head) {\n sem.release()\n return\n }\n data = head\n } else {\n const total = pending.reduce((sum, chunk) => sum + chunk.byteLength, 0)\n data = new Uint8Array(total)\n let offset = 0\n for (const chunk of pending) {\n data.set(chunk, offset)\n offset += chunk.byteLength\n }\n }\n pending.length = 0\n pendingBytes = 0\n const partNumber = nextPartNumber++\n startPartWithAcquiredSlot(data, partNumber)\n }\n\n const writable = new WritableStream<Uint8Array>({\n async write(chunk: Uint8Array): Promise<void> {\n if (errored) throw errored\n abortScope.signal.throwIfAborted()\n if (chunk.byteLength === 0) return\n\n pending.push(chunk)\n pendingBytes += chunk.byteLength\n while (pendingBytes >= partSize) {\n await acquirePartSlot()\n if (errored) {\n sem.release()\n throw errored\n }\n // Pull exactly partSize bytes off the front\n const carved = carveExact(pending, partSize)\n const partNumber = nextPartNumber++\n pendingBytes -= partSize\n startPartWithAcquiredSlot(carved, partNumber)\n }\n },\n\n async close(): Promise<void> {\n try {\n if (errored) throw errored\n abortScope.signal.throwIfAborted()\n\n // Ship any remaining bytes as the last part. If the total fit in one\n // single buffered batch (no parts shipped yet), we have to use the\n // multipart path anyway since we already called startLargeFile lazily.\n if (pendingBytes > 0) {\n await dispatchPart()\n }\n\n const settled = await settleInflightForClose()\n const rejected = settled.find(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n )\n if (rejected !== undefined && errored === null) {\n markErrored(rejected.reason)\n }\n if (errored) throw errored\n\n if (largeFileId === null) {\n // Stream closed before any data was written. Start an empty large\n // file? B2 requires at least 2 parts. Reject — callers shouldn't\n // close an empty stream.\n throw new Error('createWriteStream closed without any data written.')\n }\n\n const result = await finishLargeFileWithAbortReconciliation(raw, accountInfo, {\n fileId: largeFileId,\n bucketId: options.bucketId,\n fileName: options.fileName,\n partSha1s,\n signal: abortScope.signal,\n ...(options.retry !== undefined ? { retry: options.retry } : {}),\n })\n tracker.dispose()\n abortScope.dispose()\n resolveDone(result)\n } catch (err) {\n const closeError = toError(err)\n if (errored === null) errored = closeError\n tracker.dispose()\n abortScope.abort(errored)\n const observedError = errored\n const fileIdToCancel = largeFileId\n if (fileIdToCancel === null && startPromise !== null) {\n // Mirror writer.abort(): close() must not wait for non-abortable\n // b2_start_large_file. If a file ID arrives later, cancel it in the\n // background.\n scheduleCancelLargeFileAfterStart(startPromise)\n abortScope.dispose()\n rejectDone(observedError)\n throw observedError\n }\n await Promise.allSettled(inflight)\n // Capture into a const so the cancel closure sees a non-null\n // `fileId`; closures don't observe the outer `!== null` narrowing\n // because the variable is mutable across the lambda boundary.\n let finalError: unknown = observedError\n if (fileIdToCancel !== null) {\n finalError = await resolveLargeFileErrorAfterCleanup(observedError, raw, accountInfo, {\n fileId: fileIdToCancel,\n bucketId: options.bucketId,\n fileName: options.fileName,\n signal: options.signal,\n onCleanupFailure: options.onCleanupFailure,\n })\n }\n abortScope.dispose()\n rejectDone(finalError)\n throw finalError\n }\n },\n\n async abort(reason: unknown): Promise<void> {\n const abortError = markErrored(reason)\n pending.length = 0\n pendingBytes = 0\n const fileIdToCancel = largeFileId\n if (fileIdToCancel === null && startPromise !== null) {\n // Do not await an in-flight start request here. A stalled\n // b2_start_large_file must not make writer.abort() hang; if it later\n // returns a file ID, cancel it best-effort in the background.\n scheduleCancelLargeFileAfterStart(startPromise)\n }\n if (fileIdToCancel !== null) {\n await waitForInflightPartsToSettle()\n await cancelLargeFileBestEffort(\n raw,\n accountInfo,\n fileIdToCancel,\n cleanupWriteStreamOptions(options),\n )\n }\n tracker.dispose()\n abortScope.dispose()\n rejectDone(abortError)\n },\n })\n\n return { writable, done }\n}\n\nfunction cleanupWriteStreamOptions(options: CreateWriteStreamOptions): {\n readonly signal?: AbortSignal\n} & CleanupFailureOptions {\n return {\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.onCleanupFailure !== undefined\n ? { onCleanupFailure: options.onCleanupFailure }\n : {}),\n }\n}\n\n/**\n * Removes exactly `size` bytes from the front of `chunks` (mutates) and returns\n * them as a contiguous Uint8Array. Any trailing remainder of the last chunk\n * stays at the front of `chunks` for the next part.\n *\n * @param chunks - Queue of pending chunks. Modified in place.\n * @param size - Number of bytes to carve off the front.\n *\n * @returns A new Uint8Array containing exactly `size` bytes.\n */\nfunction carveExact(chunks: Uint8Array[], size: number): Uint8Array {\n const out = new Uint8Array(size)\n let written = 0\n while (written < size && chunks.length > 0) {\n const head = chunks[0]\n /* v8 ignore next -- chunks is never sparse; this narrows noUncheckedIndexedAccess */\n if (!head) break\n const need = size - written\n if (head.byteLength <= need) {\n out.set(head, written)\n written += head.byteLength\n chunks.shift()\n } else {\n out.set(head.subarray(0, need), written)\n chunks[0] = head.subarray(need)\n written += need\n }\n }\n return out\n}\n\nfunction waitForAbort(signal: AbortSignal): {\n readonly promise: Promise<unknown>\n dispose(): void\n} {\n /* v8 ignore next -- callers check abort before entering the start/close wait race */\n if (signal.aborted) {\n return {\n promise: Promise.resolve(abortReason(signal)),\n dispose() {},\n }\n }\n\n let onAbort: (() => void) | undefined\n const promise = new Promise<unknown>((resolve) => {\n onAbort = () => resolve(abortReason(signal))\n signal.addEventListener('abort', onAbort, { once: true })\n })\n\n return {\n promise,\n dispose() {\n /* v8 ignore next -- listener is assigned synchronously with promise construction */\n if (onAbort !== undefined) signal.removeEventListener('abort', onAbort)\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA6FA,SAAgB,kBACd,KACA,aACA,SACmB;CACnB,MAAM,cAAc,YAAY,2BAA2B;CAC3D,MAAM,sBAAsB,YAAY,uBAAuB;CAC/D,MAAM,WAAW,KAAK,IAAI,QAAQ,YAAY,qBAAqB,WAAW;CAC9E,MAAM,cAAc,QAAQ,eAAA;CAC5B,MAAM,UAAU,IAAI,iBAAA,gBAAgB,QAAQ,YAAY,MAAM,MAAM,EAClE,GAAI,QAAQ,2BAA2B,KAAA,IACnC,EAAE,eAAe,QAAQ,uBAAuB,IAChD,CAAC,EACP,CAAC;CACD,MAAM,MAAM,IAAI,oBAAA,UAAU,WAAW;CACrC,MAAM,aAAa,oBAAA,iBAAiB,QAAQ,MAAM;CAElD,IAAI,cAAkC;CACtC,IAAI,eAA4C;CAChD,IAAI,4BAA4B;CAChC,IAAI,iBAAiB;CACrB,IAAI,eAAe;CACnB,MAAM,UAAwB,CAAC;CAC/B,MAAM,YAAsB,CAAC;CAC7B,MAAM,WAA4B,CAAC;CACnC,IAAI,UAAwB;CAO5B,MAAM,EACJ,SAAS,MACT,SAAS,aACT,QAAQ,eACN,QAAQ,cAA2B;CAUvC,KAAK,YAAY,CAAC,CAAC;CAEnB,SAAS,gBAAsC;EAC7C,IAAI,gBAAgB,MAAM,OAAO,QAAQ,QAAQ,WAAW;EAC5D,IAAI,iBAAiB,MAqBnB,eApBiB,IAAI,eACnB,YAAY,UAAU,GACtB,YAAY,aAAa,GACzB;GACE,UAAU,QAAQ;GAClB,UAAU,QAAQ;GAClB,aAAa,QAAQ,eAAA;GACrB,UAAU,QAAQ,YAAY,CAAC;GAC/B,GAAI,QAAQ,0BAA0B,KAAA,IAClC,EAAE,uBAAuB,OAAO,QAAQ,qBAAqB,EAAE,IAC/D,CAAC;GACL,GAAI,QAAQ,yBAAyB,KAAA,IACjC,EAAE,sBAAsB,QAAQ,qBAAqB,IACrD,CAAC;EACP,GACA;GACE,QAAQ,WAAW;GACnB,GAAI,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;EAChE,CAEa,CAAA,CAAS,MAAM,SAAS;GACrC,cAAc,KAAK;GACnB,IAAI,WAAW,OAAO,WAAW,YAAY,MAC3C,uBAAuB,WAAW;GAEpC,OAAO;EACT,CAAC;EAEH,MAAM,UAAU;EAChB,OAAO,cAAA,cAAc,SAAS,WAAW,MAAM,CAAC,CAAC,OAAO,QAAQ;GAC9D,IAAI,WAAW,OAAO,SAAS,kCAAkC,OAAO;GACxE,MAAM;EACR,CAAC;CACH;CAEA,eAAe,SAAS,MAAkB,YAAmC;EAC3E,IAAI,YAAY,MAAM,MAAM;EAC5B,WAAW,OAAO,eAAe;EACjC,MAAM,SAAS,MAAM,cAAc;EACnC,IAAI,YAAY,MAAM,MAAM;EAC5B,WAAW,OAAO,eAAe;EAEjC,MAAM,OAAO,IAAI,aAAA,gBAAgB;EACjC,MAAM,KAAK,OAAO,IAAI;EACtB,MAAM,UAAU,MAAM,KAAK,OAAO;EAClC,WAAW,OAAO,eAAe;EAEjC,MAAM,SAAS,MAAM,cAAA,uBAAuB,KAAK,aAAa,QAAQ;GACpE,UAAU,QAAQ;GAClB;GACM;GACN,eAAe,KAAK;GACpB,aAAa;GACb,OAAO,QAAQ;GACf,QAAQ,WAAW;GACnB,eAAe,QAAQ;GACvB,2BAA2B,cAAA,iCACzB,QAAQ,yBACV;GACA,GAAI,QAAQ,yBAAyB,KAAA,IACjC,EAAE,sBAAsB,QAAQ,qBAAqB,IACrD,CAAC;EACP,CAAC;EACD,UAAU,aAAa,KAAK,OAAO;EACnC,QAAQ,SAAS,KAAK,UAAU;EAChC,QAAQ,aAAa;CACvB;CAEA,SAAS,YAAY,KAAqB;EACxC,MAAM,QAAQ,iBAAA,QAAQ,GAAG;EACzB,UAAU;EACV,QAAQ,QAAQ;EAChB,WAAW,MAAM,KAAK;EACtB,OAAO;CACT;CAEA,SAAS,uBAAuB,QAA2B;EACzD,IAAI,2BAA2B;EAC/B,4BAA4B;EAC5B,eAAK,0BAA0B,KAAK,aAAa,QAAQ,0BAA0B,OAAO,CAAC;CAC7F;CAEA,SAAS,kCAAkC,SAAqC;EAC9E,QACG,MAAM,WAAW,uBAAuB,MAAM,CAAC,CAAC,CAChD,YAAY,CAEb,CAAC;CACL;CAEA,eAAe,yBAAgE;EAC7E,MAAM,UAAU,QAAQ,WAAW,QAAQ;EAC3C,IAAI,iBAAiB,QAAQ,gBAAgB,MAAM,OAAO,MAAM;EAEhE,MAAM,cAAc,aAAa,WAAW,MAAM;EAClD,IAAI;GASF,IAAI,MARgB,QAAQ,KAAK;IAC/B,QAAQ,WAAW,SAAkB;IACrC,aAAa,WACL,uBACA,eACR;IACA,YAAY,QAAQ,WAAW,SAAkB;GACnD,CAAC,MACa,aAAa,gBAAgB,MACzC,MAAM,cAAA,YAAY,WAAW,MAAM;GAErC,OAAO,MAAM;EACf,UAAU;GACR,YAAY,QAAQ;EACtB;CACF;CAEA,SAAS,0BAA0B,MAAkB,YAA0B;EAC7E,MAAM,QAAQ,YAAY;GACxB,IAAI;IACF,MAAM,SAAS,MAAM,UAAU;GACjC,SAAS,KAAK;IACZ,YAAY,GAAG;IACf,MAAM;GACR,UAAU;IACR,IAAI,QAAQ;GACd;EACF,EAAA,CAAG;EACH,SAAS,KAAK,IAAI;EAElB,KAAK,YAAY,CAAC,CAAC;CACrB;CAEA,eAAe,kBAAiC;EAC9C,MAAM,IAAI,QAAQ;EAClB,IAAI,YAAY,MAAM;GACpB,IAAI,QAAQ;GACZ,MAAM;EACR;EACA,IAAI;GACF,WAAW,OAAO,eAAe;EACnC,SAAS,KAAK;GACZ,IAAI,QAAQ;GACZ,MAAM;EACR;CACF;CAEA,eAAe,6BACb,YAAY,eAAA,4BACG;;EAEf,IAAI,SAAS,WAAW,GAAG;EAC3B,IAAI;EACJ,IAAI;GACF,MAAM,QAAQ,KAAK,CACjB,QAAQ,WAAW,QAAQ,CAAC,CAAC,WAAW,KAAA,CAAS,GACjD,IAAI,SAAe,YAAY;IAC7B,UAAU,WAAW,SAAS,SAAS;GACzC,CAAC,CACH,CAAC;EACH,UAAU;;GAER,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;EACjD;CACF;CAEA,eAAe,eAA8B;;EAE3C,IAAI,QAAQ,WAAW,GAAG;EAC1B,MAAM,gBAAgB;EACtB,IAAI;EACJ,IAAI,QAAQ,WAAW,GAAG;GACxB,MAAM,OAAO,QAAQ;;GAErB,IAAI,CAAC,MAAM;IACT,IAAI,QAAQ;IACZ;GACF;GACA,OAAO;EACT,OAAO;GACL,MAAM,QAAQ,QAAQ,QAAQ,KAAK,UAAU,MAAM,MAAM,YAAY,CAAC;GACtE,OAAO,IAAI,WAAW,KAAK;GAC3B,IAAI,SAAS;GACb,KAAK,MAAM,SAAS,SAAS;IAC3B,KAAK,IAAI,OAAO,MAAM;IACtB,UAAU,MAAM;GAClB;EACF;EACA,QAAQ,SAAS;EACjB,eAAe;EACf,MAAM,aAAa;EACnB,0BAA0B,MAAM,UAAU;CAC5C;CA6HA,OAAO;EAAE,UAAA,IA3HY,eAA2B;GAC9C,MAAM,MAAM,OAAkC;IAC5C,IAAI,SAAS,MAAM;IACnB,WAAW,OAAO,eAAe;IACjC,IAAI,MAAM,eAAe,GAAG;IAE5B,QAAQ,KAAK,KAAK;IAClB,gBAAgB,MAAM;IACtB,OAAO,gBAAgB,UAAU;KAC/B,MAAM,gBAAgB;KACtB,IAAI,SAAS;MACX,IAAI,QAAQ;MACZ,MAAM;KACR;KAEA,MAAM,SAAS,WAAW,SAAS,QAAQ;KAC3C,MAAM,aAAa;KACnB,gBAAgB;KAChB,0BAA0B,QAAQ,UAAU;IAC9C;GACF;GAEA,MAAM,QAAuB;IAC3B,IAAI;KACF,IAAI,SAAS,MAAM;KACnB,WAAW,OAAO,eAAe;KAKjC,IAAI,eAAe,GACjB,MAAM,aAAa;KAIrB,MAAM,YAAW,MADK,uBAAuB,EAAA,CACpB,MACtB,WAA4C,OAAO,WAAW,UACjE;KACA,IAAI,aAAa,KAAA,KAAa,YAAY,MACxC,YAAY,SAAS,MAAM;KAE7B,IAAI,SAAS,MAAM;KAEnB,IAAI,gBAAgB,MAIlB,MAAM,IAAI,MAAM,oDAAoD;KAGtE,MAAM,SAAS,MAAM,eAAA,uCAAuC,KAAK,aAAa;MAC5E,QAAQ;MACR,UAAU,QAAQ;MAClB,UAAU,QAAQ;MAClB;MACA,QAAQ,WAAW;MACnB,GAAI,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;KAChE,CAAC;KACD,QAAQ,QAAQ;KAChB,WAAW,QAAQ;KACnB,YAAY,MAAM;IACpB,SAAS,KAAK;KACZ,MAAM,aAAa,iBAAA,QAAQ,GAAG;KAC9B,IAAI,YAAY,MAAM,UAAU;KAChC,QAAQ,QAAQ;KAChB,WAAW,MAAM,OAAO;KACxB,MAAM,gBAAgB;KACtB,MAAM,iBAAiB;KACvB,IAAI,mBAAmB,QAAQ,iBAAiB,MAAM;MAIpD,kCAAkC,YAAY;MAC9C,WAAW,QAAQ;MACnB,WAAW,aAAa;MACxB,MAAM;KACR;KACA,MAAM,QAAQ,WAAW,QAAQ;KAIjC,IAAI,aAAsB;KAC1B,IAAI,mBAAmB,MACrB,aAAa,MAAM,eAAA,kCAAkC,eAAe,KAAK,aAAa;MACpF,QAAQ;MACR,UAAU,QAAQ;MAClB,UAAU,QAAQ;MAClB,QAAQ,QAAQ;MAChB,kBAAkB,QAAQ;KAC5B,CAAC;KAEH,WAAW,QAAQ;KACnB,WAAW,UAAU;KACrB,MAAM;IACR;GACF;GAEA,MAAM,MAAM,QAAgC;IAC1C,MAAM,aAAa,YAAY,MAAM;IACrC,QAAQ,SAAS;IACjB,eAAe;IACf,MAAM,iBAAiB;IACvB,IAAI,mBAAmB,QAAQ,iBAAiB,MAI9C,kCAAkC,YAAY;IAEhD,IAAI,mBAAmB,MAAM;KAC3B,MAAM,6BAA6B;KACnC,MAAM,eAAA,0BACJ,KACA,aACA,gBACA,0BAA0B,OAAO,CACnC;IACF;IACA,QAAQ,QAAQ;IAChB,WAAW,QAAQ;IACnB,WAAW,UAAU;GACvB;EACF,CAES;EAAU;CAAK;AAC1B;AAEA,SAAS,0BAA0B,SAET;CACxB,OAAO;EACL,GAAI,QAAQ,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;EACjE,GAAI,QAAQ,qBAAqB,KAAA,IAC7B,EAAE,kBAAkB,QAAQ,iBAAiB,IAC7C,CAAC;CACP;AACF;;;;;;;;;;;AAYA,SAAS,WAAW,QAAsB,MAA0B;CAClE,MAAM,MAAM,IAAI,WAAW,IAAI;CAC/B,IAAI,UAAU;CACd,OAAO,UAAU,QAAQ,OAAO,SAAS,GAAG;EAC1C,MAAM,OAAO,OAAO;;EAEpB,IAAI,CAAC,MAAM;EACX,MAAM,OAAO,OAAO;EACpB,IAAI,KAAK,cAAc,MAAM;GAC3B,IAAI,IAAI,MAAM,OAAO;GACrB,WAAW,KAAK;GAChB,OAAO,MAAM;EACf,OAAO;GACL,IAAI,IAAI,KAAK,SAAS,GAAG,IAAI,GAAG,OAAO;GACvC,OAAO,KAAK,KAAK,SAAS,IAAI;GAC9B,WAAW;EACb;CACF;CACA,OAAO;AACT;AAEA,SAAS,aAAa,QAGpB;;CAEA,IAAI,OAAO,SACT,OAAO;EACL,SAAS,QAAQ,QAAQ,cAAA,YAAY,MAAM,CAAC;EAC5C,UAAU,CAAC;CACb;CAGF,IAAI;CAMJ,OAAO;EACL,SAAA,IANkB,SAAkB,YAAY;GAChD,gBAAgB,QAAQ,cAAA,YAAY,MAAM,CAAC;GAC3C,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;EAC1D,CAGE;EACA,UAAU;;GAER,IAAI,YAAY,KAAA,GAAW,OAAO,oBAAoB,SAAS,OAAO;EACxE;CACF;AACF"}
@@ -18,6 +18,12 @@ export interface CreateWriteStreamOptions extends UploadRetryOptions, CleanupFai
18
18
  readonly fileInfo?: Record<string, string>;
19
19
  /** Server-side encryption applied to each part. */
20
20
  readonly serverSideEncryption?: EncryptionSetting;
21
+ /**
22
+ * B2 upload timestamp override in milliseconds since epoch.
23
+ * Sets the file version `uploadTimestamp`; distinct from `src_last_modified_millis` metadata.
24
+ * Requires B2 account enablement for Custom Upload Timestamp.
25
+ */
26
+ readonly customUploadTimestamp?: number;
21
27
  /**
22
28
  * Target part size in bytes. The stream buffers writes until this many bytes
23
29
  * are accumulated, then ships a part. Must be at least the account's
@@ -28,6 +34,12 @@ export interface CreateWriteStreamOptions extends UploadRetryOptions, CleanupFai
28
34
  readonly concurrency?: number;
29
35
  /** Callback invoked with upload progress events. `totalBytes` is `null` (size unknown). */
30
36
  readonly onProgress?: ProgressListener;
37
+ /**
38
+ * Minimum milliseconds between byte-only progress callbacks. Defaults to
39
+ * the SDK's 100 ms progress interval; set to 0 for per-chunk callbacks.
40
+ * Part-completion progress callbacks are always emitted immediately.
41
+ */
42
+ readonly progressIntervalMillis?: number;
31
43
  /** Aborts the upload and cancels the unfinished large file. */
32
44
  readonly signal?: AbortSignal;
33
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/upload/stream.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,iBAAiB,CAAA;AAI5D,OAAO,EACL,KAAK,qBAAqB,EAI3B,MAAM,aAAa,CAAA;AAGpB,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,YAAY,CAAA;AAEnB,8DAA8D;AAC9D,MAAM,WAAW,wBAAyB,SAAQ,kBAAkB,EAAE,qBAAqB;IACzF,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,mDAAmD;IACnD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IAC7C,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;CACpC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CA0VnB"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/upload/stream.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,iBAAiB,CAAA;AAK5D,OAAO,EACL,KAAK,qBAAqB,EAI3B,MAAM,aAAa,CAAA;AAGpB,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,YAAY,CAAA;AAEnB,8DAA8D;AAC9D,MAAM,WAAW,wBAAyB,SAAQ,kBAAkB,EAAE,qBAAqB;IACzF,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,mDAAmD;IACnD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;IACvC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;IACxC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IAC7C,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;CACpC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAyWnB"}
@@ -18,6 +18,12 @@ export interface CreateWriteStreamOptions extends UploadRetryOptions, CleanupFai
18
18
  readonly fileInfo?: Record<string, string>;
19
19
  /** Server-side encryption applied to each part. */
20
20
  readonly serverSideEncryption?: EncryptionSetting;
21
+ /**
22
+ * B2 upload timestamp override in milliseconds since epoch.
23
+ * Sets the file version `uploadTimestamp`; distinct from `src_last_modified_millis` metadata.
24
+ * Requires B2 account enablement for Custom Upload Timestamp.
25
+ */
26
+ readonly customUploadTimestamp?: number;
21
27
  /**
22
28
  * Target part size in bytes. The stream buffers writes until this many bytes
23
29
  * are accumulated, then ships a part. Must be at least the account's
@@ -28,6 +34,12 @@ export interface CreateWriteStreamOptions extends UploadRetryOptions, CleanupFai
28
34
  readonly concurrency?: number;
29
35
  /** Callback invoked with upload progress events. `totalBytes` is `null` (size unknown). */
30
36
  readonly onProgress?: ProgressListener;
37
+ /**
38
+ * Minimum milliseconds between byte-only progress callbacks. Defaults to
39
+ * the SDK's 100 ms progress interval; set to 0 for per-chunk callbacks.
40
+ * Part-completion progress callbacks are always emitted immediately.
41
+ */
42
+ readonly progressIntervalMillis?: number;
31
43
  /** Aborts the upload and cancels the unfinished large file. */
32
44
  readonly signal?: AbortSignal;
33
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/upload/stream.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,iBAAiB,CAAA;AAI5D,OAAO,EACL,KAAK,qBAAqB,EAI3B,MAAM,aAAa,CAAA;AAGpB,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,YAAY,CAAA;AAEnB,8DAA8D;AAC9D,MAAM,WAAW,wBAAyB,SAAQ,kBAAkB,EAAE,qBAAqB;IACzF,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,mDAAmD;IACnD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IAC7C,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;CACpC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CA0VnB"}
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/upload/stream.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,iBAAiB,CAAA;AAK5D,OAAO,EACL,KAAK,qBAAqB,EAI3B,MAAM,aAAa,CAAA;AAGpB,OAAO,EAEL,KAAK,kBAAkB,EAExB,MAAM,YAAY,CAAA;AAEnB,8DAA8D;AAC9D,MAAM,WAAW,wBAAyB,SAAQ,kBAAkB,EAAE,qBAAqB;IACzF,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,mDAAmD;IACnD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAA;IACvC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC;;;;OAIG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAA;IACxC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IAC7C,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;CACpC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAyWnB"}
@@ -1,6 +1,7 @@
1
- import { abortReason, createAbortScope, raceWithAbort } from "./abort-scope.js";
1
+ import { createAbortScope } from "./abort-scope.js";
2
2
  import { DEFAULT_CLEANUP_TIMEOUT_MS, cancelLargeFileBestEffort, resolveLargeFileErrorAfterCleanup } from "./cancel.js";
3
3
  import { Semaphore } from "./concurrency.js";
4
+ import { abortReason, raceWithAbort } from "../util/abort.js";
4
5
  import { finishLargeFileWithAbortReconciliation } from "./finish.js";
5
6
  import "../util/defaults.js";
6
7
  import { ProgressTracker } from "../streams/progress.js";
@@ -29,7 +30,7 @@ function createWriteStream(raw, accountInfo, options) {
29
30
  const recommendedPartSize = accountInfo.getRecommendedPartSize();
30
31
  const partSize = Math.max(options.partSize ?? recommendedPartSize, minPartSize);
31
32
  const concurrency = options.concurrency ?? 4;
32
- const tracker = new ProgressTracker(options.onProgress, null, null);
33
+ const tracker = new ProgressTracker(options.onProgress, null, null, { ...options.progressIntervalMillis !== void 0 ? { minIntervalMs: options.progressIntervalMillis } : {} });
33
34
  const sem = new Semaphore(concurrency);
34
35
  const abortScope = createAbortScope(options.signal);
35
36
  let largeFileId = null;
@@ -50,6 +51,7 @@ function createWriteStream(raw, accountInfo, options) {
50
51
  fileName: options.fileName,
51
52
  contentType: options.contentType ?? "b2/x-auto",
52
53
  fileInfo: options.fileInfo ?? {},
54
+ ...options.customUploadTimestamp !== void 0 ? { customUploadTimestamp: String(options.customUploadTimestamp) } : {},
53
55
  ...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {}
54
56
  }, {
55
57
  signal: abortScope.signal,
@@ -94,6 +96,7 @@ function createWriteStream(raw, accountInfo, options) {
94
96
  function markErrored(err) {
95
97
  const error = toError(err);
96
98
  errored = error;
99
+ tracker.dispose();
97
100
  abortScope.abort(error);
98
101
  return error;
99
102
  }
@@ -148,6 +151,7 @@ function createWriteStream(raw, accountInfo, options) {
148
151
  }
149
152
  }
150
153
  async function waitForInflightPartsToSettle(timeoutMs = DEFAULT_CLEANUP_TIMEOUT_MS) {
154
+ /* v8 ignore next -- only called after a large file exists, which requires at least one part */
151
155
  if (inflight.length === 0) return;
152
156
  let timeout;
153
157
  try {
@@ -155,15 +159,18 @@ function createWriteStream(raw, accountInfo, options) {
155
159
  timeout = setTimeout(resolve, timeoutMs);
156
160
  })]);
157
161
  } finally {
162
+ /* v8 ignore next -- setTimeout is assigned synchronously when the race promise is built */
158
163
  if (timeout !== void 0) clearTimeout(timeout);
159
164
  }
160
165
  }
161
166
  async function dispatchPart() {
167
+ /* v8 ignore next -- callers guard on pendingBytes before dispatching the final part */
162
168
  if (pending.length === 0) return;
163
169
  await acquirePartSlot();
164
170
  let data;
165
171
  if (pending.length === 1) {
166
172
  const head = pending[0];
173
+ /* v8 ignore next -- pending is never sparse; this narrows noUncheckedIndexedAccess */
167
174
  if (!head) {
168
175
  sem.release();
169
176
  return;
@@ -220,11 +227,13 @@ function createWriteStream(raw, accountInfo, options) {
220
227
  signal: abortScope.signal,
221
228
  ...options.retry !== void 0 ? { retry: options.retry } : {}
222
229
  });
230
+ tracker.dispose();
223
231
  abortScope.dispose();
224
232
  resolveDone(result);
225
233
  } catch (err) {
226
234
  const closeError = toError(err);
227
235
  if (errored === null) errored = closeError;
236
+ tracker.dispose();
228
237
  abortScope.abort(errored);
229
238
  const observedError = errored;
230
239
  const fileIdToCancel = largeFileId;
@@ -258,6 +267,7 @@ function createWriteStream(raw, accountInfo, options) {
258
267
  await waitForInflightPartsToSettle();
259
268
  await cancelLargeFileBestEffort(raw, accountInfo, fileIdToCancel, cleanupWriteStreamOptions(options));
260
269
  }
270
+ tracker.dispose();
261
271
  abortScope.dispose();
262
272
  rejectDone(abortError);
263
273
  }
@@ -286,6 +296,7 @@ function carveExact(chunks, size) {
286
296
  let written = 0;
287
297
  while (written < size && chunks.length > 0) {
288
298
  const head = chunks[0];
299
+ /* v8 ignore next -- chunks is never sparse; this narrows noUncheckedIndexedAccess */
289
300
  if (!head) break;
290
301
  const need = size - written;
291
302
  if (head.byteLength <= need) {
@@ -301,6 +312,7 @@ function carveExact(chunks, size) {
301
312
  return out;
302
313
  }
303
314
  function waitForAbort(signal) {
315
+ /* v8 ignore next -- callers check abort before entering the start/close wait race */
304
316
  if (signal.aborted) return {
305
317
  promise: Promise.resolve(abortReason(signal)),
306
318
  dispose() {}
@@ -312,6 +324,7 @@ function waitForAbort(signal) {
312
324
  signal.addEventListener("abort", onAbort, { once: true });
313
325
  }),
314
326
  dispose() {
327
+ /* v8 ignore next -- listener is assigned synchronously with promise construction */
315
328
  if (onAbort !== void 0) signal.removeEventListener("abort", onAbort);
316
329
  }
317
330
  };