@backblaze-labs/b2-sdk 0.1.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 (512) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/LICENSE +21 -0
  3. package/README.md +664 -0
  4. package/dist/auth/account-info.d.cts +51 -0
  5. package/dist/auth/account-info.d.cts.map +1 -0
  6. package/dist/auth/account-info.d.ts +51 -0
  7. package/dist/auth/account-info.d.ts.map +1 -0
  8. package/dist/auth/file.cjs +210 -0
  9. package/dist/auth/file.cjs.map +1 -0
  10. package/dist/auth/file.d.cts +157 -0
  11. package/dist/auth/file.d.cts.map +1 -0
  12. package/dist/auth/file.d.ts +157 -0
  13. package/dist/auth/file.d.ts.map +1 -0
  14. package/dist/auth/file.js +210 -0
  15. package/dist/auth/file.js.map +1 -0
  16. package/dist/auth/in-memory.cjs +184 -0
  17. package/dist/auth/in-memory.cjs.map +1 -0
  18. package/dist/auth/in-memory.d.cts +147 -0
  19. package/dist/auth/in-memory.d.cts.map +1 -0
  20. package/dist/auth/in-memory.d.ts +147 -0
  21. package/dist/auth/in-memory.d.ts.map +1 -0
  22. package/dist/auth/in-memory.js +184 -0
  23. package/dist/auth/in-memory.js.map +1 -0
  24. package/dist/auth/index.cjs +10 -0
  25. package/dist/auth/index.cjs.map +1 -0
  26. package/dist/auth/index.d.cts +6 -0
  27. package/dist/auth/index.d.cts.map +1 -0
  28. package/dist/auth/index.d.ts +6 -0
  29. package/dist/auth/index.d.ts.map +1 -0
  30. package/dist/auth/index.js +10 -0
  31. package/dist/auth/index.js.map +1 -0
  32. package/dist/auth/realms.cjs +12 -0
  33. package/dist/auth/realms.cjs.map +1 -0
  34. package/dist/auth/realms.d.cts +12 -0
  35. package/dist/auth/realms.d.cts.map +1 -0
  36. package/dist/auth/realms.d.ts +12 -0
  37. package/dist/auth/realms.d.ts.map +1 -0
  38. package/dist/auth/realms.js +12 -0
  39. package/dist/auth/realms.js.map +1 -0
  40. package/dist/auth/upload-url-pool.cjs +52 -0
  41. package/dist/auth/upload-url-pool.cjs.map +1 -0
  42. package/dist/auth/upload-url-pool.d.cts +35 -0
  43. package/dist/auth/upload-url-pool.d.cts.map +1 -0
  44. package/dist/auth/upload-url-pool.d.ts +35 -0
  45. package/dist/auth/upload-url-pool.d.ts.map +1 -0
  46. package/dist/auth/upload-url-pool.js +52 -0
  47. package/dist/auth/upload-url-pool.js.map +1 -0
  48. package/dist/bucket.cjs +789 -0
  49. package/dist/bucket.cjs.map +1 -0
  50. package/dist/bucket.d.cts +659 -0
  51. package/dist/bucket.d.cts.map +1 -0
  52. package/dist/bucket.d.ts +659 -0
  53. package/dist/bucket.d.ts.map +1 -0
  54. package/dist/bucket.js +789 -0
  55. package/dist/bucket.js.map +1 -0
  56. package/dist/client.cjs +230 -0
  57. package/dist/client.cjs.map +1 -0
  58. package/dist/client.d.cts +222 -0
  59. package/dist/client.d.cts.map +1 -0
  60. package/dist/client.d.ts +222 -0
  61. package/dist/client.d.ts.map +1 -0
  62. package/dist/client.js +230 -0
  63. package/dist/client.js.map +1 -0
  64. package/dist/copy/large.cjs +74 -0
  65. package/dist/copy/large.cjs.map +1 -0
  66. package/dist/copy/large.d.cts +53 -0
  67. package/dist/copy/large.d.cts.map +1 -0
  68. package/dist/copy/large.d.ts +53 -0
  69. package/dist/copy/large.d.ts.map +1 -0
  70. package/dist/copy/large.js +74 -0
  71. package/dist/copy/large.js.map +1 -0
  72. package/dist/download/parallel.cjs +122 -0
  73. package/dist/download/parallel.cjs.map +1 -0
  74. package/dist/download/parallel.d.cts +42 -0
  75. package/dist/download/parallel.d.cts.map +1 -0
  76. package/dist/download/parallel.d.ts +42 -0
  77. package/dist/download/parallel.d.ts.map +1 -0
  78. package/dist/download/parallel.js +122 -0
  79. package/dist/download/parallel.js.map +1 -0
  80. package/dist/download/single.cjs +117 -0
  81. package/dist/download/single.cjs.map +1 -0
  82. package/dist/download/single.d.cts +152 -0
  83. package/dist/download/single.d.cts.map +1 -0
  84. package/dist/download/single.d.ts +152 -0
  85. package/dist/download/single.d.ts.map +1 -0
  86. package/dist/download/single.js +117 -0
  87. package/dist/download/single.js.map +1 -0
  88. package/dist/errors/index.cjs +268 -0
  89. package/dist/errors/index.cjs.map +1 -0
  90. package/dist/errors/index.d.cts +264 -0
  91. package/dist/errors/index.d.cts.map +1 -0
  92. package/dist/errors/index.d.ts +264 -0
  93. package/dist/errors/index.d.ts.map +1 -0
  94. package/dist/errors/index.js +268 -0
  95. package/dist/errors/index.js.map +1 -0
  96. package/dist/http/retry.cjs +36 -0
  97. package/dist/http/retry.cjs.map +1 -0
  98. package/dist/http/retry.d.cts +34 -0
  99. package/dist/http/retry.d.cts.map +1 -0
  100. package/dist/http/retry.d.ts +34 -0
  101. package/dist/http/retry.d.ts.map +1 -0
  102. package/dist/http/retry.js +36 -0
  103. package/dist/http/retry.js.map +1 -0
  104. package/dist/http/transport.cjs +143 -0
  105. package/dist/http/transport.cjs.map +1 -0
  106. package/dist/http/transport.d.cts +122 -0
  107. package/dist/http/transport.d.cts.map +1 -0
  108. package/dist/http/transport.d.ts +122 -0
  109. package/dist/http/transport.d.ts.map +1 -0
  110. package/dist/http/transport.js +143 -0
  111. package/dist/http/transport.js.map +1 -0
  112. package/dist/http/url-guard.cjs +97 -0
  113. package/dist/http/url-guard.cjs.map +1 -0
  114. package/dist/http/url-guard.d.cts +88 -0
  115. package/dist/http/url-guard.d.cts.map +1 -0
  116. package/dist/http/url-guard.d.ts +88 -0
  117. package/dist/http/url-guard.d.ts.map +1 -0
  118. package/dist/http/url-guard.js +97 -0
  119. package/dist/http/url-guard.js.map +1 -0
  120. package/dist/http/user-agent.cjs +51 -0
  121. package/dist/http/user-agent.cjs.map +1 -0
  122. package/dist/http/user-agent.d.cts +28 -0
  123. package/dist/http/user-agent.d.cts.map +1 -0
  124. package/dist/http/user-agent.d.ts +28 -0
  125. package/dist/http/user-agent.d.ts.map +1 -0
  126. package/dist/http/user-agent.js +51 -0
  127. package/dist/http/user-agent.js.map +1 -0
  128. package/dist/index.cjs +78 -0
  129. package/dist/index.cjs.map +1 -0
  130. package/dist/index.d.cts +39 -0
  131. package/dist/index.d.cts.map +1 -0
  132. package/dist/index.d.ts +39 -0
  133. package/dist/index.d.ts.map +1 -0
  134. package/dist/index.js +78 -0
  135. package/dist/index.js.map +1 -0
  136. package/dist/notifications/index.cjs +7 -0
  137. package/dist/notifications/index.cjs.map +1 -0
  138. package/dist/notifications/index.d.cts +3 -0
  139. package/dist/notifications/index.d.cts.map +1 -0
  140. package/dist/notifications/index.d.ts +3 -0
  141. package/dist/notifications/index.d.ts.map +1 -0
  142. package/dist/notifications/index.js +7 -0
  143. package/dist/notifications/index.js.map +1 -0
  144. package/dist/notifications/webhook.cjs +106 -0
  145. package/dist/notifications/webhook.cjs.map +1 -0
  146. package/dist/notifications/webhook.d.cts +146 -0
  147. package/dist/notifications/webhook.d.cts.map +1 -0
  148. package/dist/notifications/webhook.d.ts +146 -0
  149. package/dist/notifications/webhook.d.ts.map +1 -0
  150. package/dist/notifications/webhook.js +106 -0
  151. package/dist/notifications/webhook.js.map +1 -0
  152. package/dist/object.cjs +212 -0
  153. package/dist/object.cjs.map +1 -0
  154. package/dist/object.d.cts +263 -0
  155. package/dist/object.d.cts.map +1 -0
  156. package/dist/object.d.ts +263 -0
  157. package/dist/object.d.ts.map +1 -0
  158. package/dist/object.js +212 -0
  159. package/dist/object.js.map +1 -0
  160. package/dist/package.json.cjs +9 -0
  161. package/dist/package.json.cjs.map +1 -0
  162. package/dist/package.json.js +9 -0
  163. package/dist/package.json.js.map +1 -0
  164. package/dist/raw/encoding.cjs +47 -0
  165. package/dist/raw/encoding.cjs.map +1 -0
  166. package/dist/raw/encoding.d.cts +46 -0
  167. package/dist/raw/encoding.d.cts.map +1 -0
  168. package/dist/raw/encoding.d.ts +46 -0
  169. package/dist/raw/encoding.d.ts.map +1 -0
  170. package/dist/raw/encoding.js +47 -0
  171. package/dist/raw/encoding.js.map +1 -0
  172. package/dist/raw/index.cjs +600 -0
  173. package/dist/raw/index.cjs.map +1 -0
  174. package/dist/raw/index.d.cts +381 -0
  175. package/dist/raw/index.d.cts.map +1 -0
  176. package/dist/raw/index.d.ts +381 -0
  177. package/dist/raw/index.d.ts.map +1 -0
  178. package/dist/raw/index.js +601 -0
  179. package/dist/raw/index.js.map +1 -0
  180. package/dist/s3/index.cjs +23 -0
  181. package/dist/s3/index.cjs.map +1 -0
  182. package/dist/s3/index.d.cts +74 -0
  183. package/dist/s3/index.d.cts.map +1 -0
  184. package/dist/s3/index.d.ts +74 -0
  185. package/dist/s3/index.d.ts.map +1 -0
  186. package/dist/s3/index.js +23 -0
  187. package/dist/s3/index.js.map +1 -0
  188. package/dist/simulator/capabilities.cjs +53 -0
  189. package/dist/simulator/capabilities.cjs.map +1 -0
  190. package/dist/simulator/capabilities.d.cts +15 -0
  191. package/dist/simulator/capabilities.d.cts.map +1 -0
  192. package/dist/simulator/capabilities.d.ts +15 -0
  193. package/dist/simulator/capabilities.d.ts.map +1 -0
  194. package/dist/simulator/capabilities.js +53 -0
  195. package/dist/simulator/capabilities.js.map +1 -0
  196. package/dist/simulator/index.cjs +1559 -0
  197. package/dist/simulator/index.cjs.map +1 -0
  198. package/dist/simulator/index.d.cts +495 -0
  199. package/dist/simulator/index.d.cts.map +1 -0
  200. package/dist/simulator/index.d.ts +495 -0
  201. package/dist/simulator/index.d.ts.map +1 -0
  202. package/dist/simulator/index.js +1560 -0
  203. package/dist/simulator/index.js.map +1 -0
  204. package/dist/simulator/validation.cjs +174 -0
  205. package/dist/simulator/validation.cjs.map +1 -0
  206. package/dist/simulator/validation.d.cts +104 -0
  207. package/dist/simulator/validation.d.cts.map +1 -0
  208. package/dist/simulator/validation.d.ts +104 -0
  209. package/dist/simulator/validation.d.ts.map +1 -0
  210. package/dist/simulator/validation.js +174 -0
  211. package/dist/simulator/validation.js.map +1 -0
  212. package/dist/streams/collect.cjs +26 -0
  213. package/dist/streams/collect.cjs.map +1 -0
  214. package/dist/streams/collect.d.cts +18 -0
  215. package/dist/streams/collect.d.cts.map +1 -0
  216. package/dist/streams/collect.d.ts +18 -0
  217. package/dist/streams/collect.d.ts.map +1 -0
  218. package/dist/streams/collect.js +26 -0
  219. package/dist/streams/collect.js.map +1 -0
  220. package/dist/streams/hash.cjs +123 -0
  221. package/dist/streams/hash.cjs.map +1 -0
  222. package/dist/streams/hash.d.cts +42 -0
  223. package/dist/streams/hash.d.cts.map +1 -0
  224. package/dist/streams/hash.d.ts +42 -0
  225. package/dist/streams/hash.d.ts.map +1 -0
  226. package/dist/streams/hash.js +101 -0
  227. package/dist/streams/hash.js.map +1 -0
  228. package/dist/streams/index.cjs +13 -0
  229. package/dist/streams/index.cjs.map +1 -0
  230. package/dist/streams/index.d.cts +7 -0
  231. package/dist/streams/index.d.cts.map +1 -0
  232. package/dist/streams/index.d.ts +7 -0
  233. package/dist/streams/index.d.ts.map +1 -0
  234. package/dist/streams/index.js +13 -0
  235. package/dist/streams/index.js.map +1 -0
  236. package/dist/streams/progress.cjs +47 -0
  237. package/dist/streams/progress.cjs.map +1 -0
  238. package/dist/streams/progress.d.cts +53 -0
  239. package/dist/streams/progress.d.cts.map +1 -0
  240. package/dist/streams/progress.d.ts +53 -0
  241. package/dist/streams/progress.d.ts.map +1 -0
  242. package/dist/streams/progress.js +47 -0
  243. package/dist/streams/progress.js.map +1 -0
  244. package/dist/streams/source.cjs +155 -0
  245. package/dist/streams/source.cjs.map +1 -0
  246. package/dist/streams/source.d.cts +140 -0
  247. package/dist/streams/source.d.cts.map +1 -0
  248. package/dist/streams/source.d.ts +140 -0
  249. package/dist/streams/source.d.ts.map +1 -0
  250. package/dist/streams/source.js +155 -0
  251. package/dist/streams/source.js.map +1 -0
  252. package/dist/sync/actions/index.cjs +191 -0
  253. package/dist/sync/actions/index.cjs.map +1 -0
  254. package/dist/sync/actions/index.d.cts +167 -0
  255. package/dist/sync/actions/index.d.cts.map +1 -0
  256. package/dist/sync/actions/index.d.ts +167 -0
  257. package/dist/sync/actions/index.d.ts.map +1 -0
  258. package/dist/sync/actions/index.js +191 -0
  259. package/dist/sync/actions/index.js.map +1 -0
  260. package/dist/sync/index.cjs +23 -0
  261. package/dist/sync/index.cjs.map +1 -0
  262. package/dist/sync/index.d.cts +21 -0
  263. package/dist/sync/index.d.cts.map +1 -0
  264. package/dist/sync/index.d.ts +21 -0
  265. package/dist/sync/index.d.ts.map +1 -0
  266. package/dist/sync/index.js +23 -0
  267. package/dist/sync/index.js.map +1 -0
  268. package/dist/sync/pairing.cjs +31 -0
  269. package/dist/sync/pairing.cjs.map +1 -0
  270. package/dist/sync/pairing.d.cts +13 -0
  271. package/dist/sync/pairing.d.cts.map +1 -0
  272. package/dist/sync/pairing.d.ts +13 -0
  273. package/dist/sync/pairing.d.ts.map +1 -0
  274. package/dist/sync/pairing.js +31 -0
  275. package/dist/sync/pairing.js.map +1 -0
  276. package/dist/sync/policies/compare.cjs +14 -0
  277. package/dist/sync/policies/compare.cjs.map +1 -0
  278. package/dist/sync/policies/compare.d.cts +13 -0
  279. package/dist/sync/policies/compare.d.cts.map +1 -0
  280. package/dist/sync/policies/compare.d.ts +13 -0
  281. package/dist/sync/policies/compare.d.ts.map +1 -0
  282. package/dist/sync/policies/compare.js +14 -0
  283. package/dist/sync/policies/compare.js.map +1 -0
  284. package/dist/sync/policies/index.cjs +74 -0
  285. package/dist/sync/policies/index.cjs.map +1 -0
  286. package/dist/sync/policies/index.d.cts +42 -0
  287. package/dist/sync/policies/index.d.cts.map +1 -0
  288. package/dist/sync/policies/index.d.ts +42 -0
  289. package/dist/sync/policies/index.d.ts.map +1 -0
  290. package/dist/sync/policies/index.js +74 -0
  291. package/dist/sync/policies/index.js.map +1 -0
  292. package/dist/sync/scanners/b2.cjs +57 -0
  293. package/dist/sync/scanners/b2.cjs.map +1 -0
  294. package/dist/sync/scanners/b2.d.cts +20 -0
  295. package/dist/sync/scanners/b2.d.cts.map +1 -0
  296. package/dist/sync/scanners/b2.d.ts +20 -0
  297. package/dist/sync/scanners/b2.d.ts.map +1 -0
  298. package/dist/sync/scanners/b2.js +57 -0
  299. package/dist/sync/scanners/b2.js.map +1 -0
  300. package/dist/sync/scanners/local.cjs +58 -0
  301. package/dist/sync/scanners/local.cjs.map +1 -0
  302. package/dist/sync/scanners/local.d.cts +24 -0
  303. package/dist/sync/scanners/local.d.cts.map +1 -0
  304. package/dist/sync/scanners/local.d.ts +24 -0
  305. package/dist/sync/scanners/local.d.ts.map +1 -0
  306. package/dist/sync/scanners/local.js +58 -0
  307. package/dist/sync/scanners/local.js.map +1 -0
  308. package/dist/sync/synchronizer.cjs +203 -0
  309. package/dist/sync/synchronizer.cjs.map +1 -0
  310. package/dist/sync/synchronizer.d.cts +52 -0
  311. package/dist/sync/synchronizer.d.cts.map +1 -0
  312. package/dist/sync/synchronizer.d.ts +52 -0
  313. package/dist/sync/synchronizer.d.ts.map +1 -0
  314. package/dist/sync/synchronizer.js +181 -0
  315. package/dist/sync/synchronizer.js.map +1 -0
  316. package/dist/sync/types.d.cts +121 -0
  317. package/dist/sync/types.d.cts.map +1 -0
  318. package/dist/sync/types.d.ts +121 -0
  319. package/dist/sync/types.d.ts.map +1 -0
  320. package/dist/types/auth.cjs +58 -0
  321. package/dist/types/auth.cjs.map +1 -0
  322. package/dist/types/auth.d.cts +150 -0
  323. package/dist/types/auth.d.cts.map +1 -0
  324. package/dist/types/auth.d.ts +150 -0
  325. package/dist/types/auth.d.ts.map +1 -0
  326. package/dist/types/auth.js +58 -0
  327. package/dist/types/auth.js.map +1 -0
  328. package/dist/types/bucket.cjs +44 -0
  329. package/dist/types/bucket.cjs.map +1 -0
  330. package/dist/types/bucket.d.cts +245 -0
  331. package/dist/types/bucket.d.cts.map +1 -0
  332. package/dist/types/bucket.d.ts +245 -0
  333. package/dist/types/bucket.d.ts.map +1 -0
  334. package/dist/types/bucket.js +44 -0
  335. package/dist/types/bucket.js.map +1 -0
  336. package/dist/types/download.d.cts +110 -0
  337. package/dist/types/download.d.cts.map +1 -0
  338. package/dist/types/download.d.ts +110 -0
  339. package/dist/types/download.d.ts.map +1 -0
  340. package/dist/types/encryption.cjs +343 -0
  341. package/dist/types/encryption.cjs.map +1 -0
  342. package/dist/types/encryption.d.cts +132 -0
  343. package/dist/types/encryption.d.cts.map +1 -0
  344. package/dist/types/encryption.d.ts +132 -0
  345. package/dist/types/encryption.d.ts.map +1 -0
  346. package/dist/types/encryption.js +321 -0
  347. package/dist/types/encryption.js.map +1 -0
  348. package/dist/types/errors.d.cts +16 -0
  349. package/dist/types/errors.d.cts.map +1 -0
  350. package/dist/types/errors.d.ts +16 -0
  351. package/dist/types/errors.d.ts.map +1 -0
  352. package/dist/types/file.cjs +23 -0
  353. package/dist/types/file.cjs.map +1 -0
  354. package/dist/types/file.d.cts +220 -0
  355. package/dist/types/file.d.cts.map +1 -0
  356. package/dist/types/file.d.ts +220 -0
  357. package/dist/types/file.d.ts.map +1 -0
  358. package/dist/types/file.js +23 -0
  359. package/dist/types/file.js.map +1 -0
  360. package/dist/types/ids.cjs +27 -0
  361. package/dist/types/ids.cjs.map +1 -0
  362. package/dist/types/ids.d.cts +84 -0
  363. package/dist/types/ids.d.cts.map +1 -0
  364. package/dist/types/ids.d.ts +84 -0
  365. package/dist/types/ids.d.ts.map +1 -0
  366. package/dist/types/ids.js +27 -0
  367. package/dist/types/ids.js.map +1 -0
  368. package/dist/types/index.d.cts +25 -0
  369. package/dist/types/index.d.cts.map +1 -0
  370. package/dist/types/index.d.ts +25 -0
  371. package/dist/types/index.d.ts.map +1 -0
  372. package/dist/types/key.d.cts +84 -0
  373. package/dist/types/key.d.cts.map +1 -0
  374. package/dist/types/key.d.ts +84 -0
  375. package/dist/types/key.d.ts.map +1 -0
  376. package/dist/types/lock.cjs +17 -0
  377. package/dist/types/lock.cjs.map +1 -0
  378. package/dist/types/lock.d.cts +92 -0
  379. package/dist/types/lock.d.cts.map +1 -0
  380. package/dist/types/lock.d.ts +92 -0
  381. package/dist/types/lock.d.ts.map +1 -0
  382. package/dist/types/lock.js +17 -0
  383. package/dist/types/lock.js.map +1 -0
  384. package/dist/types/notifications.cjs +24 -0
  385. package/dist/types/notifications.cjs.map +1 -0
  386. package/dist/types/notifications.d.cts +97 -0
  387. package/dist/types/notifications.d.cts.map +1 -0
  388. package/dist/types/notifications.d.ts +97 -0
  389. package/dist/types/notifications.d.ts.map +1 -0
  390. package/dist/types/notifications.js +24 -0
  391. package/dist/types/notifications.js.map +1 -0
  392. package/dist/types/replication.d.cts +42 -0
  393. package/dist/types/replication.d.cts.map +1 -0
  394. package/dist/types/replication.d.ts +42 -0
  395. package/dist/types/replication.d.ts.map +1 -0
  396. package/dist/types/upload.d.cts +219 -0
  397. package/dist/types/upload.d.cts.map +1 -0
  398. package/dist/types/upload.d.ts +219 -0
  399. package/dist/types/upload.d.ts.map +1 -0
  400. package/dist/upload/cancel.cjs +10 -0
  401. package/dist/upload/cancel.cjs.map +1 -0
  402. package/dist/upload/cancel.d.cts +23 -0
  403. package/dist/upload/cancel.d.cts.map +1 -0
  404. package/dist/upload/cancel.d.ts +23 -0
  405. package/dist/upload/cancel.d.ts.map +1 -0
  406. package/dist/upload/cancel.js +10 -0
  407. package/dist/upload/cancel.js.map +1 -0
  408. package/dist/upload/concurrency.cjs +54 -0
  409. package/dist/upload/concurrency.cjs.map +1 -0
  410. package/dist/upload/concurrency.d.cts +46 -0
  411. package/dist/upload/concurrency.d.cts.map +1 -0
  412. package/dist/upload/concurrency.d.ts +46 -0
  413. package/dist/upload/concurrency.d.ts.map +1 -0
  414. package/dist/upload/concurrency.js +54 -0
  415. package/dist/upload/concurrency.js.map +1 -0
  416. package/dist/upload/large.cjs +222 -0
  417. package/dist/upload/large.cjs.map +1 -0
  418. package/dist/upload/large.d.cts +71 -0
  419. package/dist/upload/large.d.cts.map +1 -0
  420. package/dist/upload/large.d.ts +71 -0
  421. package/dist/upload/large.d.ts.map +1 -0
  422. package/dist/upload/large.js +222 -0
  423. package/dist/upload/large.js.map +1 -0
  424. package/dist/upload/resume.cjs +34 -0
  425. package/dist/upload/resume.cjs.map +1 -0
  426. package/dist/upload/resume.d.cts +33 -0
  427. package/dist/upload/resume.d.cts.map +1 -0
  428. package/dist/upload/resume.d.ts +33 -0
  429. package/dist/upload/resume.d.ts.map +1 -0
  430. package/dist/upload/resume.js +34 -0
  431. package/dist/upload/resume.js.map +1 -0
  432. package/dist/upload/single.cjs +47 -0
  433. package/dist/upload/single.cjs.map +1 -0
  434. package/dist/upload/single.d.cts +51 -0
  435. package/dist/upload/single.d.cts.map +1 -0
  436. package/dist/upload/single.d.ts +51 -0
  437. package/dist/upload/single.d.ts.map +1 -0
  438. package/dist/upload/single.js +47 -0
  439. package/dist/upload/single.js.map +1 -0
  440. package/dist/upload/stream.cjs +198 -0
  441. package/dist/upload/stream.cjs.map +1 -0
  442. package/dist/upload/stream.d.cts +61 -0
  443. package/dist/upload/stream.d.cts.map +1 -0
  444. package/dist/upload/stream.d.ts +61 -0
  445. package/dist/upload/stream.d.ts.map +1 -0
  446. package/dist/upload/stream.js +198 -0
  447. package/dist/upload/stream.js.map +1 -0
  448. package/dist/util/best-effort.cjs +10 -0
  449. package/dist/util/best-effort.cjs.map +1 -0
  450. package/dist/util/best-effort.d.cts +31 -0
  451. package/dist/util/best-effort.d.cts.map +1 -0
  452. package/dist/util/best-effort.d.ts +31 -0
  453. package/dist/util/best-effort.d.ts.map +1 -0
  454. package/dist/util/best-effort.js +10 -0
  455. package/dist/util/best-effort.js.map +1 -0
  456. package/dist/util/defaults.cjs +11 -0
  457. package/dist/util/defaults.cjs.map +1 -0
  458. package/dist/util/defaults.d.cts +54 -0
  459. package/dist/util/defaults.d.cts.map +1 -0
  460. package/dist/util/defaults.d.ts +54 -0
  461. package/dist/util/defaults.d.ts.map +1 -0
  462. package/dist/util/defaults.js +11 -0
  463. package/dist/util/defaults.js.map +1 -0
  464. package/dist/util/normalize.cjs +16 -0
  465. package/dist/util/normalize.cjs.map +1 -0
  466. package/dist/util/normalize.d.cts +62 -0
  467. package/dist/util/normalize.d.cts.map +1 -0
  468. package/dist/util/normalize.d.ts +62 -0
  469. package/dist/util/normalize.d.ts.map +1 -0
  470. package/dist/util/normalize.js +16 -0
  471. package/dist/util/normalize.js.map +1 -0
  472. package/dist/util/paginator.cjs +20 -0
  473. package/dist/util/paginator.cjs.map +1 -0
  474. package/dist/util/paginator.d.cts +120 -0
  475. package/dist/util/paginator.d.cts.map +1 -0
  476. package/dist/util/paginator.d.ts +120 -0
  477. package/dist/util/paginator.d.ts.map +1 -0
  478. package/dist/util/paginator.js +20 -0
  479. package/dist/util/paginator.js.map +1 -0
  480. package/dist/util/plan-ranges.cjs +28 -0
  481. package/dist/util/plan-ranges.cjs.map +1 -0
  482. package/dist/util/plan-ranges.d.cts +56 -0
  483. package/dist/util/plan-ranges.d.cts.map +1 -0
  484. package/dist/util/plan-ranges.d.ts +56 -0
  485. package/dist/util/plan-ranges.d.ts.map +1 -0
  486. package/dist/util/plan-ranges.js +28 -0
  487. package/dist/util/plan-ranges.js.map +1 -0
  488. package/dist/util/text-codec.cjs +7 -0
  489. package/dist/util/text-codec.cjs.map +1 -0
  490. package/dist/util/text-codec.d.cts +26 -0
  491. package/dist/util/text-codec.d.cts.map +1 -0
  492. package/dist/util/text-codec.d.ts +26 -0
  493. package/dist/util/text-codec.d.ts.map +1 -0
  494. package/dist/util/text-codec.js +7 -0
  495. package/dist/util/text-codec.js.map +1 -0
  496. package/dist/util/to-error.cjs +7 -0
  497. package/dist/util/to-error.cjs.map +1 -0
  498. package/dist/util/to-error.d.cts +15 -0
  499. package/dist/util/to-error.d.cts.map +1 -0
  500. package/dist/util/to-error.d.ts +15 -0
  501. package/dist/util/to-error.d.ts.map +1 -0
  502. package/dist/util/to-error.js +7 -0
  503. package/dist/util/to-error.js.map +1 -0
  504. package/dist/version.cjs +6 -0
  505. package/dist/version.cjs.map +1 -0
  506. package/dist/version.d.cts +14 -0
  507. package/dist/version.d.cts.map +1 -0
  508. package/dist/version.d.ts +14 -0
  509. package/dist/version.d.ts.map +1 -0
  510. package/dist/version.js +6 -0
  511. package/dist/version.js.map +1 -0
  512. package/package.json +198 -0
@@ -0,0 +1,47 @@
1
+ import { IncrementalSha1 } from "../streams/hash.js";
2
+ import { ProgressTracker } from "../streams/progress.js";
3
+ import { DEFAULT_CONTENT_TYPE } from "../util/defaults.js";
4
+ async function uploadSmallFile(raw, accountInfo, options) {
5
+ let uploadEntry = accountInfo.checkoutUploadUrl(options.bucketId);
6
+ if (!uploadEntry) {
7
+ const resp = await raw.getUploadUrl(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
8
+ bucketId: options.bucketId
9
+ });
10
+ uploadEntry = { uploadUrl: resp.uploadUrl, authorizationToken: resp.authorizationToken };
11
+ }
12
+ const data = new Uint8Array(await options.source.toArrayBuffer());
13
+ const sha1 = new IncrementalSha1();
14
+ await sha1.update(data);
15
+ const sha1Hex = await sha1.digest();
16
+ const tracker = new ProgressTracker(options.onProgress, data.byteLength, 1);
17
+ try {
18
+ const result = await raw.uploadFile(
19
+ uploadEntry.uploadUrl,
20
+ {
21
+ authorization: uploadEntry.authorizationToken,
22
+ fileName: options.fileName,
23
+ contentType: options.contentType ?? DEFAULT_CONTENT_TYPE,
24
+ contentLength: data.byteLength,
25
+ contentSha1: sha1Hex,
26
+ ...options.fileInfo !== void 0 ? { fileInfo: options.fileInfo } : {},
27
+ ...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {},
28
+ ...options.fileRetention !== void 0 ? { fileRetention: options.fileRetention } : {},
29
+ ...options.legalHold !== void 0 ? { legalHold: options.legalHold } : {},
30
+ ...options.lastModifiedMillis !== void 0 ? { lastModifiedMillis: options.lastModifiedMillis } : {}
31
+ },
32
+ data,
33
+ options.signal
34
+ );
35
+ tracker.addBytes(data.byteLength);
36
+ tracker.completePart();
37
+ accountInfo.returnUploadUrl(options.bucketId, uploadEntry);
38
+ return result;
39
+ } catch (err) {
40
+ accountInfo.evictUploadUrl(options.bucketId, uploadEntry);
41
+ throw err;
42
+ }
43
+ }
44
+ export {
45
+ uploadSmallFile
46
+ };
47
+ //# sourceMappingURL=single.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"single.js","sources":["../../src/upload/single.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport { IncrementalSha1 } from '../streams/hash.ts'\nimport { type ProgressListener, ProgressTracker } from '../streams/progress.ts'\nimport type { ContentSource } from '../streams/source.ts'\nimport type { EncryptionSetting } from '../types/encryption.ts'\nimport type { FileVersion } from '../types/file.ts'\nimport type { BucketId } from '../types/ids.ts'\nimport type { FileRetentionValue, LegalHoldValue } from '../types/lock.ts'\nimport { DEFAULT_CONTENT_TYPE } from '../util/defaults.ts'\n\n/** Options for uploading a small file in a single HTTP request. */\nexport interface UploadFileOptions {\n /** Target bucket for the upload. */\n readonly bucketId: BucketId\n /** Full B2 file name including any path prefix. */\n readonly fileName: string\n /** Content to upload. */\n readonly source: ContentSource\n /** MIME type. Defaults to `b2/x-auto` for server-side detection. */\n readonly contentType?: string\n /** Custom file info key/value pairs stored with the file. */\n readonly fileInfo?: Record<string, string>\n /** Server-side encryption settings. */\n readonly serverSideEncryption?: EncryptionSetting\n /** File retention policy applied at upload time. */\n readonly fileRetention?: FileRetentionValue\n /** Legal hold status applied at upload time. */\n readonly legalHold?: LegalHoldValue\n /** Override the last-modified timestamp (epoch millis). */\n readonly lastModifiedMillis?: number\n /** Callback invoked with upload progress updates. */\n readonly onProgress?: ProgressListener\n /** Signal to abort the upload. */\n readonly signal?: AbortSignal\n}\n\n/**\n * Uploads a file in a single HTTP request (suitable for files up to ~100 MB).\n *\n * The entire file content is read into memory, SHA-1 hashed, and sent in one\n * `b2_upload_file` call. For files larger than the recommended part size, use\n * {@link uploadLargeFile} which splits the file into parts uploaded in parallel.\n *\n * Upload URLs are pooled via {@link AccountInfo} and recycled on success or\n * evicted on failure.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state (tokens, URLs, upload URL pool).\n * @param options - Upload parameters.\n *\n * @returns The resulting {@link FileVersion} metadata.\n */\nexport async function uploadSmallFile(\n raw: RawClient,\n accountInfo: AccountInfo,\n options: UploadFileOptions,\n): Promise<FileVersion> {\n let uploadEntry = accountInfo.checkoutUploadUrl(options.bucketId)\n\n if (!uploadEntry) {\n const resp = await raw.getUploadUrl(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {\n bucketId: options.bucketId,\n })\n uploadEntry = { uploadUrl: resp.uploadUrl, authorizationToken: resp.authorizationToken }\n }\n\n const data = new Uint8Array(await options.source.toArrayBuffer())\n const sha1 = new IncrementalSha1()\n await sha1.update(data)\n const sha1Hex = await sha1.digest()\n\n // Single-request uploads send the whole payload in one shot, so the\n // tracker reports a single \"part\" worth of progress: one byte burst at\n // completion and a parts-completed transition from 0 → 1. The tracker\n // is created (rather than calling the listener directly) so consumers\n // see the same {bytesTransferred, totalBytes, partsCompleted,\n // totalParts, elapsedMs} shape they get from `uploadLargeFile`.\n const tracker = new ProgressTracker(options.onProgress, data.byteLength, 1)\n\n try {\n const result = await raw.uploadFile(\n uploadEntry.uploadUrl,\n {\n authorization: uploadEntry.authorizationToken,\n fileName: options.fileName,\n contentType: options.contentType ?? DEFAULT_CONTENT_TYPE,\n contentLength: data.byteLength,\n contentSha1: sha1Hex,\n ...(options.fileInfo !== undefined ? { fileInfo: options.fileInfo } : {}),\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n ...(options.fileRetention !== undefined ? { fileRetention: options.fileRetention } : {}),\n ...(options.legalHold !== undefined ? { legalHold: options.legalHold } : {}),\n ...(options.lastModifiedMillis !== undefined\n ? { lastModifiedMillis: options.lastModifiedMillis }\n : {}),\n },\n data,\n options.signal,\n )\n\n tracker.addBytes(data.byteLength)\n tracker.completePart()\n accountInfo.returnUploadUrl(options.bucketId, uploadEntry)\n return result\n } catch (err) {\n accountInfo.evictUploadUrl(options.bucketId, uploadEntry)\n throw err\n }\n}\n"],"names":[],"mappings":";;;AAqDA,eAAsB,gBACpB,KACA,aACA,SACsB;AACtB,MAAI,cAAc,YAAY,kBAAkB,QAAQ,QAAQ;AAEhE,MAAI,CAAC,aAAa;AAChB,UAAM,OAAO,MAAM,IAAI,aAAa,YAAY,UAAA,GAAa,YAAY,gBAAgB;AAAA,MACvF,UAAU,QAAQ;AAAA,IAAA,CACnB;AACD,kBAAc,EAAE,WAAW,KAAK,WAAW,oBAAoB,KAAK,mBAAA;AAAA,EACtE;AAEA,QAAM,OAAO,IAAI,WAAW,MAAM,QAAQ,OAAO,eAAe;AAChE,QAAM,OAAO,IAAI,gBAAA;AACjB,QAAM,KAAK,OAAO,IAAI;AACtB,QAAM,UAAU,MAAM,KAAK,OAAA;AAQ3B,QAAM,UAAU,IAAI,gBAAgB,QAAQ,YAAY,KAAK,YAAY,CAAC;AAE1E,MAAI;AACF,UAAM,SAAS,MAAM,IAAI;AAAA,MACvB,YAAY;AAAA,MACZ;AAAA,QACE,eAAe,YAAY;AAAA,QAC3B,UAAU,QAAQ;AAAA,QAClB,aAAa,QAAQ,eAAe;AAAA,QACpC,eAAe,KAAK;AAAA,QACpB,aAAa;AAAA,QACb,GAAI,QAAQ,aAAa,SAAY,EAAE,UAAU,QAAQ,SAAA,IAAa,CAAA;AAAA,QACtE,GAAI,QAAQ,yBAAyB,SACjC,EAAE,sBAAsB,QAAQ,qBAAA,IAChC,CAAA;AAAA,QACJ,GAAI,QAAQ,kBAAkB,SAAY,EAAE,eAAe,QAAQ,cAAA,IAAkB,CAAA;AAAA,QACrF,GAAI,QAAQ,cAAc,SAAY,EAAE,WAAW,QAAQ,UAAA,IAAc,CAAA;AAAA,QACzE,GAAI,QAAQ,uBAAuB,SAC/B,EAAE,oBAAoB,QAAQ,uBAC9B,CAAA;AAAA,MAAC;AAAA,MAEP;AAAA,MACA,QAAQ;AAAA,IAAA;AAGV,YAAQ,SAAS,KAAK,UAAU;AAChC,YAAQ,aAAA;AACR,gBAAY,gBAAgB,QAAQ,UAAU,WAAW;AACzD,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,gBAAY,eAAe,QAAQ,UAAU,WAAW;AACxD,UAAM;AAAA,EACR;AACF;"}
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const hash = require("../streams/hash.cjs");
4
+ const progress = require("../streams/progress.cjs");
5
+ const defaults = require("../util/defaults.cjs");
6
+ const toError = require("../util/to-error.cjs");
7
+ const cancel = require("./cancel.cjs");
8
+ const concurrency = require("./concurrency.cjs");
9
+ function createWriteStream(raw, accountInfo, options) {
10
+ const minPartSize = accountInfo.getAbsoluteMinimumPartSize();
11
+ const recommendedPartSize = accountInfo.getRecommendedPartSize();
12
+ const partSize = Math.max(options.partSize ?? recommendedPartSize, minPartSize);
13
+ const concurrency$1 = options.concurrency ?? defaults.DEFAULT_TRANSFER_CONCURRENCY;
14
+ const tracker = new progress.ProgressTracker(options.onProgress, null, null);
15
+ const sem = new concurrency.Semaphore(concurrency$1);
16
+ let largeFileId = null;
17
+ let startPromise = null;
18
+ let nextPartNumber = 1;
19
+ let pendingBytes = 0;
20
+ const pending = [];
21
+ const partSha1s = [];
22
+ const inflight = [];
23
+ let errored = null;
24
+ const {
25
+ promise: done,
26
+ resolve: resolveDone,
27
+ reject: rejectDone
28
+ } = Promise.withResolvers();
29
+ done.catch(() => {
30
+ });
31
+ function ensureStarted() {
32
+ if (largeFileId !== null) return Promise.resolve(largeFileId);
33
+ if (startPromise !== null) return startPromise;
34
+ startPromise = (async () => {
35
+ const resp = await raw.startLargeFile(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
36
+ bucketId: options.bucketId,
37
+ fileName: options.fileName,
38
+ contentType: options.contentType ?? defaults.DEFAULT_CONTENT_TYPE,
39
+ fileInfo: options.fileInfo ?? {},
40
+ ...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {}
41
+ });
42
+ largeFileId = resp.fileId;
43
+ return largeFileId;
44
+ })();
45
+ return startPromise;
46
+ }
47
+ async function shipPart(data, partNumber) {
48
+ const fileId = await ensureStarted();
49
+ const sha1 = new hash.IncrementalSha1();
50
+ await sha1.update(data);
51
+ const sha1Hex = await sha1.digest();
52
+ let uploadEntry = accountInfo.checkoutPartUploadUrl(fileId);
53
+ if (!uploadEntry) {
54
+ const resp = await raw.getUploadPartUrl(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
55
+ fileId
56
+ });
57
+ uploadEntry = { uploadUrl: resp.uploadUrl, authorizationToken: resp.authorizationToken };
58
+ }
59
+ try {
60
+ const result = await raw.uploadPart(
61
+ uploadEntry.uploadUrl,
62
+ {
63
+ authorization: uploadEntry.authorizationToken,
64
+ partNumber,
65
+ contentLength: data.byteLength,
66
+ contentSha1: sha1Hex,
67
+ ...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {}
68
+ },
69
+ data,
70
+ options.signal
71
+ );
72
+ accountInfo.returnPartUploadUrl(fileId, uploadEntry);
73
+ partSha1s[partNumber - 1] = result.contentSha1;
74
+ tracker.addBytes(data.byteLength);
75
+ tracker.completePart();
76
+ } catch (err) {
77
+ accountInfo.evictPartUploadUrl(fileId, uploadEntry);
78
+ throw err;
79
+ }
80
+ }
81
+ function dispatchPart() {
82
+ if (pending.length === 0) return;
83
+ let data;
84
+ if (pending.length === 1) {
85
+ const head = pending[0];
86
+ if (!head) return;
87
+ data = head;
88
+ } else {
89
+ const total = pending.reduce((sum, chunk) => sum + chunk.byteLength, 0);
90
+ data = new Uint8Array(total);
91
+ let offset = 0;
92
+ for (const chunk of pending) {
93
+ data.set(chunk, offset);
94
+ offset += chunk.byteLength;
95
+ }
96
+ }
97
+ pending.length = 0;
98
+ pendingBytes = 0;
99
+ const partNumber = nextPartNumber++;
100
+ const task = (async () => {
101
+ await sem.acquire();
102
+ try {
103
+ await shipPart(data, partNumber);
104
+ } catch (err) {
105
+ errored = toError.toError(err);
106
+ throw err;
107
+ } finally {
108
+ sem.release();
109
+ }
110
+ })();
111
+ inflight.push(task);
112
+ task.catch(() => {
113
+ });
114
+ }
115
+ const writable = new WritableStream({
116
+ async write(chunk) {
117
+ if (errored) throw errored;
118
+ options.signal?.throwIfAborted();
119
+ pending.push(chunk);
120
+ pendingBytes += chunk.byteLength;
121
+ while (pendingBytes >= partSize) {
122
+ const carved = carveExact(pending, partSize);
123
+ const partNumber = nextPartNumber++;
124
+ pendingBytes -= partSize;
125
+ const task = (async () => {
126
+ await sem.acquire();
127
+ try {
128
+ await shipPart(carved, partNumber);
129
+ } catch (err) {
130
+ errored = toError.toError(err);
131
+ throw err;
132
+ } finally {
133
+ sem.release();
134
+ }
135
+ })();
136
+ inflight.push(task);
137
+ task.catch(() => {
138
+ });
139
+ }
140
+ },
141
+ async close() {
142
+ try {
143
+ if (errored) throw errored;
144
+ options.signal?.throwIfAborted();
145
+ if (pendingBytes > 0) {
146
+ dispatchPart();
147
+ }
148
+ await Promise.all(inflight);
149
+ if (errored) throw errored;
150
+ if (largeFileId === null) {
151
+ throw new Error("createWriteStream closed without any data written.");
152
+ }
153
+ const result = await raw.finishLargeFile(
154
+ accountInfo.getApiUrl(),
155
+ accountInfo.getAuthToken(),
156
+ { fileId: largeFileId, partSha1Array: partSha1s }
157
+ );
158
+ resolveDone(result);
159
+ } catch (err) {
160
+ const fileIdToCancel = largeFileId;
161
+ if (fileIdToCancel !== null) {
162
+ await cancel.cancelLargeFileBestEffort(raw, accountInfo, fileIdToCancel);
163
+ }
164
+ rejectDone(err);
165
+ throw err;
166
+ }
167
+ },
168
+ async abort(reason) {
169
+ const fileIdToCancel = largeFileId;
170
+ if (fileIdToCancel !== null) {
171
+ await cancel.cancelLargeFileBestEffort(raw, accountInfo, fileIdToCancel);
172
+ }
173
+ rejectDone(toError.toError(reason));
174
+ }
175
+ });
176
+ return { writable, done };
177
+ }
178
+ function carveExact(chunks, size) {
179
+ const out = new Uint8Array(size);
180
+ let written = 0;
181
+ while (written < size && chunks.length > 0) {
182
+ const head = chunks[0];
183
+ if (!head) break;
184
+ const need = size - written;
185
+ if (head.byteLength <= need) {
186
+ out.set(head, written);
187
+ written += head.byteLength;
188
+ chunks.shift();
189
+ } else {
190
+ out.set(head.subarray(0, need), written);
191
+ chunks[0] = head.subarray(need);
192
+ written += need;
193
+ }
194
+ }
195
+ return out;
196
+ }
197
+ exports.createWriteStream = createWriteStream;
198
+ //# sourceMappingURL=stream.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.cjs","sources":["../../src/upload/stream.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport { IncrementalSha1 } from '../streams/hash.ts'\nimport type { ProgressListener } from '../streams/progress.ts'\nimport { ProgressTracker } from '../streams/progress.ts'\nimport type { EncryptionSetting } from '../types/encryption.ts'\nimport type { FileVersion } from '../types/file.ts'\nimport type { BucketId, LargeFileId } from '../types/ids.ts'\nimport { DEFAULT_CONTENT_TYPE, DEFAULT_TRANSFER_CONCURRENCY } from '../util/defaults.ts'\nimport { toError } from '../util/to-error.ts'\nimport { cancelLargeFileBestEffort } from './cancel.ts'\nimport { Semaphore } from './concurrency.ts'\n\n/** Options for creating a streaming multipart upload sink. */\nexport interface CreateWriteStreamOptions {\n /** Target bucket for the upload. */\n readonly bucketId: BucketId\n /** Destination file name in the bucket. */\n readonly fileName: string\n /** MIME type. Defaults to `b2/x-auto`. */\n readonly contentType?: string\n /** Custom file info stored with the file. */\n readonly fileInfo?: Record<string, string>\n /** Server-side encryption applied to each part. */\n readonly serverSideEncryption?: EncryptionSetting\n /**\n * Target part size in bytes. The stream buffers writes until this many bytes\n * are accumulated, then ships a part. Must be at least the account's\n * absolute minimum part size; the implementation will raise it if too small.\n */\n readonly partSize?: number\n /** Maximum number of parts uploaded in parallel. Defaults to 4. */\n readonly concurrency?: number\n /** Callback invoked with upload progress events. `totalBytes` is `null` (size unknown). */\n readonly onProgress?: ProgressListener\n /** Aborts the upload and cancels the unfinished large file. */\n readonly signal?: AbortSignal\n}\n\n/**\n * Handle returned by `B2Object.createWriteStream`: the Web `WritableStream` to\n * pipe data into, plus a promise that resolves with the finished\n * {@link FileVersion} once the stream is closed and all parts have been\n * uploaded.\n */\nexport interface UploadWriteHandle {\n /** Web `WritableStream` sink to pipe data into. */\n readonly writable: WritableStream<Uint8Array>\n /** Resolves with the finalized file version when the stream closes successfully. */\n readonly done: Promise<FileVersion>\n}\n\n/**\n * Creates a {@link WritableStream} that streams data into a B2 multipart upload.\n *\n * Buffers incoming chunks until `partSize` bytes are accumulated, ships each\n * complete part through the standard multipart engine, and finalizes the file\n * once the stream is closed. Honours backpressure via the queue's bounded\n * concurrency. Streaming uploads do not support resume because the total size\n * and per-part hashes aren't known in advance; use {@link uploadLargeFile} with\n * a buffered source when resume is required.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state (tokens, URLs, part URL pool).\n * @param options - Streaming upload parameters.\n *\n * @returns A {@link UploadWriteHandle} with the writable sink and a completion promise.\n */\nexport function createWriteStream(\n raw: RawClient,\n accountInfo: AccountInfo,\n options: CreateWriteStreamOptions,\n): UploadWriteHandle {\n const minPartSize = accountInfo.getAbsoluteMinimumPartSize()\n const recommendedPartSize = accountInfo.getRecommendedPartSize()\n const partSize = Math.max(options.partSize ?? recommendedPartSize, minPartSize)\n const concurrency = options.concurrency ?? DEFAULT_TRANSFER_CONCURRENCY\n const tracker = new ProgressTracker(options.onProgress, null, null)\n const sem = new Semaphore(concurrency)\n\n let largeFileId: LargeFileId | null = null\n let startPromise: Promise<LargeFileId> | null = null\n let nextPartNumber = 1\n let pendingBytes = 0\n const pending: Uint8Array[] = []\n const partSha1s: string[] = []\n const inflight: Promise<void>[] = []\n let errored: Error | null = null\n\n // ES2024 `Promise.withResolvers()` exposes the resolve/reject pair as\n // properties of the returned object, avoiding the `let resolve!:` /\n // `let reject!:` non-null-assertion pattern needed before this API\n // existed. Available in Node 22 (our minimum), Bun, Deno, modern\n // browsers, and Cloudflare Workers.\n const {\n promise: done,\n resolve: resolveDone,\n reject: rejectDone,\n } = Promise.withResolvers<FileVersion>()\n // Attach a no-op rejection handler so a `done` that rejects before the\n // caller observes it never surfaces as a process-level unhandled rejection.\n // The error is not swallowed: `close()`/`abort()` also reject the writable\n // (so `pipeTo`/`getWriter().close()` throw), and any later `await done` /\n // `done.then(onRejected)` the caller attaches still sees the rejection —\n // extra handlers on the same promise all fire. Mirrors the\n // `task.catch(() => {})` pattern used for inflight part uploads below, and\n // keeps the engine well-behaved under Bun and Node's strict\n // unhandled-rejection mode.\n done.catch(() => {})\n\n function ensureStarted(): Promise<LargeFileId> {\n if (largeFileId !== null) return Promise.resolve(largeFileId)\n if (startPromise !== null) return startPromise\n startPromise = (async () => {\n const resp = await raw.startLargeFile(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {\n bucketId: options.bucketId,\n fileName: options.fileName,\n contentType: options.contentType ?? DEFAULT_CONTENT_TYPE,\n fileInfo: options.fileInfo ?? {},\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n })\n largeFileId = resp.fileId\n return largeFileId\n })()\n return startPromise\n }\n\n async function shipPart(data: Uint8Array, partNumber: number): Promise<void> {\n const fileId = await ensureStarted()\n\n const sha1 = new IncrementalSha1()\n await sha1.update(data)\n const sha1Hex = await sha1.digest()\n\n let uploadEntry = accountInfo.checkoutPartUploadUrl(fileId)\n if (!uploadEntry) {\n const resp = await raw.getUploadPartUrl(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {\n fileId,\n })\n uploadEntry = { uploadUrl: resp.uploadUrl, authorizationToken: resp.authorizationToken }\n }\n\n try {\n const result = await raw.uploadPart(\n uploadEntry.uploadUrl,\n {\n authorization: uploadEntry.authorizationToken,\n partNumber,\n contentLength: data.byteLength,\n contentSha1: sha1Hex,\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n },\n data as BodyInit,\n options.signal,\n )\n accountInfo.returnPartUploadUrl(fileId, uploadEntry)\n partSha1s[partNumber - 1] = result.contentSha1\n tracker.addBytes(data.byteLength)\n tracker.completePart()\n } catch (err) {\n accountInfo.evictPartUploadUrl(fileId, uploadEntry)\n throw err\n }\n }\n\n function dispatchPart(): void {\n if (pending.length === 0) return\n let data: Uint8Array\n if (pending.length === 1) {\n const head = pending[0]\n if (!head) return\n data = head\n } else {\n const total = pending.reduce((sum, chunk) => sum + chunk.byteLength, 0)\n data = new Uint8Array(total)\n let offset = 0\n for (const chunk of pending) {\n data.set(chunk, offset)\n offset += chunk.byteLength\n }\n }\n pending.length = 0\n pendingBytes = 0\n const partNumber = nextPartNumber++\n const task = (async () => {\n await sem.acquire()\n try {\n await shipPart(data, partNumber)\n } catch (err) {\n errored = toError(err)\n throw err\n } finally {\n sem.release()\n }\n })()\n inflight.push(task)\n // Swallow rejection here; we check `errored` later.\n task.catch(() => {})\n }\n\n const writable = new WritableStream<Uint8Array>({\n async write(chunk: Uint8Array): Promise<void> {\n if (errored) throw errored\n options.signal?.throwIfAborted()\n\n pending.push(chunk)\n pendingBytes += chunk.byteLength\n while (pendingBytes >= partSize) {\n // Pull exactly partSize bytes off the front\n const carved = carveExact(pending, partSize)\n const partNumber = nextPartNumber++\n pendingBytes -= partSize\n const task = (async () => {\n await sem.acquire()\n try {\n await shipPart(carved, partNumber)\n } catch (err) {\n errored = toError(err)\n throw err\n } finally {\n sem.release()\n }\n })()\n inflight.push(task)\n task.catch(() => {})\n }\n },\n\n async close(): Promise<void> {\n try {\n if (errored) throw errored\n options.signal?.throwIfAborted()\n\n // Ship any remaining bytes as the last part. If the total fit in one\n // single buffered batch (no parts shipped yet), we have to use the\n // multipart path anyway since we already called startLargeFile lazily.\n if (pendingBytes > 0) {\n dispatchPart()\n }\n\n await Promise.all(inflight)\n if (errored) throw errored\n\n if (largeFileId === null) {\n // Stream closed before any data was written. Start an empty large\n // file? B2 requires at least 2 parts. Reject — callers shouldn't\n // close an empty stream.\n throw new Error('createWriteStream closed without any data written.')\n }\n\n const result = await raw.finishLargeFile(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n { fileId: largeFileId, partSha1Array: partSha1s },\n )\n resolveDone(result)\n } catch (err) {\n // Capture into a const so the cancel closure sees a non-null\n // `fileId`; closures don't observe the outer `!== null` narrowing\n // because the variable is mutable across the lambda boundary.\n const fileIdToCancel = largeFileId\n if (fileIdToCancel !== null) {\n await cancelLargeFileBestEffort(raw, accountInfo, fileIdToCancel)\n }\n rejectDone(err)\n throw err\n }\n },\n\n async abort(reason: unknown): Promise<void> {\n const fileIdToCancel = largeFileId\n if (fileIdToCancel !== null) {\n await cancelLargeFileBestEffort(raw, accountInfo, fileIdToCancel)\n }\n rejectDone(toError(reason))\n },\n })\n\n return { writable, done }\n}\n\n/**\n * Removes exactly `size` bytes from the front of `chunks` (mutates) and returns\n * them as a contiguous Uint8Array. Any trailing remainder of the last chunk\n * stays at the front of `chunks` for the next part.\n *\n * @param chunks - Queue of pending chunks. Modified in place.\n * @param size - Number of bytes to carve off the front.\n *\n * @returns A new Uint8Array containing exactly `size` bytes.\n */\nfunction carveExact(chunks: Uint8Array[], size: number): Uint8Array {\n const out = new Uint8Array(size)\n let written = 0\n while (written < size && chunks.length > 0) {\n const head = chunks[0]\n if (!head) break\n const need = size - written\n if (head.byteLength <= need) {\n out.set(head, written)\n written += head.byteLength\n chunks.shift()\n } else {\n out.set(head.subarray(0, need), written)\n chunks[0] = head.subarray(need)\n written += need\n }\n }\n return out\n}\n"],"names":["concurrency","DEFAULT_TRANSFER_CONCURRENCY","ProgressTracker","Semaphore","DEFAULT_CONTENT_TYPE","IncrementalSha1","toError","cancelLargeFileBestEffort"],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import { AccountInfo } from '../auth/account-info.js';
2
+ import { RawClient } from '../raw/index.js';
3
+ import { ProgressListener } from '../streams/progress.js';
4
+ import { EncryptionSetting } from '../types/encryption.js';
5
+ import { FileVersion } from '../types/file.js';
6
+ import { BucketId } from '../types/ids.js';
7
+ /** Options for creating a streaming multipart upload sink. */
8
+ export interface CreateWriteStreamOptions {
9
+ /** Target bucket for the upload. */
10
+ readonly bucketId: BucketId;
11
+ /** Destination file name in the bucket. */
12
+ readonly fileName: string;
13
+ /** MIME type. Defaults to `b2/x-auto`. */
14
+ readonly contentType?: string;
15
+ /** Custom file info stored with the file. */
16
+ readonly fileInfo?: Record<string, string>;
17
+ /** Server-side encryption applied to each part. */
18
+ readonly serverSideEncryption?: EncryptionSetting;
19
+ /**
20
+ * Target part size in bytes. The stream buffers writes until this many bytes
21
+ * are accumulated, then ships a part. Must be at least the account's
22
+ * absolute minimum part size; the implementation will raise it if too small.
23
+ */
24
+ readonly partSize?: number;
25
+ /** Maximum number of parts uploaded in parallel. Defaults to 4. */
26
+ readonly concurrency?: number;
27
+ /** Callback invoked with upload progress events. `totalBytes` is `null` (size unknown). */
28
+ readonly onProgress?: ProgressListener;
29
+ /** Aborts the upload and cancels the unfinished large file. */
30
+ readonly signal?: AbortSignal;
31
+ }
32
+ /**
33
+ * Handle returned by `B2Object.createWriteStream`: the Web `WritableStream` to
34
+ * pipe data into, plus a promise that resolves with the finished
35
+ * {@link FileVersion} once the stream is closed and all parts have been
36
+ * uploaded.
37
+ */
38
+ export interface UploadWriteHandle {
39
+ /** Web `WritableStream` sink to pipe data into. */
40
+ readonly writable: WritableStream<Uint8Array>;
41
+ /** Resolves with the finalized file version when the stream closes successfully. */
42
+ readonly done: Promise<FileVersion>;
43
+ }
44
+ /**
45
+ * Creates a {@link WritableStream} that streams data into a B2 multipart upload.
46
+ *
47
+ * Buffers incoming chunks until `partSize` bytes are accumulated, ships each
48
+ * complete part through the standard multipart engine, and finalizes the file
49
+ * once the stream is closed. Honours backpressure via the queue's bounded
50
+ * concurrency. Streaming uploads do not support resume because the total size
51
+ * and per-part hashes aren't known in advance; use {@link uploadLargeFile} with
52
+ * a buffered source when resume is required.
53
+ *
54
+ * @param raw - Low-level B2 API client.
55
+ * @param accountInfo - Authorized account state (tokens, URLs, part URL pool).
56
+ * @param options - Streaming upload parameters.
57
+ *
58
+ * @returns A {@link UploadWriteHandle} with the writable sink and a completion promise.
59
+ */
60
+ export declare function createWriteStream(raw: RawClient, accountInfo: AccountInfo, options: CreateWriteStreamOptions): UploadWriteHandle;
61
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/upload/stream.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,iBAAiB,CAAA;AAM5D,8DAA8D;AAC9D,MAAM,WAAW,wBAAwB;IACvC,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,mDAAmD;IACnD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IAC7C,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;CACpC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAmNnB"}
@@ -0,0 +1,61 @@
1
+ import { AccountInfo } from '../auth/account-info.js';
2
+ import { RawClient } from '../raw/index.js';
3
+ import { ProgressListener } from '../streams/progress.js';
4
+ import { EncryptionSetting } from '../types/encryption.js';
5
+ import { FileVersion } from '../types/file.js';
6
+ import { BucketId } from '../types/ids.js';
7
+ /** Options for creating a streaming multipart upload sink. */
8
+ export interface CreateWriteStreamOptions {
9
+ /** Target bucket for the upload. */
10
+ readonly bucketId: BucketId;
11
+ /** Destination file name in the bucket. */
12
+ readonly fileName: string;
13
+ /** MIME type. Defaults to `b2/x-auto`. */
14
+ readonly contentType?: string;
15
+ /** Custom file info stored with the file. */
16
+ readonly fileInfo?: Record<string, string>;
17
+ /** Server-side encryption applied to each part. */
18
+ readonly serverSideEncryption?: EncryptionSetting;
19
+ /**
20
+ * Target part size in bytes. The stream buffers writes until this many bytes
21
+ * are accumulated, then ships a part. Must be at least the account's
22
+ * absolute minimum part size; the implementation will raise it if too small.
23
+ */
24
+ readonly partSize?: number;
25
+ /** Maximum number of parts uploaded in parallel. Defaults to 4. */
26
+ readonly concurrency?: number;
27
+ /** Callback invoked with upload progress events. `totalBytes` is `null` (size unknown). */
28
+ readonly onProgress?: ProgressListener;
29
+ /** Aborts the upload and cancels the unfinished large file. */
30
+ readonly signal?: AbortSignal;
31
+ }
32
+ /**
33
+ * Handle returned by `B2Object.createWriteStream`: the Web `WritableStream` to
34
+ * pipe data into, plus a promise that resolves with the finished
35
+ * {@link FileVersion} once the stream is closed and all parts have been
36
+ * uploaded.
37
+ */
38
+ export interface UploadWriteHandle {
39
+ /** Web `WritableStream` sink to pipe data into. */
40
+ readonly writable: WritableStream<Uint8Array>;
41
+ /** Resolves with the finalized file version when the stream closes successfully. */
42
+ readonly done: Promise<FileVersion>;
43
+ }
44
+ /**
45
+ * Creates a {@link WritableStream} that streams data into a B2 multipart upload.
46
+ *
47
+ * Buffers incoming chunks until `partSize` bytes are accumulated, ships each
48
+ * complete part through the standard multipart engine, and finalizes the file
49
+ * once the stream is closed. Honours backpressure via the queue's bounded
50
+ * concurrency. Streaming uploads do not support resume because the total size
51
+ * and per-part hashes aren't known in advance; use {@link uploadLargeFile} with
52
+ * a buffered source when resume is required.
53
+ *
54
+ * @param raw - Low-level B2 API client.
55
+ * @param accountInfo - Authorized account state (tokens, URLs, part URL pool).
56
+ * @param options - Streaming upload parameters.
57
+ *
58
+ * @returns A {@link UploadWriteHandle} with the writable sink and a completion promise.
59
+ */
60
+ export declare function createWriteStream(raw: RawClient, accountInfo: AccountInfo, options: CreateWriteStreamOptions): UploadWriteHandle;
61
+ //# sourceMappingURL=stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/upload/stream.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAe,MAAM,iBAAiB,CAAA;AAM5D,8DAA8D;AAC9D,MAAM,WAAW,wBAAwB;IACvC,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1C,mDAAmD;IACnD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,CAAA;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAA;IACtC,+DAA+D;IAC/D,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IAC7C,oFAAoF;IACpF,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;CACpC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,wBAAwB,GAChC,iBAAiB,CAmNnB"}
@@ -0,0 +1,198 @@
1
+ import { IncrementalSha1 } from "../streams/hash.js";
2
+ import { ProgressTracker } from "../streams/progress.js";
3
+ import { DEFAULT_TRANSFER_CONCURRENCY, DEFAULT_CONTENT_TYPE } from "../util/defaults.js";
4
+ import { toError } from "../util/to-error.js";
5
+ import { cancelLargeFileBestEffort } from "./cancel.js";
6
+ import { Semaphore } from "./concurrency.js";
7
+ function createWriteStream(raw, accountInfo, options) {
8
+ const minPartSize = accountInfo.getAbsoluteMinimumPartSize();
9
+ const recommendedPartSize = accountInfo.getRecommendedPartSize();
10
+ const partSize = Math.max(options.partSize ?? recommendedPartSize, minPartSize);
11
+ const concurrency = options.concurrency ?? DEFAULT_TRANSFER_CONCURRENCY;
12
+ const tracker = new ProgressTracker(options.onProgress, null, null);
13
+ const sem = new Semaphore(concurrency);
14
+ let largeFileId = null;
15
+ let startPromise = null;
16
+ let nextPartNumber = 1;
17
+ let pendingBytes = 0;
18
+ const pending = [];
19
+ const partSha1s = [];
20
+ const inflight = [];
21
+ let errored = null;
22
+ const {
23
+ promise: done,
24
+ resolve: resolveDone,
25
+ reject: rejectDone
26
+ } = Promise.withResolvers();
27
+ done.catch(() => {
28
+ });
29
+ function ensureStarted() {
30
+ if (largeFileId !== null) return Promise.resolve(largeFileId);
31
+ if (startPromise !== null) return startPromise;
32
+ startPromise = (async () => {
33
+ const resp = await raw.startLargeFile(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
34
+ bucketId: options.bucketId,
35
+ fileName: options.fileName,
36
+ contentType: options.contentType ?? DEFAULT_CONTENT_TYPE,
37
+ fileInfo: options.fileInfo ?? {},
38
+ ...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {}
39
+ });
40
+ largeFileId = resp.fileId;
41
+ return largeFileId;
42
+ })();
43
+ return startPromise;
44
+ }
45
+ async function shipPart(data, partNumber) {
46
+ const fileId = await ensureStarted();
47
+ const sha1 = new IncrementalSha1();
48
+ await sha1.update(data);
49
+ const sha1Hex = await sha1.digest();
50
+ let uploadEntry = accountInfo.checkoutPartUploadUrl(fileId);
51
+ if (!uploadEntry) {
52
+ const resp = await raw.getUploadPartUrl(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
53
+ fileId
54
+ });
55
+ uploadEntry = { uploadUrl: resp.uploadUrl, authorizationToken: resp.authorizationToken };
56
+ }
57
+ try {
58
+ const result = await raw.uploadPart(
59
+ uploadEntry.uploadUrl,
60
+ {
61
+ authorization: uploadEntry.authorizationToken,
62
+ partNumber,
63
+ contentLength: data.byteLength,
64
+ contentSha1: sha1Hex,
65
+ ...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {}
66
+ },
67
+ data,
68
+ options.signal
69
+ );
70
+ accountInfo.returnPartUploadUrl(fileId, uploadEntry);
71
+ partSha1s[partNumber - 1] = result.contentSha1;
72
+ tracker.addBytes(data.byteLength);
73
+ tracker.completePart();
74
+ } catch (err) {
75
+ accountInfo.evictPartUploadUrl(fileId, uploadEntry);
76
+ throw err;
77
+ }
78
+ }
79
+ function dispatchPart() {
80
+ if (pending.length === 0) return;
81
+ let data;
82
+ if (pending.length === 1) {
83
+ const head = pending[0];
84
+ if (!head) return;
85
+ data = head;
86
+ } else {
87
+ const total = pending.reduce((sum, chunk) => sum + chunk.byteLength, 0);
88
+ data = new Uint8Array(total);
89
+ let offset = 0;
90
+ for (const chunk of pending) {
91
+ data.set(chunk, offset);
92
+ offset += chunk.byteLength;
93
+ }
94
+ }
95
+ pending.length = 0;
96
+ pendingBytes = 0;
97
+ const partNumber = nextPartNumber++;
98
+ const task = (async () => {
99
+ await sem.acquire();
100
+ try {
101
+ await shipPart(data, partNumber);
102
+ } catch (err) {
103
+ errored = toError(err);
104
+ throw err;
105
+ } finally {
106
+ sem.release();
107
+ }
108
+ })();
109
+ inflight.push(task);
110
+ task.catch(() => {
111
+ });
112
+ }
113
+ const writable = new WritableStream({
114
+ async write(chunk) {
115
+ if (errored) throw errored;
116
+ options.signal?.throwIfAborted();
117
+ pending.push(chunk);
118
+ pendingBytes += chunk.byteLength;
119
+ while (pendingBytes >= partSize) {
120
+ const carved = carveExact(pending, partSize);
121
+ const partNumber = nextPartNumber++;
122
+ pendingBytes -= partSize;
123
+ const task = (async () => {
124
+ await sem.acquire();
125
+ try {
126
+ await shipPart(carved, partNumber);
127
+ } catch (err) {
128
+ errored = toError(err);
129
+ throw err;
130
+ } finally {
131
+ sem.release();
132
+ }
133
+ })();
134
+ inflight.push(task);
135
+ task.catch(() => {
136
+ });
137
+ }
138
+ },
139
+ async close() {
140
+ try {
141
+ if (errored) throw errored;
142
+ options.signal?.throwIfAborted();
143
+ if (pendingBytes > 0) {
144
+ dispatchPart();
145
+ }
146
+ await Promise.all(inflight);
147
+ if (errored) throw errored;
148
+ if (largeFileId === null) {
149
+ throw new Error("createWriteStream closed without any data written.");
150
+ }
151
+ const result = await raw.finishLargeFile(
152
+ accountInfo.getApiUrl(),
153
+ accountInfo.getAuthToken(),
154
+ { fileId: largeFileId, partSha1Array: partSha1s }
155
+ );
156
+ resolveDone(result);
157
+ } catch (err) {
158
+ const fileIdToCancel = largeFileId;
159
+ if (fileIdToCancel !== null) {
160
+ await cancelLargeFileBestEffort(raw, accountInfo, fileIdToCancel);
161
+ }
162
+ rejectDone(err);
163
+ throw err;
164
+ }
165
+ },
166
+ async abort(reason) {
167
+ const fileIdToCancel = largeFileId;
168
+ if (fileIdToCancel !== null) {
169
+ await cancelLargeFileBestEffort(raw, accountInfo, fileIdToCancel);
170
+ }
171
+ rejectDone(toError(reason));
172
+ }
173
+ });
174
+ return { writable, done };
175
+ }
176
+ function carveExact(chunks, size) {
177
+ const out = new Uint8Array(size);
178
+ let written = 0;
179
+ while (written < size && chunks.length > 0) {
180
+ const head = chunks[0];
181
+ if (!head) break;
182
+ const need = size - written;
183
+ if (head.byteLength <= need) {
184
+ out.set(head, written);
185
+ written += head.byteLength;
186
+ chunks.shift();
187
+ } else {
188
+ out.set(head.subarray(0, need), written);
189
+ chunks[0] = head.subarray(need);
190
+ written += need;
191
+ }
192
+ }
193
+ return out;
194
+ }
195
+ export {
196
+ createWriteStream
197
+ };
198
+ //# sourceMappingURL=stream.js.map