@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
@@ -13,6 +13,16 @@ export interface ProgressEvent {
13
13
  }
14
14
  /** Callback invoked each time transfer progress changes. */
15
15
  export type ProgressListener = (event: ProgressEvent) => void;
16
+ /** Default minimum time between byte-progress emissions. */
17
+ export declare const DEFAULT_PROGRESS_EMIT_INTERVAL_MS = 100;
18
+ /** Internal controls for ProgressTracker emission behavior. */
19
+ export interface ProgressTrackerOptions {
20
+ /**
21
+ * Minimum milliseconds between byte-only progress emissions.
22
+ * Set to 0 to emit every change.
23
+ */
24
+ readonly minIntervalMs?: number;
25
+ }
16
26
  /**
17
27
  * Accumulates byte and part counts and emits {@link ProgressEvent}s to a listener.
18
28
  *
@@ -33,20 +43,36 @@ export declare class ProgressTracker {
33
43
  private partsCompleted;
34
44
  /** Timestamp when tracking began. */
35
45
  private readonly startTime;
46
+ /** Minimum milliseconds between byte-only emissions. */
47
+ private readonly minIntervalMs;
48
+ /** Timestamp of the most recent emitted snapshot. */
49
+ private lastEmitTime;
50
+ /** Timer scheduled for a coalesced byte-only emission. */
51
+ private pendingEmitTimer;
52
+ /** Listener error captured from a detached timer callback. */
53
+ private listenerError;
36
54
  /**
37
55
  * Creates a new ProgressTracker.
38
56
  * @param listener - Callback to receive progress events, or undefined to disable.
39
57
  * @param totalBytes - Expected total bytes, or null if unknown.
40
58
  * @param totalParts - Expected total parts, or null if not a multipart transfer.
59
+ * @param options - Optional emission controls.
41
60
  */
42
- constructor(listener: ProgressListener | undefined, totalBytes: number | null, totalParts: number | null);
61
+ constructor(listener: ProgressListener | undefined, totalBytes: number | null, totalParts: number | null, options?: ProgressTrackerOptions);
43
62
  /**
44
- * Record that additional bytes have been transferred and notify the listener.
63
+ * Record that additional bytes have been transferred and schedule listener notification.
45
64
  * @param count - The number of additional bytes that were transferred.
46
65
  */
47
66
  addBytes(count: number): void;
48
67
  /** Record that a multipart part has completed and notify the listener. */
49
68
  completePart(): void;
69
+ /** Cancel any pending coalesced progress emission. */
70
+ dispose(): void;
71
+ private emitThrottled;
72
+ private flushPendingEmit;
73
+ private clearPendingEmit;
74
+ private emitNow;
75
+ private throwPendingListenerError;
50
76
  /** Emit the current progress snapshot to the listener, if one is registered. */
51
77
  private emit;
52
78
  }
@@ -1 +1 @@
1
- {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/streams/progress.js"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,kDAAkD;IAClD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,wDAAwD;IACxD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,4DAA4D;AAC5D,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;AAE7D;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAexB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAhB7B,0CAA0C;IAC1C,OAAO,CAAC,gBAAgB,CAAI;IAC5B,wCAAwC;IACxC,OAAO,CAAC,cAAc,CAAI;IAC1B,qCAAqC;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAElC;;;;;OAKG;gBAEgB,QAAQ,EAAE,gBAAgB,GAAG,SAAS,EACtC,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,UAAU,EAAE,MAAM,GAAG,IAAI;IAK5C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAK7B,0EAA0E;IAC1E,YAAY,IAAI,IAAI;IAKpB,gFAAgF;IAChF,OAAO,CAAC,IAAI;CASb"}
1
+ {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../src/streams/progress.js"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC5B,0CAA0C;IAC1C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,gDAAgD;IAChD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,kDAAkD;IAClD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IAC/B,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,wDAAwD;IACxD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,4DAA4D;AAC5D,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;AAE7D,4DAA4D;AAC5D,eAAO,MAAM,iCAAiC,MAAM,CAAA;AAEpD,+DAA+D;AAC/D,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAChC;AAED;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAwBxB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAzB7B,0CAA0C;IAC1C,OAAO,CAAC,gBAAgB,CAAI;IAC5B,wCAAwC;IACxC,OAAO,CAAC,cAAc,CAAI;IAC1B,qCAAqC;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,wDAAwD;IACxD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IACtC,qDAAqD;IACrD,OAAO,CAAC,YAAY,CAAsB;IAC1C,0DAA0D;IAC1D,OAAO,CAAC,gBAAgB,CAA2C;IACnE,8DAA8D;IAC9D,OAAO,CAAC,aAAa,CAAS;IAE9B;;;;;;OAMG;gBAEgB,QAAQ,EAAE,gBAAgB,GAAG,SAAS,EACtC,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,UAAU,EAAE,MAAM,GAAG,IAAI,EAC1C,OAAO,GAAE,sBAA2B;IAMtC;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM7B,0EAA0E;IAC1E,YAAY,IAAI,IAAI;IAOpB,sDAAsD;IACtD,OAAO,IAAI,IAAI;IAKf,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,OAAO;IAMf,OAAO,CAAC,yBAAyB;IAOjC,gFAAgF;IAChF,OAAO,CAAC,IAAI;CASb"}
@@ -1,4 +1,3 @@
1
- //#region src/streams/progress.ts
2
1
  /**
3
2
  * Accumulates byte and part counts and emits {@link ProgressEvent}s to a listener.
4
3
  *
@@ -19,31 +18,91 @@ var ProgressTracker = class {
19
18
  partsCompleted = 0;
20
19
  /** Timestamp when tracking began. */
21
20
  startTime;
21
+ /** Minimum milliseconds between byte-only emissions. */
22
+ minIntervalMs;
23
+ /** Timestamp of the most recent emitted snapshot. */
24
+ lastEmitTime = null;
25
+ /** Timer scheduled for a coalesced byte-only emission. */
26
+ pendingEmitTimer;
27
+ /** Listener error captured from a detached timer callback. */
28
+ listenerError;
22
29
  /**
23
30
  * Creates a new ProgressTracker.
24
31
  * @param listener - Callback to receive progress events, or undefined to disable.
25
32
  * @param totalBytes - Expected total bytes, or null if unknown.
26
33
  * @param totalParts - Expected total parts, or null if not a multipart transfer.
34
+ * @param options - Optional emission controls.
27
35
  */
28
- constructor(listener, totalBytes, totalParts) {
36
+ constructor(listener, totalBytes, totalParts, options = {}) {
29
37
  this.listener = listener;
30
38
  this.totalBytes = totalBytes;
31
39
  this.totalParts = totalParts;
32
40
  this.startTime = Date.now();
41
+ this.minIntervalMs = Math.max(0, options.minIntervalMs ?? 100);
33
42
  }
34
43
  /**
35
- * Record that additional bytes have been transferred and notify the listener.
44
+ * Record that additional bytes have been transferred and schedule listener notification.
36
45
  * @param count - The number of additional bytes that were transferred.
37
46
  */
38
47
  addBytes(count) {
48
+ this.throwPendingListenerError();
39
49
  this.bytesTransferred += count;
40
- this.emit();
50
+ this.emitThrottled();
41
51
  }
42
52
  /** Record that a multipart part has completed and notify the listener. */
43
53
  completePart() {
54
+ this.throwPendingListenerError();
55
+ this.flushPendingEmit();
44
56
  this.partsCompleted++;
57
+ this.emitNow();
58
+ }
59
+ /** Cancel any pending coalesced progress emission. */
60
+ dispose() {
61
+ this.clearPendingEmit();
62
+ this.listenerError = void 0;
63
+ }
64
+ emitThrottled() {
65
+ if (this.listener === void 0) return;
66
+ if (this.minIntervalMs === 0) {
67
+ this.emitNow();
68
+ return;
69
+ }
70
+ const now = Date.now();
71
+ if (this.lastEmitTime === null || now - this.lastEmitTime >= this.minIntervalMs) {
72
+ this.emitNow(now);
73
+ return;
74
+ }
75
+ if (this.pendingEmitTimer !== void 0) return;
76
+ const delay = Math.max(0, this.minIntervalMs - (now - this.lastEmitTime));
77
+ this.pendingEmitTimer = setTimeout(() => {
78
+ this.pendingEmitTimer = void 0;
79
+ try {
80
+ this.emitNow();
81
+ } catch (err) {
82
+ this.listenerError = err;
83
+ }
84
+ }, delay);
85
+ this.pendingEmitTimer.unref?.();
86
+ }
87
+ flushPendingEmit() {
88
+ if (this.pendingEmitTimer !== void 0) this.emitNow();
89
+ }
90
+ clearPendingEmit() {
91
+ if (this.pendingEmitTimer === void 0) return;
92
+ clearTimeout(this.pendingEmitTimer);
93
+ this.pendingEmitTimer = void 0;
94
+ }
95
+ emitNow(now = Date.now()) {
96
+ this.clearPendingEmit();
97
+ this.lastEmitTime = now;
45
98
  this.emit();
46
99
  }
100
+ throwPendingListenerError() {
101
+ if (this.listenerError === void 0) return;
102
+ const err = this.listenerError;
103
+ this.listenerError = void 0;
104
+ throw err;
105
+ }
47
106
  /** Emit the current progress snapshot to the listener, if one is registered. */
48
107
  emit() {
49
108
  this.listener?.({
@@ -1 +1 @@
1
- {"version":3,"file":"progress.js","names":[],"sources":["../../src/streams/progress.ts"],"sourcesContent":["/** Snapshot of upload or download progress at a point in time. */\nexport interface ProgressEvent {\n /** Number of bytes transferred so far. */\n readonly bytesTransferred: number\n /** Total bytes expected, or null if unknown. */\n readonly totalBytes: number | null\n /** Number of multipart parts completed so far. */\n readonly partsCompleted: number\n /** Total number of parts expected, or null if unknown. */\n readonly totalParts: number | null\n /** Milliseconds elapsed since the operation started. */\n readonly elapsedMs: number\n}\n\n/** Callback invoked each time transfer progress changes. */\nexport type ProgressListener = (event: ProgressEvent) => void\n\n/**\n * Accumulates byte and part counts and emits {@link ProgressEvent}s to a listener.\n *\n * Internal building block. The SDK wires one of these inside every\n * transfer that accepts an `onProgress` option; users supply the\n * listener callback, not the tracker. Exported only so SDK source\n * modules can import it; not re-exported through any subpath.\n *\n * @internal\n */\nexport class ProgressTracker {\n /** Running total of bytes transferred. */\n private bytesTransferred = 0\n /** Running count of completed parts. */\n private partsCompleted = 0\n /** Timestamp when tracking began. */\n private readonly startTime: number\n\n /**\n * Creates a new ProgressTracker.\n * @param listener - Callback to receive progress events, or undefined to disable.\n * @param totalBytes - Expected total bytes, or null if unknown.\n * @param totalParts - Expected total parts, or null if not a multipart transfer.\n */\n constructor(\n private readonly listener: ProgressListener | undefined,\n private readonly totalBytes: number | null,\n private readonly totalParts: number | null,\n ) {\n this.startTime = Date.now()\n }\n\n /**\n * Record that additional bytes have been transferred and notify the listener.\n * @param count - The number of additional bytes that were transferred.\n */\n addBytes(count: number): void {\n this.bytesTransferred += count\n this.emit()\n }\n\n /** Record that a multipart part has completed and notify the listener. */\n completePart(): void {\n this.partsCompleted++\n this.emit()\n }\n\n /** Emit the current progress snapshot to the listener, if one is registered. */\n private emit(): void {\n this.listener?.({\n bytesTransferred: this.bytesTransferred,\n totalBytes: this.totalBytes,\n partsCompleted: this.partsCompleted,\n totalParts: this.totalParts,\n elapsedMs: Date.now() - this.startTime,\n })\n }\n}\n"],"mappings":";;;;;;;;;;;AA2BA,IAAa,kBAAb,MAA6B;CAeR;CACA;CACA;;CAfnB,mBAA2B;;CAE3B,iBAAyB;;CAEzB;;;;;;;CAQA,YACE,UACA,YACA,YACA;EAHiB,KAAA,WAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EAEjB,KAAK,YAAY,KAAK,IAAI;CAC5B;;;;;CAMA,SAAS,OAAqB;EAC5B,KAAK,oBAAoB;EACzB,KAAK,KAAK;CACZ;;CAGA,eAAqB;EACnB,KAAK;EACL,KAAK,KAAK;CACZ;;CAGA,OAAqB;EACnB,KAAK,WAAW;GACd,kBAAkB,KAAK;GACvB,YAAY,KAAK;GACjB,gBAAgB,KAAK;GACrB,YAAY,KAAK;GACjB,WAAW,KAAK,IAAI,IAAI,KAAK;EAC/B,CAAC;CACH;AACF"}
1
+ {"version":3,"file":"progress.js","names":[],"sources":["../../src/streams/progress.ts"],"sourcesContent":["/** Snapshot of upload or download progress at a point in time. */\nexport interface ProgressEvent {\n /** Number of bytes transferred so far. */\n readonly bytesTransferred: number\n /** Total bytes expected, or null if unknown. */\n readonly totalBytes: number | null\n /** Number of multipart parts completed so far. */\n readonly partsCompleted: number\n /** Total number of parts expected, or null if unknown. */\n readonly totalParts: number | null\n /** Milliseconds elapsed since the operation started. */\n readonly elapsedMs: number\n}\n\n/** Callback invoked each time transfer progress changes. */\nexport type ProgressListener = (event: ProgressEvent) => void\n\n/** Default minimum time between byte-progress emissions. */\nexport const DEFAULT_PROGRESS_EMIT_INTERVAL_MS = 100\n\n/** Internal controls for ProgressTracker emission behavior. */\nexport interface ProgressTrackerOptions {\n /**\n * Minimum milliseconds between byte-only progress emissions.\n * Set to 0 to emit every change.\n */\n readonly minIntervalMs?: number\n}\n\n/**\n * Accumulates byte and part counts and emits {@link ProgressEvent}s to a listener.\n *\n * Internal building block. The SDK wires one of these inside every\n * transfer that accepts an `onProgress` option; users supply the\n * listener callback, not the tracker. Exported only so SDK source\n * modules can import it; not re-exported through any subpath.\n *\n * @internal\n */\nexport class ProgressTracker {\n /** Running total of bytes transferred. */\n private bytesTransferred = 0\n /** Running count of completed parts. */\n private partsCompleted = 0\n /** Timestamp when tracking began. */\n private readonly startTime: number\n /** Minimum milliseconds between byte-only emissions. */\n private readonly minIntervalMs: number\n /** Timestamp of the most recent emitted snapshot. */\n private lastEmitTime: number | null = null\n /** Timer scheduled for a coalesced byte-only emission. */\n private pendingEmitTimer: ReturnType<typeof setTimeout> | undefined\n /** Listener error captured from a detached timer callback. */\n private listenerError: unknown\n\n /**\n * Creates a new ProgressTracker.\n * @param listener - Callback to receive progress events, or undefined to disable.\n * @param totalBytes - Expected total bytes, or null if unknown.\n * @param totalParts - Expected total parts, or null if not a multipart transfer.\n * @param options - Optional emission controls.\n */\n constructor(\n private readonly listener: ProgressListener | undefined,\n private readonly totalBytes: number | null,\n private readonly totalParts: number | null,\n options: ProgressTrackerOptions = {},\n ) {\n this.startTime = Date.now()\n this.minIntervalMs = Math.max(0, options.minIntervalMs ?? DEFAULT_PROGRESS_EMIT_INTERVAL_MS)\n }\n\n /**\n * Record that additional bytes have been transferred and schedule listener notification.\n * @param count - The number of additional bytes that were transferred.\n */\n addBytes(count: number): void {\n this.throwPendingListenerError()\n this.bytesTransferred += count\n this.emitThrottled()\n }\n\n /** Record that a multipart part has completed and notify the listener. */\n completePart(): void {\n this.throwPendingListenerError()\n this.flushPendingEmit()\n this.partsCompleted++\n this.emitNow()\n }\n\n /** Cancel any pending coalesced progress emission. */\n dispose(): void {\n this.clearPendingEmit()\n this.listenerError = undefined\n }\n\n private emitThrottled(): void {\n if (this.listener === undefined) return\n if (this.minIntervalMs === 0) {\n this.emitNow()\n return\n }\n\n const now = Date.now()\n if (this.lastEmitTime === null || now - this.lastEmitTime >= this.minIntervalMs) {\n this.emitNow(now)\n return\n }\n\n if (this.pendingEmitTimer !== undefined) return\n\n const delay = Math.max(0, this.minIntervalMs - (now - this.lastEmitTime))\n this.pendingEmitTimer = setTimeout(() => {\n this.pendingEmitTimer = undefined\n try {\n this.emitNow()\n } catch (err) {\n this.listenerError = err\n }\n }, delay)\n ;(this.pendingEmitTimer as { unref?: () => void }).unref?.()\n }\n\n private flushPendingEmit(): void {\n if (this.pendingEmitTimer !== undefined) {\n this.emitNow()\n }\n }\n\n private clearPendingEmit(): void {\n if (this.pendingEmitTimer === undefined) return\n clearTimeout(this.pendingEmitTimer)\n this.pendingEmitTimer = undefined\n }\n\n private emitNow(now = Date.now()): void {\n this.clearPendingEmit()\n this.lastEmitTime = now\n this.emit()\n }\n\n private throwPendingListenerError(): void {\n if (this.listenerError === undefined) return\n const err = this.listenerError\n this.listenerError = undefined\n throw err\n }\n\n /** Emit the current progress snapshot to the listener, if one is registered. */\n private emit(): void {\n this.listener?.({\n bytesTransferred: this.bytesTransferred,\n totalBytes: this.totalBytes,\n partsCompleted: this.partsCompleted,\n totalParts: this.totalParts,\n elapsedMs: Date.now() - this.startTime,\n })\n }\n}\n"],"mappings":";;;;;;;;;;AAuCA,IAAa,kBAAb,MAA6B;CAwBR;CACA;CACA;;CAxBnB,mBAA2B;;CAE3B,iBAAyB;;CAEzB;;CAEA;;CAEA,eAAsC;;CAEtC;;CAEA;;;;;;;;CASA,YACE,UACA,YACA,YACA,UAAkC,CAAC,GACnC;EAJiB,KAAA,WAAA;EACA,KAAA,aAAA;EACA,KAAA,aAAA;EAGjB,KAAK,YAAY,KAAK,IAAI;EAC1B,KAAK,gBAAgB,KAAK,IAAI,GAAG,QAAQ,iBAAA,GAAkD;CAC7F;;;;;CAMA,SAAS,OAAqB;EAC5B,KAAK,0BAA0B;EAC/B,KAAK,oBAAoB;EACzB,KAAK,cAAc;CACrB;;CAGA,eAAqB;EACnB,KAAK,0BAA0B;EAC/B,KAAK,iBAAiB;EACtB,KAAK;EACL,KAAK,QAAQ;CACf;;CAGA,UAAgB;EACd,KAAK,iBAAiB;EACtB,KAAK,gBAAgB,KAAA;CACvB;CAEA,gBAA8B;EAC5B,IAAI,KAAK,aAAa,KAAA,GAAW;EACjC,IAAI,KAAK,kBAAkB,GAAG;GAC5B,KAAK,QAAQ;GACb;EACF;EAEA,MAAM,MAAM,KAAK,IAAI;EACrB,IAAI,KAAK,iBAAiB,QAAQ,MAAM,KAAK,gBAAgB,KAAK,eAAe;GAC/E,KAAK,QAAQ,GAAG;GAChB;EACF;EAEA,IAAI,KAAK,qBAAqB,KAAA,GAAW;EAEzC,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,iBAAiB,MAAM,KAAK,aAAa;EACxE,KAAK,mBAAmB,iBAAiB;GACvC,KAAK,mBAAmB,KAAA;GACxB,IAAI;IACF,KAAK,QAAQ;GACf,SAAS,KAAK;IACZ,KAAK,gBAAgB;GACvB;EACF,GAAG,KAAK;EACP,KAAM,iBAA4C,QAAQ;CAC7D;CAEA,mBAAiC;EAC/B,IAAI,KAAK,qBAAqB,KAAA,GAC5B,KAAK,QAAQ;CAEjB;CAEA,mBAAiC;EAC/B,IAAI,KAAK,qBAAqB,KAAA,GAAW;EACzC,aAAa,KAAK,gBAAgB;EAClC,KAAK,mBAAmB,KAAA;CAC1B;CAEA,QAAgB,MAAM,KAAK,IAAI,GAAS;EACtC,KAAK,iBAAiB;EACtB,KAAK,eAAe;EACpB,KAAK,KAAK;CACZ;CAEA,4BAA0C;EACxC,IAAI,KAAK,kBAAkB,KAAA,GAAW;EACtC,MAAM,MAAM,KAAK;EACjB,KAAK,gBAAgB,KAAA;EACrB,MAAM;CACR;;CAGA,OAAqB;EACnB,KAAK,WAAW;GACd,kBAAkB,KAAK;GACvB,YAAY,KAAK;GACjB,gBAAgB,KAAK;GACrB,YAAY,KAAK;GACjB,WAAW,KAAK,IAAI,IAAI,KAAK;EAC/B,CAAC;CACH;AACF"}
@@ -84,7 +84,8 @@ var BlobSource = class BlobSource {
84
84
  async toArrayBuffer(options = {}) {
85
85
  options.signal?.throwIfAborted();
86
86
  if (options.signal === void 0) return this.blob.arrayBuffer();
87
- return require_bytes.arrayBufferFor(await require_collect.collectStream(this.stream(), options));
87
+ const bytes = await require_collect.collectStream(this.stream(), options);
88
+ return require_bytes.arrayBufferFor(bytes);
88
89
  }
89
90
  };
90
91
  /** ContentSource backed by a Uint8Array buffer. */
@@ -1 +1 @@
1
- {"version":3,"file":"source.cjs","names":[],"sources":["../../src/streams/source.ts"],"sourcesContent":["import { arrayBufferFor } from '../util/bytes.ts'\nimport { collectStream } from './collect.ts'\n\nexport { FileSource, type FileSourcePath } from './file-source.ts'\n\nconst READABLE_STREAM_SIZE_REQUIRED_ERROR = 'size is required when using a ReadableStream as input.'\nconst FORWARD_ONLY_SIZE_REQUIRED_ERROR =\n 'size is required when using a forward-only content source as input.'\nconst STREAM_SOURCE_ENDED_EARLY_ERROR = 'StreamSource ended before the advertised byte count.'\nconst STREAM_SOURCE_TOO_MANY_BYTES_ERROR =\n 'StreamSource emitted more bytes than the advertised byte count.'\nconst STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR =\n 'StreamSource emitted too many empty chunks without data.'\n/** Maximum consecutive empty chunks tolerated from a forward-only stream. */\nexport const MAX_EMPTY_STREAM_CHUNKS = 1024\n\nfunction asyncIterableToReadableStream(\n iterable: AsyncIterable<Uint8Array>,\n): ReadableStream<Uint8Array> {\n const iterator = iterable[Symbol.asyncIterator]()\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const { done, value } = await iterator.next()\n if (done === true) {\n controller.close()\n return\n }\n if (!(value instanceof Uint8Array)) {\n throw new TypeError('Async iterable content sources must yield Uint8Array chunks.')\n }\n controller.enqueue(value)\n } catch (err) {\n /* v8 ignore next -- Iterator-return failure must not mask the pull error. */\n await returnAsyncIteratorBestEffort(iterator)\n throw err\n }\n },\n async cancel(reason) {\n await returnAsyncIteratorBestEffort(iterator, reason)\n },\n })\n}\n\nasync function returnAsyncIteratorBestEffort(\n iterator: AsyncIterator<Uint8Array>,\n reason?: unknown,\n): Promise<void> {\n try {\n await iterator.return?.(reason)\n } catch {\n // Iterator cleanup is secondary and must not mask the pull error.\n }\n}\n\nfunction isAsyncIterable(input: unknown): input is AsyncIterable<Uint8Array> {\n return (\n typeof input === 'object' &&\n input !== null &&\n Symbol.asyncIterator in input &&\n typeof input[Symbol.asyncIterator] === 'function'\n )\n}\n\nfunction isReadableStream(input: unknown): input is ReadableStream<Uint8Array> {\n return (\n typeof input === 'object' &&\n input !== null &&\n typeof (input as { getReader?: unknown }).getReader === 'function'\n )\n}\n\n/**\n * Uniform adapter for upload content. Wraps File, Blob, Buffer, local files,\n * async iterables, or ReadableStream behind a common interface so upload logic\n * does not depend on the input type.\n */\nexport interface ContentSource {\n /** Total size of the content in bytes. */\n readonly size: number\n /** Pre-computed SHA-1 hex digest, if available. */\n readonly sha1?: string\n /**\n * Whether {@link slice} is safe to call on this source.\n *\n * `true` for in-memory / random-access sources (`BufferSource`,\n * `BlobSource`, `FileSource`) — the multipart upload engine can dispatch\n * part reads in parallel by slicing the source into disjoint ranges.\n * `false` for forward-only streams and async iterables — the engine must\n * read sequentially, one `partSize` chunk at a time. Callers that branch on\n * this flag are expected to fall back to the sequential path rather than call\n * `slice()` and catch the throw.\n */\n readonly canSlice: boolean\n /** Return a sub-range of this source as a new ContentSource. */\n slice(start: number, end: number): ContentSource\n /** Open the content as a ReadableStream. */\n stream(): ReadableStream<Uint8Array>\n /** Read the entire content into an ArrayBuffer. */\n toArrayBuffer(options?: { readonly signal?: AbortSignal }): Promise<ArrayBuffer>\n}\n\n/** ContentSource backed by a Blob or File. */\nexport class BlobSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /** Random-access: `Blob.slice()` is cheap and returns a new Blob view. */\n readonly canSlice = true\n\n /**\n * Create a BlobSource wrapping the given Blob.\n * @param blob - The Blob or File to use as the underlying content.\n */\n constructor(private readonly blob: Blob) {\n this.size = blob.size\n }\n\n /**\n * Return a new BlobSource covering the specified byte range.\n * @param start - The zero-based byte offset to begin the slice.\n * @param end - The exclusive byte offset where the slice ends.\n *\n * @returns A new ContentSource representing the requested sub-range.\n */\n slice(start: number, end: number): ContentSource {\n return new BlobSource(this.blob.slice(start, end))\n }\n\n /**\n * Open the Blob content as a ReadableStream.\n * @returns A ReadableStream of the Blob bytes.\n */\n stream(): ReadableStream<Uint8Array> {\n return this.blob.stream() as ReadableStream<Uint8Array>\n }\n\n /**\n * Read the entire Blob content into an ArrayBuffer.\n * @param options - Optional abort signal used while reading.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n options.signal?.throwIfAborted()\n if (options.signal === undefined) return this.blob.arrayBuffer()\n const bytes = await collectStream(this.stream(), options)\n return arrayBufferFor(bytes)\n }\n}\n\n/** ContentSource backed by a Uint8Array buffer. */\nexport class BufferSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /** Random-access: the entire payload lives in memory. */\n readonly canSlice = true\n\n /**\n * Create a BufferSource wrapping the given Uint8Array.\n * @param buffer - The byte buffer to use as the underlying content.\n */\n constructor(private readonly buffer: Uint8Array) {\n this.size = buffer.byteLength\n }\n\n /**\n * Return a new BufferSource covering the specified byte range.\n * @param start - The zero-based byte offset to begin the slice.\n * @param end - The exclusive byte offset where the slice ends.\n *\n * @returns A new ContentSource representing the requested sub-range.\n */\n slice(start: number, end: number): ContentSource {\n return new BufferSource(this.buffer.slice(start, end))\n }\n\n /**\n * Open the buffer content as a ReadableStream.\n * @returns A ReadableStream that emits the buffer bytes in a single chunk.\n */\n stream(): ReadableStream<Uint8Array> {\n const buffer = this.buffer\n return new ReadableStream({\n start(controller) {\n controller.enqueue(buffer)\n controller.close()\n },\n })\n }\n\n /**\n * Read the entire buffer content into an ArrayBuffer.\n * @param options - Optional abort signal checked before returning bytes.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n options.signal?.throwIfAborted()\n return arrayBufferFor(this.buffer)\n }\n}\n\n/** ContentSource backed by a ReadableStream. Can only be consumed once and does not support slicing. */\nexport class StreamSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /**\n * Forward-only: ReadableStreams cannot be repositioned, so multipart\n * uploads must take the sequential path. See the interface comment on\n * `canSlice` for what the engine does with this flag.\n */\n readonly canSlice = false\n /** Whether the stream has already been read. */\n private consumed = false\n\n /**\n * Create a StreamSource wrapping the given ReadableStream with a known byte size.\n * @param readable - The ReadableStream to wrap as a content source.\n * @param size - The total number of bytes the stream will produce.\n */\n constructor(\n private readonly readable: ReadableStream<Uint8Array>,\n size: number,\n ) {\n validateStreamSourceSize(size)\n this.size = size\n }\n\n /**\n * Always throws because streams cannot be sliced. Buffer the stream first.\n *\n * @throws If slicing is attempted on a stream-backed source.\n */\n slice(): ContentSource {\n throw new Error('StreamSource does not support slicing. Buffer the stream first.')\n }\n\n /**\n * Open the underlying ReadableStream. Can only be called once.\n * @returns The underlying ReadableStream of bytes.\n *\n * @throws If the stream has already been consumed.\n */\n stream(): ReadableStream<Uint8Array> {\n if (this.consumed) throw new Error('StreamSource can only be consumed once.')\n this.consumed = true\n return this.readable\n }\n\n /**\n * Read the entire stream into an ArrayBuffer.\n * @param options - Optional abort signal used while reading.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n const bytes = await collectStreamExactly(this.stream(), this.size, options.signal)\n return bytes.buffer as ArrayBuffer\n }\n}\n\nfunction validateStreamSourceSize(size: number): void {\n if (!Number.isFinite(size) || !Number.isInteger(size) || size < 0) {\n throw new RangeError('StreamSource size must be a non-negative finite integer.')\n }\n}\n\n/**\n * Reads exactly the advertised number of bytes from a stream.\n * @param stream - Stream to consume.\n * @param expectedSize - Exact number of bytes expected from the stream.\n * @param signal - Optional abort signal for cancelling the read.\n *\n * @returns A byte array of length `expectedSize`.\n *\n * @throws If the stream emits too few bytes, too many bytes, too many empty chunks, or aborts.\n */\nexport async function collectStreamExactly(\n stream: ReadableStream<Uint8Array>,\n expectedSize: number,\n signal?: AbortSignal,\n): Promise<Uint8Array<ArrayBuffer>> {\n const reader = stream.getReader()\n const chunks: Uint8Array[] = []\n let total = 0\n let completed = false\n\n try {\n while (total < expectedSize) {\n const { done, value } = await readNextNonEmptyStreamChunk(\n reader,\n STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR,\n signal,\n )\n if (done) throw new Error(STREAM_SOURCE_ENDED_EARLY_ERROR)\n if (total + value.byteLength > expectedSize) {\n throw new Error(STREAM_SOURCE_TOO_MANY_BYTES_ERROR)\n }\n chunks.push(value)\n total += value.byteLength\n }\n\n const extra = await readNextNonEmptyStreamChunk(\n reader,\n STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR,\n signal,\n )\n if (!extra.done) throw new Error(STREAM_SOURCE_TOO_MANY_BYTES_ERROR)\n\n const result = new Uint8Array(expectedSize)\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.byteLength\n }\n completed = true\n return result\n } finally {\n if (!completed) {\n cancelReaderBestEffort(reader)\n }\n try {\n reader.releaseLock()\n } catch {\n // Aborted reads can leave a pending read while best-effort cancel is\n // still unsettled. Preserve the original abort/error instead.\n }\n }\n}\n\n/**\n * Reads from a stream until it receives data, EOF, or too many consecutive empty chunks.\n * @param reader - Locked reader for a Uint8Array stream.\n * @param emptyChunkErrorMessage - Error message to throw when the empty-chunk limit is exceeded.\n * @param signal - Optional abort signal that cancels the reader and rejects the read.\n *\n * @returns The next non-empty chunk or EOF result.\n */\nexport async function readNextNonEmptyStreamChunk(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n emptyChunkErrorMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n let emptyChunks = 0\n while (true) {\n const result = await readStreamChunk(reader, signal)\n if (result.done || result.value.byteLength > 0) return result\n emptyChunks += 1\n if (emptyChunks > MAX_EMPTY_STREAM_CHUNKS) {\n throw new Error(emptyChunkErrorMessage)\n }\n }\n}\n\nasync function readStreamChunk(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n signal: AbortSignal | undefined,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n if (signal === undefined) return reader.read()\n if (signal.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n throw reason\n }\n\n let removeAbortListener: (() => void) | undefined\n const abort = new Promise<never>((_, reject) => {\n const onAbort = (): void => {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n reject(reason)\n }\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n const result = await Promise.race([reader.read(), abort])\n if (signal.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n throw reason\n }\n return result\n } finally {\n removeAbortListener?.()\n }\n}\n\nfunction cancelReaderBestEffort(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n reason?: unknown,\n): void {\n /* v8 ignore next -- Reader cancellation failure is deliberately best-effort. */\n void reader.cancel(reason).catch(() => {})\n}\n\n/** ContentSource backed by a forward-only async iterable of Uint8Array chunks. */\nclass AsyncIterableSource extends StreamSource {\n /**\n * Create an AsyncIterableSource from a known-size async iterable.\n * @param iterable - Async iterable that yields Uint8Array chunks.\n * @param size - Total byte length the iterable will produce.\n */\n constructor(iterable: AsyncIterable<Uint8Array>, size: number) {\n super(asyncIterableToReadableStream(iterable), size)\n }\n}\n\n/**\n * Convert a Uint8Array, Blob, ReadableStream, or async iterable into a {@link ContentSource}.\n * When passing a ReadableStream or async iterable, the `size` parameter is required.\n * @param input - The content to wrap.\n * @param size - The total byte length, required for forward-only inputs.\n *\n * @returns A ContentSource adapter for the given input.\n *\n * @throws If input is forward-only and size is not provided.\n */\nexport function toContentSource(\n input: Uint8Array | Blob | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>,\n size?: number,\n): ContentSource {\n if (input instanceof Uint8Array) {\n return new BufferSource(input)\n }\n if (input instanceof Blob) {\n return new BlobSource(input)\n }\n if (isReadableStream(input)) {\n if (size === undefined) {\n throw new Error(READABLE_STREAM_SIZE_REQUIRED_ERROR)\n }\n return new StreamSource(input, size)\n }\n if (isAsyncIterable(input)) {\n if (size === undefined) {\n throw new Error(FORWARD_ONLY_SIZE_REQUIRED_ERROR)\n }\n return new AsyncIterableSource(input, size)\n }\n throw new TypeError('Unsupported content source input.')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"source.cjs","names":[],"sources":["../../src/streams/source.ts"],"sourcesContent":["import { arrayBufferFor } from '../util/bytes.ts'\nimport { collectStream } from './collect.ts'\n\nexport { FileSource, type FileSourcePath } from './file-source.ts'\n\nconst READABLE_STREAM_SIZE_REQUIRED_ERROR = 'size is required when using a ReadableStream as input.'\nconst FORWARD_ONLY_SIZE_REQUIRED_ERROR =\n 'size is required when using a forward-only content source as input.'\nconst STREAM_SOURCE_ENDED_EARLY_ERROR = 'StreamSource ended before the advertised byte count.'\nconst STREAM_SOURCE_TOO_MANY_BYTES_ERROR =\n 'StreamSource emitted more bytes than the advertised byte count.'\nconst STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR =\n 'StreamSource emitted too many empty chunks without data.'\n/** Maximum consecutive empty chunks tolerated from a forward-only stream. */\nexport const MAX_EMPTY_STREAM_CHUNKS = 1024\n\nfunction asyncIterableToReadableStream(\n iterable: AsyncIterable<Uint8Array>,\n): ReadableStream<Uint8Array> {\n const iterator = iterable[Symbol.asyncIterator]()\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const { done, value } = await iterator.next()\n if (done === true) {\n controller.close()\n return\n }\n if (!(value instanceof Uint8Array)) {\n throw new TypeError('Async iterable content sources must yield Uint8Array chunks.')\n }\n controller.enqueue(value)\n } catch (err) {\n /* v8 ignore next -- Iterator-return failure must not mask the pull error. */\n await returnAsyncIteratorBestEffort(iterator)\n throw err\n }\n },\n async cancel(reason) {\n await returnAsyncIteratorBestEffort(iterator, reason)\n },\n })\n}\n\nasync function returnAsyncIteratorBestEffort(\n iterator: AsyncIterator<Uint8Array>,\n reason?: unknown,\n): Promise<void> {\n try {\n await iterator.return?.(reason)\n } catch {\n // Iterator cleanup is secondary and must not mask the pull error.\n }\n}\n\nfunction isAsyncIterable(input: unknown): input is AsyncIterable<Uint8Array> {\n return (\n typeof input === 'object' &&\n input !== null &&\n Symbol.asyncIterator in input &&\n typeof input[Symbol.asyncIterator] === 'function'\n )\n}\n\nfunction isReadableStream(input: unknown): input is ReadableStream<Uint8Array> {\n return (\n typeof input === 'object' &&\n input !== null &&\n typeof (input as { getReader?: unknown }).getReader === 'function'\n )\n}\n\n/**\n * Uniform adapter for upload content. Wraps File, Blob, Buffer, local files,\n * async iterables, or ReadableStream behind a common interface so upload logic\n * does not depend on the input type.\n */\nexport interface ContentSource {\n /** Total size of the content in bytes. */\n readonly size: number\n /** Pre-computed SHA-1 hex digest, if available. */\n readonly sha1?: string\n /**\n * Whether {@link slice} is safe to call on this source.\n *\n * `true` for in-memory / random-access sources (`BufferSource`,\n * `BlobSource`, `FileSource`) — the multipart upload engine can dispatch\n * part reads in parallel by slicing the source into disjoint ranges.\n * `false` for forward-only streams and async iterables — the engine must\n * read sequentially, one `partSize` chunk at a time. Callers that branch on\n * this flag are expected to fall back to the sequential path rather than call\n * `slice()` and catch the throw.\n */\n readonly canSlice: boolean\n /** Return a sub-range of this source as a new ContentSource. */\n slice(start: number, end: number): ContentSource\n /** Open the content as a ReadableStream. */\n stream(): ReadableStream<Uint8Array>\n /** Read the entire content into an ArrayBuffer. */\n toArrayBuffer(options?: { readonly signal?: AbortSignal }): Promise<ArrayBuffer>\n}\n\n/** ContentSource backed by a Blob or File. */\nexport class BlobSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /** Random-access: `Blob.slice()` is cheap and returns a new Blob view. */\n readonly canSlice = true\n\n /**\n * Create a BlobSource wrapping the given Blob.\n * @param blob - The Blob or File to use as the underlying content.\n */\n constructor(private readonly blob: Blob) {\n this.size = blob.size\n }\n\n /**\n * Return a new BlobSource covering the specified byte range.\n * @param start - The zero-based byte offset to begin the slice.\n * @param end - The exclusive byte offset where the slice ends.\n *\n * @returns A new ContentSource representing the requested sub-range.\n */\n slice(start: number, end: number): ContentSource {\n return new BlobSource(this.blob.slice(start, end))\n }\n\n /**\n * Open the Blob content as a ReadableStream.\n * @returns A ReadableStream of the Blob bytes.\n */\n stream(): ReadableStream<Uint8Array> {\n return this.blob.stream() as ReadableStream<Uint8Array>\n }\n\n /**\n * Read the entire Blob content into an ArrayBuffer.\n * @param options - Optional abort signal used while reading.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n options.signal?.throwIfAborted()\n if (options.signal === undefined) return this.blob.arrayBuffer()\n const bytes = await collectStream(this.stream(), options)\n return arrayBufferFor(bytes)\n }\n}\n\n/** ContentSource backed by a Uint8Array buffer. */\nexport class BufferSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /** Random-access: the entire payload lives in memory. */\n readonly canSlice = true\n\n /**\n * Create a BufferSource wrapping the given Uint8Array.\n * @param buffer - The byte buffer to use as the underlying content.\n */\n constructor(private readonly buffer: Uint8Array) {\n this.size = buffer.byteLength\n }\n\n /**\n * Return a new BufferSource covering the specified byte range.\n * @param start - The zero-based byte offset to begin the slice.\n * @param end - The exclusive byte offset where the slice ends.\n *\n * @returns A new ContentSource representing the requested sub-range.\n */\n slice(start: number, end: number): ContentSource {\n return new BufferSource(this.buffer.slice(start, end))\n }\n\n /**\n * Open the buffer content as a ReadableStream.\n * @returns A ReadableStream that emits the buffer bytes in a single chunk.\n */\n stream(): ReadableStream<Uint8Array> {\n const buffer = this.buffer\n return new ReadableStream({\n start(controller) {\n controller.enqueue(buffer)\n controller.close()\n },\n })\n }\n\n /**\n * Read the entire buffer content into an ArrayBuffer.\n * @param options - Optional abort signal checked before returning bytes.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n options.signal?.throwIfAborted()\n return arrayBufferFor(this.buffer)\n }\n}\n\n/** ContentSource backed by a ReadableStream. Can only be consumed once and does not support slicing. */\nexport class StreamSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /**\n * Forward-only: ReadableStreams cannot be repositioned, so multipart\n * uploads must take the sequential path. See the interface comment on\n * `canSlice` for what the engine does with this flag.\n */\n readonly canSlice = false\n /** Whether the stream has already been read. */\n private consumed = false\n\n /**\n * Create a StreamSource wrapping the given ReadableStream with a known byte size.\n * @param readable - The ReadableStream to wrap as a content source.\n * @param size - The total number of bytes the stream will produce.\n */\n constructor(\n private readonly readable: ReadableStream<Uint8Array>,\n size: number,\n ) {\n validateStreamSourceSize(size)\n this.size = size\n }\n\n /**\n * Always throws because streams cannot be sliced. Buffer the stream first.\n *\n * @throws If slicing is attempted on a stream-backed source.\n */\n slice(): ContentSource {\n throw new Error('StreamSource does not support slicing. Buffer the stream first.')\n }\n\n /**\n * Open the underlying ReadableStream. Can only be called once.\n * @returns The underlying ReadableStream of bytes.\n *\n * @throws If the stream has already been consumed.\n */\n stream(): ReadableStream<Uint8Array> {\n if (this.consumed) throw new Error('StreamSource can only be consumed once.')\n this.consumed = true\n return this.readable\n }\n\n /**\n * Read the entire stream into an ArrayBuffer.\n * @param options - Optional abort signal used while reading.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n const bytes = await collectStreamExactly(this.stream(), this.size, options.signal)\n return bytes.buffer as ArrayBuffer\n }\n}\n\nfunction validateStreamSourceSize(size: number): void {\n if (!Number.isFinite(size) || !Number.isInteger(size) || size < 0) {\n throw new RangeError('StreamSource size must be a non-negative finite integer.')\n }\n}\n\n/**\n * Reads exactly the advertised number of bytes from a stream.\n * @param stream - Stream to consume.\n * @param expectedSize - Exact number of bytes expected from the stream.\n * @param signal - Optional abort signal for cancelling the read.\n *\n * @returns A byte array of length `expectedSize`.\n *\n * @throws If the stream emits too few bytes, too many bytes, too many empty chunks, or aborts.\n */\nexport async function collectStreamExactly(\n stream: ReadableStream<Uint8Array>,\n expectedSize: number,\n signal?: AbortSignal,\n): Promise<Uint8Array<ArrayBuffer>> {\n const reader = stream.getReader()\n const chunks: Uint8Array[] = []\n let total = 0\n let completed = false\n\n try {\n while (total < expectedSize) {\n const { done, value } = await readNextNonEmptyStreamChunk(\n reader,\n STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR,\n signal,\n )\n if (done) throw new Error(STREAM_SOURCE_ENDED_EARLY_ERROR)\n if (total + value.byteLength > expectedSize) {\n throw new Error(STREAM_SOURCE_TOO_MANY_BYTES_ERROR)\n }\n chunks.push(value)\n total += value.byteLength\n }\n\n const extra = await readNextNonEmptyStreamChunk(\n reader,\n STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR,\n signal,\n )\n if (!extra.done) throw new Error(STREAM_SOURCE_TOO_MANY_BYTES_ERROR)\n\n const result = new Uint8Array(expectedSize)\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.byteLength\n }\n completed = true\n return result\n } finally {\n if (!completed) {\n cancelReaderBestEffort(reader)\n }\n try {\n reader.releaseLock()\n } catch {\n // Aborted reads can leave a pending read while best-effort cancel is\n // still unsettled. Preserve the original abort/error instead.\n }\n }\n}\n\n/**\n * Reads from a stream until it receives data, EOF, or too many consecutive empty chunks.\n * @param reader - Locked reader for a Uint8Array stream.\n * @param emptyChunkErrorMessage - Error message to throw when the empty-chunk limit is exceeded.\n * @param signal - Optional abort signal that cancels the reader and rejects the read.\n *\n * @returns The next non-empty chunk or EOF result.\n */\nexport async function readNextNonEmptyStreamChunk(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n emptyChunkErrorMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n let emptyChunks = 0\n while (true) {\n const result = await readStreamChunk(reader, signal)\n if (result.done || result.value.byteLength > 0) return result\n emptyChunks += 1\n if (emptyChunks > MAX_EMPTY_STREAM_CHUNKS) {\n throw new Error(emptyChunkErrorMessage)\n }\n }\n}\n\nasync function readStreamChunk(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n signal: AbortSignal | undefined,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n if (signal === undefined) return reader.read()\n if (signal.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n throw reason\n }\n\n let removeAbortListener: (() => void) | undefined\n const abort = new Promise<never>((_, reject) => {\n const onAbort = (): void => {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n reject(reason)\n }\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n const result = await Promise.race([reader.read(), abort])\n if (signal.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n throw reason\n }\n return result\n } finally {\n removeAbortListener?.()\n }\n}\n\nfunction cancelReaderBestEffort(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n reason?: unknown,\n): void {\n /* v8 ignore next -- Reader cancellation failure is deliberately best-effort. */\n void reader.cancel(reason).catch(() => {})\n}\n\n/** ContentSource backed by a forward-only async iterable of Uint8Array chunks. */\nclass AsyncIterableSource extends StreamSource {\n /**\n * Create an AsyncIterableSource from a known-size async iterable.\n * @param iterable - Async iterable that yields Uint8Array chunks.\n * @param size - Total byte length the iterable will produce.\n */\n constructor(iterable: AsyncIterable<Uint8Array>, size: number) {\n super(asyncIterableToReadableStream(iterable), size)\n }\n}\n\n/**\n * Convert a Uint8Array, Blob, ReadableStream, or async iterable into a {@link ContentSource}.\n * When passing a ReadableStream or async iterable, the `size` parameter is required.\n * @param input - The content to wrap.\n * @param size - The total byte length, required for forward-only inputs.\n *\n * @returns A ContentSource adapter for the given input.\n *\n * @throws If input is forward-only and size is not provided.\n */\nexport function toContentSource(\n input: Uint8Array | Blob | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>,\n size?: number,\n): ContentSource {\n if (input instanceof Uint8Array) {\n return new BufferSource(input)\n }\n if (input instanceof Blob) {\n return new BlobSource(input)\n }\n if (isReadableStream(input)) {\n if (size === undefined) {\n throw new Error(READABLE_STREAM_SIZE_REQUIRED_ERROR)\n }\n return new StreamSource(input, size)\n }\n if (isAsyncIterable(input)) {\n if (size === undefined) {\n throw new Error(FORWARD_ONLY_SIZE_REQUIRED_ERROR)\n }\n return new AsyncIterableSource(input, size)\n }\n throw new TypeError('Unsupported content source input.')\n}\n"],"mappings":"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"}
@@ -84,7 +84,8 @@ var BlobSource = class BlobSource {
84
84
  async toArrayBuffer(options = {}) {
85
85
  options.signal?.throwIfAborted();
86
86
  if (options.signal === void 0) return this.blob.arrayBuffer();
87
- return arrayBufferFor(await collectStream(this.stream(), options));
87
+ const bytes = await collectStream(this.stream(), options);
88
+ return arrayBufferFor(bytes);
88
89
  }
89
90
  };
90
91
  /** ContentSource backed by a Uint8Array buffer. */
@@ -1 +1 @@
1
- {"version":3,"file":"source.js","names":[],"sources":["../../src/streams/source.ts"],"sourcesContent":["import { arrayBufferFor } from '../util/bytes.ts'\nimport { collectStream } from './collect.ts'\n\nexport { FileSource, type FileSourcePath } from './file-source.ts'\n\nconst READABLE_STREAM_SIZE_REQUIRED_ERROR = 'size is required when using a ReadableStream as input.'\nconst FORWARD_ONLY_SIZE_REQUIRED_ERROR =\n 'size is required when using a forward-only content source as input.'\nconst STREAM_SOURCE_ENDED_EARLY_ERROR = 'StreamSource ended before the advertised byte count.'\nconst STREAM_SOURCE_TOO_MANY_BYTES_ERROR =\n 'StreamSource emitted more bytes than the advertised byte count.'\nconst STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR =\n 'StreamSource emitted too many empty chunks without data.'\n/** Maximum consecutive empty chunks tolerated from a forward-only stream. */\nexport const MAX_EMPTY_STREAM_CHUNKS = 1024\n\nfunction asyncIterableToReadableStream(\n iterable: AsyncIterable<Uint8Array>,\n): ReadableStream<Uint8Array> {\n const iterator = iterable[Symbol.asyncIterator]()\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const { done, value } = await iterator.next()\n if (done === true) {\n controller.close()\n return\n }\n if (!(value instanceof Uint8Array)) {\n throw new TypeError('Async iterable content sources must yield Uint8Array chunks.')\n }\n controller.enqueue(value)\n } catch (err) {\n /* v8 ignore next -- Iterator-return failure must not mask the pull error. */\n await returnAsyncIteratorBestEffort(iterator)\n throw err\n }\n },\n async cancel(reason) {\n await returnAsyncIteratorBestEffort(iterator, reason)\n },\n })\n}\n\nasync function returnAsyncIteratorBestEffort(\n iterator: AsyncIterator<Uint8Array>,\n reason?: unknown,\n): Promise<void> {\n try {\n await iterator.return?.(reason)\n } catch {\n // Iterator cleanup is secondary and must not mask the pull error.\n }\n}\n\nfunction isAsyncIterable(input: unknown): input is AsyncIterable<Uint8Array> {\n return (\n typeof input === 'object' &&\n input !== null &&\n Symbol.asyncIterator in input &&\n typeof input[Symbol.asyncIterator] === 'function'\n )\n}\n\nfunction isReadableStream(input: unknown): input is ReadableStream<Uint8Array> {\n return (\n typeof input === 'object' &&\n input !== null &&\n typeof (input as { getReader?: unknown }).getReader === 'function'\n )\n}\n\n/**\n * Uniform adapter for upload content. Wraps File, Blob, Buffer, local files,\n * async iterables, or ReadableStream behind a common interface so upload logic\n * does not depend on the input type.\n */\nexport interface ContentSource {\n /** Total size of the content in bytes. */\n readonly size: number\n /** Pre-computed SHA-1 hex digest, if available. */\n readonly sha1?: string\n /**\n * Whether {@link slice} is safe to call on this source.\n *\n * `true` for in-memory / random-access sources (`BufferSource`,\n * `BlobSource`, `FileSource`) — the multipart upload engine can dispatch\n * part reads in parallel by slicing the source into disjoint ranges.\n * `false` for forward-only streams and async iterables — the engine must\n * read sequentially, one `partSize` chunk at a time. Callers that branch on\n * this flag are expected to fall back to the sequential path rather than call\n * `slice()` and catch the throw.\n */\n readonly canSlice: boolean\n /** Return a sub-range of this source as a new ContentSource. */\n slice(start: number, end: number): ContentSource\n /** Open the content as a ReadableStream. */\n stream(): ReadableStream<Uint8Array>\n /** Read the entire content into an ArrayBuffer. */\n toArrayBuffer(options?: { readonly signal?: AbortSignal }): Promise<ArrayBuffer>\n}\n\n/** ContentSource backed by a Blob or File. */\nexport class BlobSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /** Random-access: `Blob.slice()` is cheap and returns a new Blob view. */\n readonly canSlice = true\n\n /**\n * Create a BlobSource wrapping the given Blob.\n * @param blob - The Blob or File to use as the underlying content.\n */\n constructor(private readonly blob: Blob) {\n this.size = blob.size\n }\n\n /**\n * Return a new BlobSource covering the specified byte range.\n * @param start - The zero-based byte offset to begin the slice.\n * @param end - The exclusive byte offset where the slice ends.\n *\n * @returns A new ContentSource representing the requested sub-range.\n */\n slice(start: number, end: number): ContentSource {\n return new BlobSource(this.blob.slice(start, end))\n }\n\n /**\n * Open the Blob content as a ReadableStream.\n * @returns A ReadableStream of the Blob bytes.\n */\n stream(): ReadableStream<Uint8Array> {\n return this.blob.stream() as ReadableStream<Uint8Array>\n }\n\n /**\n * Read the entire Blob content into an ArrayBuffer.\n * @param options - Optional abort signal used while reading.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n options.signal?.throwIfAborted()\n if (options.signal === undefined) return this.blob.arrayBuffer()\n const bytes = await collectStream(this.stream(), options)\n return arrayBufferFor(bytes)\n }\n}\n\n/** ContentSource backed by a Uint8Array buffer. */\nexport class BufferSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /** Random-access: the entire payload lives in memory. */\n readonly canSlice = true\n\n /**\n * Create a BufferSource wrapping the given Uint8Array.\n * @param buffer - The byte buffer to use as the underlying content.\n */\n constructor(private readonly buffer: Uint8Array) {\n this.size = buffer.byteLength\n }\n\n /**\n * Return a new BufferSource covering the specified byte range.\n * @param start - The zero-based byte offset to begin the slice.\n * @param end - The exclusive byte offset where the slice ends.\n *\n * @returns A new ContentSource representing the requested sub-range.\n */\n slice(start: number, end: number): ContentSource {\n return new BufferSource(this.buffer.slice(start, end))\n }\n\n /**\n * Open the buffer content as a ReadableStream.\n * @returns A ReadableStream that emits the buffer bytes in a single chunk.\n */\n stream(): ReadableStream<Uint8Array> {\n const buffer = this.buffer\n return new ReadableStream({\n start(controller) {\n controller.enqueue(buffer)\n controller.close()\n },\n })\n }\n\n /**\n * Read the entire buffer content into an ArrayBuffer.\n * @param options - Optional abort signal checked before returning bytes.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n options.signal?.throwIfAborted()\n return arrayBufferFor(this.buffer)\n }\n}\n\n/** ContentSource backed by a ReadableStream. Can only be consumed once and does not support slicing. */\nexport class StreamSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /**\n * Forward-only: ReadableStreams cannot be repositioned, so multipart\n * uploads must take the sequential path. See the interface comment on\n * `canSlice` for what the engine does with this flag.\n */\n readonly canSlice = false\n /** Whether the stream has already been read. */\n private consumed = false\n\n /**\n * Create a StreamSource wrapping the given ReadableStream with a known byte size.\n * @param readable - The ReadableStream to wrap as a content source.\n * @param size - The total number of bytes the stream will produce.\n */\n constructor(\n private readonly readable: ReadableStream<Uint8Array>,\n size: number,\n ) {\n validateStreamSourceSize(size)\n this.size = size\n }\n\n /**\n * Always throws because streams cannot be sliced. Buffer the stream first.\n *\n * @throws If slicing is attempted on a stream-backed source.\n */\n slice(): ContentSource {\n throw new Error('StreamSource does not support slicing. Buffer the stream first.')\n }\n\n /**\n * Open the underlying ReadableStream. Can only be called once.\n * @returns The underlying ReadableStream of bytes.\n *\n * @throws If the stream has already been consumed.\n */\n stream(): ReadableStream<Uint8Array> {\n if (this.consumed) throw new Error('StreamSource can only be consumed once.')\n this.consumed = true\n return this.readable\n }\n\n /**\n * Read the entire stream into an ArrayBuffer.\n * @param options - Optional abort signal used while reading.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n const bytes = await collectStreamExactly(this.stream(), this.size, options.signal)\n return bytes.buffer as ArrayBuffer\n }\n}\n\nfunction validateStreamSourceSize(size: number): void {\n if (!Number.isFinite(size) || !Number.isInteger(size) || size < 0) {\n throw new RangeError('StreamSource size must be a non-negative finite integer.')\n }\n}\n\n/**\n * Reads exactly the advertised number of bytes from a stream.\n * @param stream - Stream to consume.\n * @param expectedSize - Exact number of bytes expected from the stream.\n * @param signal - Optional abort signal for cancelling the read.\n *\n * @returns A byte array of length `expectedSize`.\n *\n * @throws If the stream emits too few bytes, too many bytes, too many empty chunks, or aborts.\n */\nexport async function collectStreamExactly(\n stream: ReadableStream<Uint8Array>,\n expectedSize: number,\n signal?: AbortSignal,\n): Promise<Uint8Array<ArrayBuffer>> {\n const reader = stream.getReader()\n const chunks: Uint8Array[] = []\n let total = 0\n let completed = false\n\n try {\n while (total < expectedSize) {\n const { done, value } = await readNextNonEmptyStreamChunk(\n reader,\n STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR,\n signal,\n )\n if (done) throw new Error(STREAM_SOURCE_ENDED_EARLY_ERROR)\n if (total + value.byteLength > expectedSize) {\n throw new Error(STREAM_SOURCE_TOO_MANY_BYTES_ERROR)\n }\n chunks.push(value)\n total += value.byteLength\n }\n\n const extra = await readNextNonEmptyStreamChunk(\n reader,\n STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR,\n signal,\n )\n if (!extra.done) throw new Error(STREAM_SOURCE_TOO_MANY_BYTES_ERROR)\n\n const result = new Uint8Array(expectedSize)\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.byteLength\n }\n completed = true\n return result\n } finally {\n if (!completed) {\n cancelReaderBestEffort(reader)\n }\n try {\n reader.releaseLock()\n } catch {\n // Aborted reads can leave a pending read while best-effort cancel is\n // still unsettled. Preserve the original abort/error instead.\n }\n }\n}\n\n/**\n * Reads from a stream until it receives data, EOF, or too many consecutive empty chunks.\n * @param reader - Locked reader for a Uint8Array stream.\n * @param emptyChunkErrorMessage - Error message to throw when the empty-chunk limit is exceeded.\n * @param signal - Optional abort signal that cancels the reader and rejects the read.\n *\n * @returns The next non-empty chunk or EOF result.\n */\nexport async function readNextNonEmptyStreamChunk(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n emptyChunkErrorMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n let emptyChunks = 0\n while (true) {\n const result = await readStreamChunk(reader, signal)\n if (result.done || result.value.byteLength > 0) return result\n emptyChunks += 1\n if (emptyChunks > MAX_EMPTY_STREAM_CHUNKS) {\n throw new Error(emptyChunkErrorMessage)\n }\n }\n}\n\nasync function readStreamChunk(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n signal: AbortSignal | undefined,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n if (signal === undefined) return reader.read()\n if (signal.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n throw reason\n }\n\n let removeAbortListener: (() => void) | undefined\n const abort = new Promise<never>((_, reject) => {\n const onAbort = (): void => {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n reject(reason)\n }\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n const result = await Promise.race([reader.read(), abort])\n if (signal.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n throw reason\n }\n return result\n } finally {\n removeAbortListener?.()\n }\n}\n\nfunction cancelReaderBestEffort(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n reason?: unknown,\n): void {\n /* v8 ignore next -- Reader cancellation failure is deliberately best-effort. */\n void reader.cancel(reason).catch(() => {})\n}\n\n/** ContentSource backed by a forward-only async iterable of Uint8Array chunks. */\nclass AsyncIterableSource extends StreamSource {\n /**\n * Create an AsyncIterableSource from a known-size async iterable.\n * @param iterable - Async iterable that yields Uint8Array chunks.\n * @param size - Total byte length the iterable will produce.\n */\n constructor(iterable: AsyncIterable<Uint8Array>, size: number) {\n super(asyncIterableToReadableStream(iterable), size)\n }\n}\n\n/**\n * Convert a Uint8Array, Blob, ReadableStream, or async iterable into a {@link ContentSource}.\n * When passing a ReadableStream or async iterable, the `size` parameter is required.\n * @param input - The content to wrap.\n * @param size - The total byte length, required for forward-only inputs.\n *\n * @returns A ContentSource adapter for the given input.\n *\n * @throws If input is forward-only and size is not provided.\n */\nexport function toContentSource(\n input: Uint8Array | Blob | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>,\n size?: number,\n): ContentSource {\n if (input instanceof Uint8Array) {\n return new BufferSource(input)\n }\n if (input instanceof Blob) {\n return new BlobSource(input)\n }\n if (isReadableStream(input)) {\n if (size === undefined) {\n throw new Error(READABLE_STREAM_SIZE_REQUIRED_ERROR)\n }\n return new StreamSource(input, size)\n }\n if (isAsyncIterable(input)) {\n if (size === undefined) {\n throw new Error(FORWARD_ONLY_SIZE_REQUIRED_ERROR)\n }\n return new AsyncIterableSource(input, size)\n }\n throw new TypeError('Unsupported content source input.')\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"source.js","names":[],"sources":["../../src/streams/source.ts"],"sourcesContent":["import { arrayBufferFor } from '../util/bytes.ts'\nimport { collectStream } from './collect.ts'\n\nexport { FileSource, type FileSourcePath } from './file-source.ts'\n\nconst READABLE_STREAM_SIZE_REQUIRED_ERROR = 'size is required when using a ReadableStream as input.'\nconst FORWARD_ONLY_SIZE_REQUIRED_ERROR =\n 'size is required when using a forward-only content source as input.'\nconst STREAM_SOURCE_ENDED_EARLY_ERROR = 'StreamSource ended before the advertised byte count.'\nconst STREAM_SOURCE_TOO_MANY_BYTES_ERROR =\n 'StreamSource emitted more bytes than the advertised byte count.'\nconst STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR =\n 'StreamSource emitted too many empty chunks without data.'\n/** Maximum consecutive empty chunks tolerated from a forward-only stream. */\nexport const MAX_EMPTY_STREAM_CHUNKS = 1024\n\nfunction asyncIterableToReadableStream(\n iterable: AsyncIterable<Uint8Array>,\n): ReadableStream<Uint8Array> {\n const iterator = iterable[Symbol.asyncIterator]()\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n const { done, value } = await iterator.next()\n if (done === true) {\n controller.close()\n return\n }\n if (!(value instanceof Uint8Array)) {\n throw new TypeError('Async iterable content sources must yield Uint8Array chunks.')\n }\n controller.enqueue(value)\n } catch (err) {\n /* v8 ignore next -- Iterator-return failure must not mask the pull error. */\n await returnAsyncIteratorBestEffort(iterator)\n throw err\n }\n },\n async cancel(reason) {\n await returnAsyncIteratorBestEffort(iterator, reason)\n },\n })\n}\n\nasync function returnAsyncIteratorBestEffort(\n iterator: AsyncIterator<Uint8Array>,\n reason?: unknown,\n): Promise<void> {\n try {\n await iterator.return?.(reason)\n } catch {\n // Iterator cleanup is secondary and must not mask the pull error.\n }\n}\n\nfunction isAsyncIterable(input: unknown): input is AsyncIterable<Uint8Array> {\n return (\n typeof input === 'object' &&\n input !== null &&\n Symbol.asyncIterator in input &&\n typeof input[Symbol.asyncIterator] === 'function'\n )\n}\n\nfunction isReadableStream(input: unknown): input is ReadableStream<Uint8Array> {\n return (\n typeof input === 'object' &&\n input !== null &&\n typeof (input as { getReader?: unknown }).getReader === 'function'\n )\n}\n\n/**\n * Uniform adapter for upload content. Wraps File, Blob, Buffer, local files,\n * async iterables, or ReadableStream behind a common interface so upload logic\n * does not depend on the input type.\n */\nexport interface ContentSource {\n /** Total size of the content in bytes. */\n readonly size: number\n /** Pre-computed SHA-1 hex digest, if available. */\n readonly sha1?: string\n /**\n * Whether {@link slice} is safe to call on this source.\n *\n * `true` for in-memory / random-access sources (`BufferSource`,\n * `BlobSource`, `FileSource`) — the multipart upload engine can dispatch\n * part reads in parallel by slicing the source into disjoint ranges.\n * `false` for forward-only streams and async iterables — the engine must\n * read sequentially, one `partSize` chunk at a time. Callers that branch on\n * this flag are expected to fall back to the sequential path rather than call\n * `slice()` and catch the throw.\n */\n readonly canSlice: boolean\n /** Return a sub-range of this source as a new ContentSource. */\n slice(start: number, end: number): ContentSource\n /** Open the content as a ReadableStream. */\n stream(): ReadableStream<Uint8Array>\n /** Read the entire content into an ArrayBuffer. */\n toArrayBuffer(options?: { readonly signal?: AbortSignal }): Promise<ArrayBuffer>\n}\n\n/** ContentSource backed by a Blob or File. */\nexport class BlobSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /** Random-access: `Blob.slice()` is cheap and returns a new Blob view. */\n readonly canSlice = true\n\n /**\n * Create a BlobSource wrapping the given Blob.\n * @param blob - The Blob or File to use as the underlying content.\n */\n constructor(private readonly blob: Blob) {\n this.size = blob.size\n }\n\n /**\n * Return a new BlobSource covering the specified byte range.\n * @param start - The zero-based byte offset to begin the slice.\n * @param end - The exclusive byte offset where the slice ends.\n *\n * @returns A new ContentSource representing the requested sub-range.\n */\n slice(start: number, end: number): ContentSource {\n return new BlobSource(this.blob.slice(start, end))\n }\n\n /**\n * Open the Blob content as a ReadableStream.\n * @returns A ReadableStream of the Blob bytes.\n */\n stream(): ReadableStream<Uint8Array> {\n return this.blob.stream() as ReadableStream<Uint8Array>\n }\n\n /**\n * Read the entire Blob content into an ArrayBuffer.\n * @param options - Optional abort signal used while reading.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n options.signal?.throwIfAborted()\n if (options.signal === undefined) return this.blob.arrayBuffer()\n const bytes = await collectStream(this.stream(), options)\n return arrayBufferFor(bytes)\n }\n}\n\n/** ContentSource backed by a Uint8Array buffer. */\nexport class BufferSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /** Random-access: the entire payload lives in memory. */\n readonly canSlice = true\n\n /**\n * Create a BufferSource wrapping the given Uint8Array.\n * @param buffer - The byte buffer to use as the underlying content.\n */\n constructor(private readonly buffer: Uint8Array) {\n this.size = buffer.byteLength\n }\n\n /**\n * Return a new BufferSource covering the specified byte range.\n * @param start - The zero-based byte offset to begin the slice.\n * @param end - The exclusive byte offset where the slice ends.\n *\n * @returns A new ContentSource representing the requested sub-range.\n */\n slice(start: number, end: number): ContentSource {\n return new BufferSource(this.buffer.slice(start, end))\n }\n\n /**\n * Open the buffer content as a ReadableStream.\n * @returns A ReadableStream that emits the buffer bytes in a single chunk.\n */\n stream(): ReadableStream<Uint8Array> {\n const buffer = this.buffer\n return new ReadableStream({\n start(controller) {\n controller.enqueue(buffer)\n controller.close()\n },\n })\n }\n\n /**\n * Read the entire buffer content into an ArrayBuffer.\n * @param options - Optional abort signal checked before returning bytes.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n options.signal?.throwIfAborted()\n return arrayBufferFor(this.buffer)\n }\n}\n\n/** ContentSource backed by a ReadableStream. Can only be consumed once and does not support slicing. */\nexport class StreamSource implements ContentSource {\n /** {@inheritDoc} */\n readonly size: number\n /**\n * Forward-only: ReadableStreams cannot be repositioned, so multipart\n * uploads must take the sequential path. See the interface comment on\n * `canSlice` for what the engine does with this flag.\n */\n readonly canSlice = false\n /** Whether the stream has already been read. */\n private consumed = false\n\n /**\n * Create a StreamSource wrapping the given ReadableStream with a known byte size.\n * @param readable - The ReadableStream to wrap as a content source.\n * @param size - The total number of bytes the stream will produce.\n */\n constructor(\n private readonly readable: ReadableStream<Uint8Array>,\n size: number,\n ) {\n validateStreamSourceSize(size)\n this.size = size\n }\n\n /**\n * Always throws because streams cannot be sliced. Buffer the stream first.\n *\n * @throws If slicing is attempted on a stream-backed source.\n */\n slice(): ContentSource {\n throw new Error('StreamSource does not support slicing. Buffer the stream first.')\n }\n\n /**\n * Open the underlying ReadableStream. Can only be called once.\n * @returns The underlying ReadableStream of bytes.\n *\n * @throws If the stream has already been consumed.\n */\n stream(): ReadableStream<Uint8Array> {\n if (this.consumed) throw new Error('StreamSource can only be consumed once.')\n this.consumed = true\n return this.readable\n }\n\n /**\n * Read the entire stream into an ArrayBuffer.\n * @param options - Optional abort signal used while reading.\n *\n * @returns A promise that resolves with the full content as an ArrayBuffer.\n */\n async toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n const bytes = await collectStreamExactly(this.stream(), this.size, options.signal)\n return bytes.buffer as ArrayBuffer\n }\n}\n\nfunction validateStreamSourceSize(size: number): void {\n if (!Number.isFinite(size) || !Number.isInteger(size) || size < 0) {\n throw new RangeError('StreamSource size must be a non-negative finite integer.')\n }\n}\n\n/**\n * Reads exactly the advertised number of bytes from a stream.\n * @param stream - Stream to consume.\n * @param expectedSize - Exact number of bytes expected from the stream.\n * @param signal - Optional abort signal for cancelling the read.\n *\n * @returns A byte array of length `expectedSize`.\n *\n * @throws If the stream emits too few bytes, too many bytes, too many empty chunks, or aborts.\n */\nexport async function collectStreamExactly(\n stream: ReadableStream<Uint8Array>,\n expectedSize: number,\n signal?: AbortSignal,\n): Promise<Uint8Array<ArrayBuffer>> {\n const reader = stream.getReader()\n const chunks: Uint8Array[] = []\n let total = 0\n let completed = false\n\n try {\n while (total < expectedSize) {\n const { done, value } = await readNextNonEmptyStreamChunk(\n reader,\n STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR,\n signal,\n )\n if (done) throw new Error(STREAM_SOURCE_ENDED_EARLY_ERROR)\n if (total + value.byteLength > expectedSize) {\n throw new Error(STREAM_SOURCE_TOO_MANY_BYTES_ERROR)\n }\n chunks.push(value)\n total += value.byteLength\n }\n\n const extra = await readNextNonEmptyStreamChunk(\n reader,\n STREAM_SOURCE_TOO_MANY_EMPTY_CHUNKS_ERROR,\n signal,\n )\n if (!extra.done) throw new Error(STREAM_SOURCE_TOO_MANY_BYTES_ERROR)\n\n const result = new Uint8Array(expectedSize)\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.byteLength\n }\n completed = true\n return result\n } finally {\n if (!completed) {\n cancelReaderBestEffort(reader)\n }\n try {\n reader.releaseLock()\n } catch {\n // Aborted reads can leave a pending read while best-effort cancel is\n // still unsettled. Preserve the original abort/error instead.\n }\n }\n}\n\n/**\n * Reads from a stream until it receives data, EOF, or too many consecutive empty chunks.\n * @param reader - Locked reader for a Uint8Array stream.\n * @param emptyChunkErrorMessage - Error message to throw when the empty-chunk limit is exceeded.\n * @param signal - Optional abort signal that cancels the reader and rejects the read.\n *\n * @returns The next non-empty chunk or EOF result.\n */\nexport async function readNextNonEmptyStreamChunk(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n emptyChunkErrorMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n let emptyChunks = 0\n while (true) {\n const result = await readStreamChunk(reader, signal)\n if (result.done || result.value.byteLength > 0) return result\n emptyChunks += 1\n if (emptyChunks > MAX_EMPTY_STREAM_CHUNKS) {\n throw new Error(emptyChunkErrorMessage)\n }\n }\n}\n\nasync function readStreamChunk(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n signal: AbortSignal | undefined,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n if (signal === undefined) return reader.read()\n if (signal.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n throw reason\n }\n\n let removeAbortListener: (() => void) | undefined\n const abort = new Promise<never>((_, reject) => {\n const onAbort = (): void => {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n reject(reason)\n }\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n const result = await Promise.race([reader.read(), abort])\n if (signal.aborted) {\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n cancelReaderBestEffort(reader, reason)\n throw reason\n }\n return result\n } finally {\n removeAbortListener?.()\n }\n}\n\nfunction cancelReaderBestEffort(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n reason?: unknown,\n): void {\n /* v8 ignore next -- Reader cancellation failure is deliberately best-effort. */\n void reader.cancel(reason).catch(() => {})\n}\n\n/** ContentSource backed by a forward-only async iterable of Uint8Array chunks. */\nclass AsyncIterableSource extends StreamSource {\n /**\n * Create an AsyncIterableSource from a known-size async iterable.\n * @param iterable - Async iterable that yields Uint8Array chunks.\n * @param size - Total byte length the iterable will produce.\n */\n constructor(iterable: AsyncIterable<Uint8Array>, size: number) {\n super(asyncIterableToReadableStream(iterable), size)\n }\n}\n\n/**\n * Convert a Uint8Array, Blob, ReadableStream, or async iterable into a {@link ContentSource}.\n * When passing a ReadableStream or async iterable, the `size` parameter is required.\n * @param input - The content to wrap.\n * @param size - The total byte length, required for forward-only inputs.\n *\n * @returns A ContentSource adapter for the given input.\n *\n * @throws If input is forward-only and size is not provided.\n */\nexport function toContentSource(\n input: Uint8Array | Blob | ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>,\n size?: number,\n): ContentSource {\n if (input instanceof Uint8Array) {\n return new BufferSource(input)\n }\n if (input instanceof Blob) {\n return new BlobSource(input)\n }\n if (isReadableStream(input)) {\n if (size === undefined) {\n throw new Error(READABLE_STREAM_SIZE_REQUIRED_ERROR)\n }\n return new StreamSource(input, size)\n }\n if (isAsyncIterable(input)) {\n if (size === undefined) {\n throw new Error(FORWARD_ONLY_SIZE_REQUIRED_ERROR)\n }\n return new AsyncIterableSource(input, size)\n }\n throw new TypeError('Unsupported content source input.')\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ const require_abort = require("../util/abort.cjs");
1
2
  const require_hash = require("../streams/hash.cjs");
2
3
  const require_sha1_options = require("./sha1-options.cjs");
3
4
  //#region src/sync/b2-sha1-reader.ts
@@ -26,7 +27,7 @@ async function readStreamChunkWithTimeout(reader, timeoutMillis, stalledMessage,
26
27
  }
27
28
  }
28
29
  async function readRawStreamChunkWithTimeout(reader, timeoutMillis, stalledMessage, signal) {
29
- signal?.throwIfAborted();
30
+ require_abort.throwIfSignalAborted(signal);
30
31
  let timeout;
31
32
  let removeAbortListener;
32
33
  const readPromise = reader.read();
@@ -36,9 +37,12 @@ async function readRawStreamChunkWithTimeout(reader, timeoutMillis, stalledMessa
36
37
  }, timeoutMillis);
37
38
  });
38
39
  const abortPromise = signal === void 0 ? void 0 : new Promise((_, reject) => {
39
- const onAbort = () => reject(signal.reason ?? /* @__PURE__ */ new Error("aborted"));
40
+ const onAbort = () => {
41
+ reject(require_abort.abortReason(signal));
42
+ };
40
43
  signal.addEventListener("abort", onAbort, { once: true });
41
44
  removeAbortListener = () => signal.removeEventListener("abort", onAbort);
45
+ if (signal.aborted) onAbort();
42
46
  });
43
47
  try {
44
48
  if (timeoutPromise === void 0 && abortPromise === void 0) return await readPromise;
@@ -1 +1 @@
1
- {"version":3,"file":"b2-sha1-reader.cjs","names":[],"sources":["../../src/sync/b2-sha1-reader.ts"],"sourcesContent":["import { IncrementalSha1 } from '../streams/hash.ts'\nimport { normalizeSha1TimeoutMillis } from './sha1-options.ts'\n\nconst MAX_CONSECUTIVE_EMPTY_READ_CHUNKS = 1024\n\n/**\n * Reads one non-empty stream chunk with an idle timeout and optional abort signal.\n * Empty chunks are not progress; too many consecutive empty chunks fail with the\n * same stalled-read diagnostic used for pending reads.\n *\n * @param reader - Locked reader to read from.\n * @param timeoutMillis - Idle timeout in milliseconds for this read.\n * @param stalledMessage - Error message used when the read makes no progress.\n * @param signal - Optional abort signal to observe while reading.\n *\n * @returns The next stream read result.\n *\n * @internal\n */\nexport async function readStreamChunkWithTimeout(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n timeoutMillis: number,\n stalledMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n let emptyChunks = 0\n while (true) {\n const result = await readRawStreamChunkWithTimeout(\n reader,\n timeoutMillis,\n stalledMessage,\n signal,\n )\n if (result.done || result.value.byteLength > 0) return result\n emptyChunks += 1\n if (emptyChunks > MAX_CONSECUTIVE_EMPTY_READ_CHUNKS) {\n throw new Error(stalledMessage)\n }\n }\n}\n\nasync function readRawStreamChunkWithTimeout(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n timeoutMillis: number,\n stalledMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n signal?.throwIfAborted()\n\n let timeout: ReturnType<typeof setTimeout> | undefined\n let removeAbortListener: (() => void) | undefined\n const readPromise = reader.read()\n const timeoutPromise =\n timeoutMillis === Number.POSITIVE_INFINITY\n ? undefined\n : new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n reject(new Error(stalledMessage))\n }, timeoutMillis)\n })\n const abortPromise =\n signal === undefined\n ? undefined\n : new Promise<never>((_, reject) => {\n const onAbort = () => reject(signal.reason ?? new Error('aborted'))\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n if (timeoutPromise === undefined && abortPromise === undefined) return await readPromise\n const candidates = [readPromise]\n if (timeoutPromise !== undefined) candidates.push(timeoutPromise)\n if (abortPromise !== undefined) candidates.push(abortPromise)\n return await Promise.race(candidates)\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n removeAbortListener?.()\n void readPromise.catch(() => {})\n }\n}\n\n/**\n * Hashes a B2 response body as SHA-1 with idle timeout, abort, and size checks.\n *\n * @param body - Response body stream to hash.\n * @param signal - Optional abort signal to observe while reading.\n * @param options - Optional timeout and byte-count limits.\n *\n * @returns The computed SHA-1 and number of bytes read.\n *\n * @internal\n */\nexport async function hashReadableStreamSha1(\n body: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n options?: {\n readonly idleTimeoutMillis: number\n readonly maxBytes: number\n readonly expectedBytes: number\n },\n): Promise<{ readonly contentSha1: string; readonly bytesRead: number }> {\n const hash = new IncrementalSha1()\n const reader = body.getReader()\n const idleTimeoutMillis = options?.idleTimeoutMillis ?? normalizeSha1TimeoutMillis(undefined)\n const maxBytes = options?.maxBytes ?? Number.POSITIVE_INFINITY\n const expectedBytes = options?.expectedBytes\n let bytesRead = 0\n try {\n while (true) {\n const { done, value } = await readStreamChunkWithTimeout(\n reader,\n idleTimeoutMillis,\n `sha1 B2 read stalled for ${idleTimeoutMillis} ms`,\n signal,\n )\n if (done) break\n bytesRead += value.byteLength\n if (bytesRead > maxBytes) {\n throw new Error(`sha1 B2 read exceeded ${maxBytes} byte verification budget`)\n }\n await hash.update(value)\n }\n if (expectedBytes !== undefined && bytesRead !== expectedBytes) {\n throw new Error(`sha1 B2 read ended after ${bytesRead} bytes, expected ${expectedBytes}`)\n }\n return { contentSha1: await hash.digest(), bytesRead }\n } catch (err) {\n void reader.cancel(err).catch(() => {})\n throw err\n } finally {\n reader.releaseLock()\n }\n}\n\n/**\n * Applies an absolute verification deadline while forwarding parent aborts.\n *\n * @param signal - Optional parent abort signal.\n * @param timeoutMillis - Absolute deadline in milliseconds.\n * @param run - Operation to run with the derived deadline signal.\n *\n * @returns The operation result.\n *\n * @internal\n */\nexport async function withSha1VerificationDeadline<T>(\n signal: AbortSignal | undefined,\n timeoutMillis: number,\n run: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n const controller = new AbortController()\n const abortFromParent = () => controller.abort(signal?.reason)\n if (signal?.aborted) abortFromParent()\n signal?.addEventListener('abort', abortFromParent, { once: true })\n\n let timeout: ReturnType<typeof setTimeout> | undefined\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n const error = new Error(`sha1 B2 verification exceeded ${timeoutMillis} ms`)\n controller.abort(error)\n reject(error)\n }, timeoutMillis)\n })\n const runPromise = run(controller.signal)\n try {\n return await Promise.race([runPromise, timeoutPromise])\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n signal?.removeEventListener('abort', abortFromParent)\n void runPromise.catch(() => {})\n }\n}\n\n/**\n * Bounds B2 SHA-1 verification downloads to the selected object's size and optional ceiling.\n *\n * @param contentLength - Selected B2 object byte length.\n * @param ceiling - Optional lower verification budget.\n *\n * @returns The byte budget to enforce.\n *\n * @internal\n */\nexport function normalizeSha1VerificationMaxBytes(\n contentLength: number,\n ceiling: number | undefined,\n): number {\n const contentBudget = Math.max(0, Math.floor(contentLength))\n if (ceiling === undefined) return contentBudget\n if (!Number.isFinite(ceiling) || ceiling < 0) return contentBudget\n return Math.min(contentBudget, Math.floor(ceiling))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"b2-sha1-reader.cjs","names":[],"sources":["../../src/sync/b2-sha1-reader.ts"],"sourcesContent":["import { IncrementalSha1 } from '../streams/hash.ts'\nimport { abortReason, throwIfSignalAborted } from '../util/abort.ts'\nimport { normalizeSha1TimeoutMillis } from './sha1-options.ts'\n\nconst MAX_CONSECUTIVE_EMPTY_READ_CHUNKS = 1024\n\n/**\n * Reads one non-empty stream chunk with an idle timeout and optional abort signal.\n * Empty chunks are not progress; too many consecutive empty chunks fail with the\n * same stalled-read diagnostic used for pending reads.\n *\n * @param reader - Locked reader to read from.\n * @param timeoutMillis - Idle timeout in milliseconds for this read.\n * @param stalledMessage - Error message used when the read makes no progress.\n * @param signal - Optional abort signal to observe while reading.\n *\n * @returns The next stream read result.\n *\n * @internal\n */\nexport async function readStreamChunkWithTimeout(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n timeoutMillis: number,\n stalledMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n let emptyChunks = 0\n while (true) {\n const result = await readRawStreamChunkWithTimeout(\n reader,\n timeoutMillis,\n stalledMessage,\n signal,\n )\n if (result.done || result.value.byteLength > 0) return result\n emptyChunks += 1\n if (emptyChunks > MAX_CONSECUTIVE_EMPTY_READ_CHUNKS) {\n throw new Error(stalledMessage)\n }\n }\n}\n\nasync function readRawStreamChunkWithTimeout(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n timeoutMillis: number,\n stalledMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n throwIfSignalAborted(signal)\n\n let timeout: ReturnType<typeof setTimeout> | undefined\n let removeAbortListener: (() => void) | undefined\n const readPromise = reader.read()\n const timeoutPromise =\n timeoutMillis === Number.POSITIVE_INFINITY\n ? undefined\n : new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n reject(new Error(stalledMessage))\n }, timeoutMillis)\n })\n const abortPromise =\n signal === undefined\n ? undefined\n : new Promise<never>((_, reject) => {\n const onAbort = () => {\n reject(abortReason(signal))\n }\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n if (signal.aborted) onAbort()\n })\n\n try {\n if (timeoutPromise === undefined && abortPromise === undefined) return await readPromise\n const candidates = [readPromise]\n if (timeoutPromise !== undefined) candidates.push(timeoutPromise)\n if (abortPromise !== undefined) candidates.push(abortPromise)\n return await Promise.race(candidates)\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n removeAbortListener?.()\n void readPromise.catch(() => {})\n }\n}\n\n/**\n * Hashes a B2 response body as SHA-1 with idle timeout, abort, and size checks.\n *\n * @param body - Response body stream to hash.\n * @param signal - Optional abort signal to observe while reading.\n * @param options - Optional timeout and byte-count limits.\n *\n * @returns The computed SHA-1 and number of bytes read.\n *\n * @internal\n */\nexport async function hashReadableStreamSha1(\n body: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n options?: {\n readonly idleTimeoutMillis: number\n readonly maxBytes: number\n readonly expectedBytes: number\n },\n): Promise<{ readonly contentSha1: string; readonly bytesRead: number }> {\n const hash = new IncrementalSha1()\n const reader = body.getReader()\n const idleTimeoutMillis = options?.idleTimeoutMillis ?? normalizeSha1TimeoutMillis(undefined)\n const maxBytes = options?.maxBytes ?? Number.POSITIVE_INFINITY\n const expectedBytes = options?.expectedBytes\n let bytesRead = 0\n try {\n while (true) {\n const { done, value } = await readStreamChunkWithTimeout(\n reader,\n idleTimeoutMillis,\n `sha1 B2 read stalled for ${idleTimeoutMillis} ms`,\n signal,\n )\n if (done) break\n bytesRead += value.byteLength\n if (bytesRead > maxBytes) {\n throw new Error(`sha1 B2 read exceeded ${maxBytes} byte verification budget`)\n }\n await hash.update(value)\n }\n if (expectedBytes !== undefined && bytesRead !== expectedBytes) {\n throw new Error(`sha1 B2 read ended after ${bytesRead} bytes, expected ${expectedBytes}`)\n }\n return { contentSha1: await hash.digest(), bytesRead }\n } catch (err) {\n void reader.cancel(err).catch(() => {})\n throw err\n } finally {\n reader.releaseLock()\n }\n}\n\n/**\n * Applies an absolute verification deadline while forwarding parent aborts.\n *\n * @param signal - Optional parent abort signal.\n * @param timeoutMillis - Absolute deadline in milliseconds.\n * @param run - Operation to run with the derived deadline signal.\n *\n * @returns The operation result.\n *\n * @internal\n */\nexport async function withSha1VerificationDeadline<T>(\n signal: AbortSignal | undefined,\n timeoutMillis: number,\n run: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n const controller = new AbortController()\n const abortFromParent = () => controller.abort(signal?.reason)\n if (signal?.aborted) abortFromParent()\n signal?.addEventListener('abort', abortFromParent, { once: true })\n\n let timeout: ReturnType<typeof setTimeout> | undefined\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n const error = new Error(`sha1 B2 verification exceeded ${timeoutMillis} ms`)\n controller.abort(error)\n reject(error)\n }, timeoutMillis)\n })\n const runPromise = run(controller.signal)\n try {\n return await Promise.race([runPromise, timeoutPromise])\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n signal?.removeEventListener('abort', abortFromParent)\n void runPromise.catch(() => {})\n }\n}\n\n/**\n * Bounds B2 SHA-1 verification downloads to the selected object's size and optional ceiling.\n *\n * @param contentLength - Selected B2 object byte length.\n * @param ceiling - Optional lower verification budget.\n *\n * @returns The byte budget to enforce.\n *\n * @internal\n */\nexport function normalizeSha1VerificationMaxBytes(\n contentLength: number,\n ceiling: number | undefined,\n): number {\n const contentBudget = Math.max(0, Math.floor(contentLength))\n if (ceiling === undefined) return contentBudget\n if (!Number.isFinite(ceiling) || ceiling < 0) return contentBudget\n return Math.min(contentBudget, Math.floor(ceiling))\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"b2-sha1-reader.d.ts","sourceRoot":"","sources":["../../src/sync/b2-sha1-reader.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;GAaG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,EAC/C,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAe/C;AA2CD;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B,GACA,OAAO,CAAC;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgCvE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,4BAA4B,CAAC,CAAC,EAClD,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GACvC,OAAO,CAAC,CAAC,CAAC,CAsBZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,MAAM,CAKR"}
1
+ {"version":3,"file":"b2-sha1-reader.d.ts","sourceRoot":"","sources":["../../src/sync/b2-sha1-reader.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;GAaG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,EAC/C,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAe/C;AA8CD;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B,GACA,OAAO,CAAC;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgCvE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,4BAA4B,CAAC,CAAC,EAClD,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GACvC,OAAO,CAAC,CAAC,CAAC,CAsBZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,MAAM,CAKR"}
@@ -1 +1 @@
1
- {"version":3,"file":"b2-sha1-reader.d.ts","sourceRoot":"","sources":["../../src/sync/b2-sha1-reader.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;GAaG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,EAC/C,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAe/C;AA2CD;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B,GACA,OAAO,CAAC;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgCvE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,4BAA4B,CAAC,CAAC,EAClD,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GACvC,OAAO,CAAC,CAAC,CAAC,CAsBZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,MAAM,CAKR"}
1
+ {"version":3,"file":"b2-sha1-reader.d.ts","sourceRoot":"","sources":["../../src/sync/b2-sha1-reader.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;GAaG;AACH,wBAAsB,0BAA0B,CAC9C,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,EAC/C,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAe/C;AA8CD;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAChC,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE;IACR,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B,GACA,OAAO,CAAC;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgCvE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,4BAA4B,CAAC,CAAC,EAClD,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GACvC,OAAO,CAAC,CAAC,CAAC,CAsBZ;AAED;;;;;;;;;GASG;AACH,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,MAAM,CAKR"}
@@ -1,3 +1,4 @@
1
+ import { abortReason, throwIfSignalAborted } from "../util/abort.js";
1
2
  import { IncrementalSha1 } from "../streams/hash.js";
2
3
  import { normalizeSha1TimeoutMillis } from "./sha1-options.js";
3
4
  //#region src/sync/b2-sha1-reader.ts
@@ -26,7 +27,7 @@ async function readStreamChunkWithTimeout(reader, timeoutMillis, stalledMessage,
26
27
  }
27
28
  }
28
29
  async function readRawStreamChunkWithTimeout(reader, timeoutMillis, stalledMessage, signal) {
29
- signal?.throwIfAborted();
30
+ throwIfSignalAborted(signal);
30
31
  let timeout;
31
32
  let removeAbortListener;
32
33
  const readPromise = reader.read();
@@ -36,9 +37,12 @@ async function readRawStreamChunkWithTimeout(reader, timeoutMillis, stalledMessa
36
37
  }, timeoutMillis);
37
38
  });
38
39
  const abortPromise = signal === void 0 ? void 0 : new Promise((_, reject) => {
39
- const onAbort = () => reject(signal.reason ?? /* @__PURE__ */ new Error("aborted"));
40
+ const onAbort = () => {
41
+ reject(abortReason(signal));
42
+ };
40
43
  signal.addEventListener("abort", onAbort, { once: true });
41
44
  removeAbortListener = () => signal.removeEventListener("abort", onAbort);
45
+ if (signal.aborted) onAbort();
42
46
  });
43
47
  try {
44
48
  if (timeoutPromise === void 0 && abortPromise === void 0) return await readPromise;
@@ -1 +1 @@
1
- {"version":3,"file":"b2-sha1-reader.js","names":[],"sources":["../../src/sync/b2-sha1-reader.ts"],"sourcesContent":["import { IncrementalSha1 } from '../streams/hash.ts'\nimport { normalizeSha1TimeoutMillis } from './sha1-options.ts'\n\nconst MAX_CONSECUTIVE_EMPTY_READ_CHUNKS = 1024\n\n/**\n * Reads one non-empty stream chunk with an idle timeout and optional abort signal.\n * Empty chunks are not progress; too many consecutive empty chunks fail with the\n * same stalled-read diagnostic used for pending reads.\n *\n * @param reader - Locked reader to read from.\n * @param timeoutMillis - Idle timeout in milliseconds for this read.\n * @param stalledMessage - Error message used when the read makes no progress.\n * @param signal - Optional abort signal to observe while reading.\n *\n * @returns The next stream read result.\n *\n * @internal\n */\nexport async function readStreamChunkWithTimeout(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n timeoutMillis: number,\n stalledMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n let emptyChunks = 0\n while (true) {\n const result = await readRawStreamChunkWithTimeout(\n reader,\n timeoutMillis,\n stalledMessage,\n signal,\n )\n if (result.done || result.value.byteLength > 0) return result\n emptyChunks += 1\n if (emptyChunks > MAX_CONSECUTIVE_EMPTY_READ_CHUNKS) {\n throw new Error(stalledMessage)\n }\n }\n}\n\nasync function readRawStreamChunkWithTimeout(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n timeoutMillis: number,\n stalledMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n signal?.throwIfAborted()\n\n let timeout: ReturnType<typeof setTimeout> | undefined\n let removeAbortListener: (() => void) | undefined\n const readPromise = reader.read()\n const timeoutPromise =\n timeoutMillis === Number.POSITIVE_INFINITY\n ? undefined\n : new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n reject(new Error(stalledMessage))\n }, timeoutMillis)\n })\n const abortPromise =\n signal === undefined\n ? undefined\n : new Promise<never>((_, reject) => {\n const onAbort = () => reject(signal.reason ?? new Error('aborted'))\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n if (timeoutPromise === undefined && abortPromise === undefined) return await readPromise\n const candidates = [readPromise]\n if (timeoutPromise !== undefined) candidates.push(timeoutPromise)\n if (abortPromise !== undefined) candidates.push(abortPromise)\n return await Promise.race(candidates)\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n removeAbortListener?.()\n void readPromise.catch(() => {})\n }\n}\n\n/**\n * Hashes a B2 response body as SHA-1 with idle timeout, abort, and size checks.\n *\n * @param body - Response body stream to hash.\n * @param signal - Optional abort signal to observe while reading.\n * @param options - Optional timeout and byte-count limits.\n *\n * @returns The computed SHA-1 and number of bytes read.\n *\n * @internal\n */\nexport async function hashReadableStreamSha1(\n body: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n options?: {\n readonly idleTimeoutMillis: number\n readonly maxBytes: number\n readonly expectedBytes: number\n },\n): Promise<{ readonly contentSha1: string; readonly bytesRead: number }> {\n const hash = new IncrementalSha1()\n const reader = body.getReader()\n const idleTimeoutMillis = options?.idleTimeoutMillis ?? normalizeSha1TimeoutMillis(undefined)\n const maxBytes = options?.maxBytes ?? Number.POSITIVE_INFINITY\n const expectedBytes = options?.expectedBytes\n let bytesRead = 0\n try {\n while (true) {\n const { done, value } = await readStreamChunkWithTimeout(\n reader,\n idleTimeoutMillis,\n `sha1 B2 read stalled for ${idleTimeoutMillis} ms`,\n signal,\n )\n if (done) break\n bytesRead += value.byteLength\n if (bytesRead > maxBytes) {\n throw new Error(`sha1 B2 read exceeded ${maxBytes} byte verification budget`)\n }\n await hash.update(value)\n }\n if (expectedBytes !== undefined && bytesRead !== expectedBytes) {\n throw new Error(`sha1 B2 read ended after ${bytesRead} bytes, expected ${expectedBytes}`)\n }\n return { contentSha1: await hash.digest(), bytesRead }\n } catch (err) {\n void reader.cancel(err).catch(() => {})\n throw err\n } finally {\n reader.releaseLock()\n }\n}\n\n/**\n * Applies an absolute verification deadline while forwarding parent aborts.\n *\n * @param signal - Optional parent abort signal.\n * @param timeoutMillis - Absolute deadline in milliseconds.\n * @param run - Operation to run with the derived deadline signal.\n *\n * @returns The operation result.\n *\n * @internal\n */\nexport async function withSha1VerificationDeadline<T>(\n signal: AbortSignal | undefined,\n timeoutMillis: number,\n run: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n const controller = new AbortController()\n const abortFromParent = () => controller.abort(signal?.reason)\n if (signal?.aborted) abortFromParent()\n signal?.addEventListener('abort', abortFromParent, { once: true })\n\n let timeout: ReturnType<typeof setTimeout> | undefined\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n const error = new Error(`sha1 B2 verification exceeded ${timeoutMillis} ms`)\n controller.abort(error)\n reject(error)\n }, timeoutMillis)\n })\n const runPromise = run(controller.signal)\n try {\n return await Promise.race([runPromise, timeoutPromise])\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n signal?.removeEventListener('abort', abortFromParent)\n void runPromise.catch(() => {})\n }\n}\n\n/**\n * Bounds B2 SHA-1 verification downloads to the selected object's size and optional ceiling.\n *\n * @param contentLength - Selected B2 object byte length.\n * @param ceiling - Optional lower verification budget.\n *\n * @returns The byte budget to enforce.\n *\n * @internal\n */\nexport function normalizeSha1VerificationMaxBytes(\n contentLength: number,\n ceiling: number | undefined,\n): number {\n const contentBudget = Math.max(0, Math.floor(contentLength))\n if (ceiling === undefined) return contentBudget\n if (!Number.isFinite(ceiling) || ceiling < 0) return contentBudget\n return Math.min(contentBudget, Math.floor(ceiling))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"b2-sha1-reader.js","names":[],"sources":["../../src/sync/b2-sha1-reader.ts"],"sourcesContent":["import { IncrementalSha1 } from '../streams/hash.ts'\nimport { abortReason, throwIfSignalAborted } from '../util/abort.ts'\nimport { normalizeSha1TimeoutMillis } from './sha1-options.ts'\n\nconst MAX_CONSECUTIVE_EMPTY_READ_CHUNKS = 1024\n\n/**\n * Reads one non-empty stream chunk with an idle timeout and optional abort signal.\n * Empty chunks are not progress; too many consecutive empty chunks fail with the\n * same stalled-read diagnostic used for pending reads.\n *\n * @param reader - Locked reader to read from.\n * @param timeoutMillis - Idle timeout in milliseconds for this read.\n * @param stalledMessage - Error message used when the read makes no progress.\n * @param signal - Optional abort signal to observe while reading.\n *\n * @returns The next stream read result.\n *\n * @internal\n */\nexport async function readStreamChunkWithTimeout(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n timeoutMillis: number,\n stalledMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n let emptyChunks = 0\n while (true) {\n const result = await readRawStreamChunkWithTimeout(\n reader,\n timeoutMillis,\n stalledMessage,\n signal,\n )\n if (result.done || result.value.byteLength > 0) return result\n emptyChunks += 1\n if (emptyChunks > MAX_CONSECUTIVE_EMPTY_READ_CHUNKS) {\n throw new Error(stalledMessage)\n }\n }\n}\n\nasync function readRawStreamChunkWithTimeout(\n reader: ReadableStreamDefaultReader<Uint8Array>,\n timeoutMillis: number,\n stalledMessage: string,\n signal?: AbortSignal,\n): Promise<ReadableStreamReadResult<Uint8Array>> {\n throwIfSignalAborted(signal)\n\n let timeout: ReturnType<typeof setTimeout> | undefined\n let removeAbortListener: (() => void) | undefined\n const readPromise = reader.read()\n const timeoutPromise =\n timeoutMillis === Number.POSITIVE_INFINITY\n ? undefined\n : new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n reject(new Error(stalledMessage))\n }, timeoutMillis)\n })\n const abortPromise =\n signal === undefined\n ? undefined\n : new Promise<never>((_, reject) => {\n const onAbort = () => {\n reject(abortReason(signal))\n }\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n if (signal.aborted) onAbort()\n })\n\n try {\n if (timeoutPromise === undefined && abortPromise === undefined) return await readPromise\n const candidates = [readPromise]\n if (timeoutPromise !== undefined) candidates.push(timeoutPromise)\n if (abortPromise !== undefined) candidates.push(abortPromise)\n return await Promise.race(candidates)\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n removeAbortListener?.()\n void readPromise.catch(() => {})\n }\n}\n\n/**\n * Hashes a B2 response body as SHA-1 with idle timeout, abort, and size checks.\n *\n * @param body - Response body stream to hash.\n * @param signal - Optional abort signal to observe while reading.\n * @param options - Optional timeout and byte-count limits.\n *\n * @returns The computed SHA-1 and number of bytes read.\n *\n * @internal\n */\nexport async function hashReadableStreamSha1(\n body: ReadableStream<Uint8Array>,\n signal?: AbortSignal,\n options?: {\n readonly idleTimeoutMillis: number\n readonly maxBytes: number\n readonly expectedBytes: number\n },\n): Promise<{ readonly contentSha1: string; readonly bytesRead: number }> {\n const hash = new IncrementalSha1()\n const reader = body.getReader()\n const idleTimeoutMillis = options?.idleTimeoutMillis ?? normalizeSha1TimeoutMillis(undefined)\n const maxBytes = options?.maxBytes ?? Number.POSITIVE_INFINITY\n const expectedBytes = options?.expectedBytes\n let bytesRead = 0\n try {\n while (true) {\n const { done, value } = await readStreamChunkWithTimeout(\n reader,\n idleTimeoutMillis,\n `sha1 B2 read stalled for ${idleTimeoutMillis} ms`,\n signal,\n )\n if (done) break\n bytesRead += value.byteLength\n if (bytesRead > maxBytes) {\n throw new Error(`sha1 B2 read exceeded ${maxBytes} byte verification budget`)\n }\n await hash.update(value)\n }\n if (expectedBytes !== undefined && bytesRead !== expectedBytes) {\n throw new Error(`sha1 B2 read ended after ${bytesRead} bytes, expected ${expectedBytes}`)\n }\n return { contentSha1: await hash.digest(), bytesRead }\n } catch (err) {\n void reader.cancel(err).catch(() => {})\n throw err\n } finally {\n reader.releaseLock()\n }\n}\n\n/**\n * Applies an absolute verification deadline while forwarding parent aborts.\n *\n * @param signal - Optional parent abort signal.\n * @param timeoutMillis - Absolute deadline in milliseconds.\n * @param run - Operation to run with the derived deadline signal.\n *\n * @returns The operation result.\n *\n * @internal\n */\nexport async function withSha1VerificationDeadline<T>(\n signal: AbortSignal | undefined,\n timeoutMillis: number,\n run: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n const controller = new AbortController()\n const abortFromParent = () => controller.abort(signal?.reason)\n if (signal?.aborted) abortFromParent()\n signal?.addEventListener('abort', abortFromParent, { once: true })\n\n let timeout: ReturnType<typeof setTimeout> | undefined\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n const error = new Error(`sha1 B2 verification exceeded ${timeoutMillis} ms`)\n controller.abort(error)\n reject(error)\n }, timeoutMillis)\n })\n const runPromise = run(controller.signal)\n try {\n return await Promise.race([runPromise, timeoutPromise])\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n signal?.removeEventListener('abort', abortFromParent)\n void runPromise.catch(() => {})\n }\n}\n\n/**\n * Bounds B2 SHA-1 verification downloads to the selected object's size and optional ceiling.\n *\n * @param contentLength - Selected B2 object byte length.\n * @param ceiling - Optional lower verification budget.\n *\n * @returns The byte budget to enforce.\n *\n * @internal\n */\nexport function normalizeSha1VerificationMaxBytes(\n contentLength: number,\n ceiling: number | undefined,\n): number {\n const contentBudget = Math.max(0, Math.floor(contentLength))\n if (ceiling === undefined) return contentBudget\n if (!Number.isFinite(ceiling) || ceiling < 0) return contentBudget\n return Math.min(contentBudget, Math.floor(ceiling))\n}\n"],"mappings":"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"}