@backblaze-labs/b2-sdk 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (701) hide show
  1. package/CHANGELOG.md +110 -5
  2. package/README.md +144 -33
  3. package/dist/_virtual/_b2-sdk-version-json.cjs +4 -0
  4. package/dist/_virtual/_b2-sdk-version-json.js +4 -0
  5. package/dist/auth/account-info.d.cts +32 -0
  6. package/dist/auth/account-info.d.cts.map +1 -1
  7. package/dist/auth/account-info.d.ts +32 -0
  8. package/dist/auth/account-info.d.ts.map +1 -1
  9. package/dist/auth/file.cjs +408 -207
  10. package/dist/auth/file.cjs.map +1 -1
  11. package/dist/auth/file.d.cts +77 -3
  12. package/dist/auth/file.d.cts.map +1 -1
  13. package/dist/auth/file.d.ts +77 -3
  14. package/dist/auth/file.d.ts.map +1 -1
  15. package/dist/auth/file.js +407 -207
  16. package/dist/auth/file.js.map +1 -1
  17. package/dist/auth/in-memory.cjs +212 -183
  18. package/dist/auth/in-memory.cjs.map +1 -1
  19. package/dist/auth/in-memory.d.cts +8 -0
  20. package/dist/auth/in-memory.d.cts.map +1 -1
  21. package/dist/auth/in-memory.d.ts +8 -0
  22. package/dist/auth/in-memory.d.ts.map +1 -1
  23. package/dist/auth/in-memory.js +211 -182
  24. package/dist/auth/in-memory.js.map +1 -1
  25. package/dist/auth/index.cjs +7 -9
  26. package/dist/auth/index.d.cts +3 -2
  27. package/dist/auth/index.d.cts.map +1 -1
  28. package/dist/auth/index.d.ts +3 -2
  29. package/dist/auth/index.d.ts.map +1 -1
  30. package/dist/auth/index.js +2 -8
  31. package/dist/auth/realms.cjs +80 -7
  32. package/dist/auth/realms.cjs.map +1 -1
  33. package/dist/auth/realms.d.cts +27 -4
  34. package/dist/auth/realms.d.cts.map +1 -1
  35. package/dist/auth/realms.d.ts +27 -4
  36. package/dist/auth/realms.d.ts.map +1 -1
  37. package/dist/auth/realms.js +80 -9
  38. package/dist/auth/realms.js.map +1 -1
  39. package/dist/auth/upload-url-pool.cjs +55 -51
  40. package/dist/auth/upload-url-pool.cjs.map +1 -1
  41. package/dist/auth/upload-url-pool.js +55 -51
  42. package/dist/auth/upload-url-pool.js.map +1 -1
  43. package/dist/bucket.cjs +785 -787
  44. package/dist/bucket.cjs.map +1 -1
  45. package/dist/bucket.d.cts +35 -47
  46. package/dist/bucket.d.cts.map +1 -1
  47. package/dist/bucket.d.ts +35 -47
  48. package/dist/bucket.d.ts.map +1 -1
  49. package/dist/bucket.js +780 -782
  50. package/dist/bucket.js.map +1 -1
  51. package/dist/client.cjs +246 -228
  52. package/dist/client.cjs.map +1 -1
  53. package/dist/client.d.cts +25 -17
  54. package/dist/client.d.cts.map +1 -1
  55. package/dist/client.d.ts +25 -17
  56. package/dist/client.d.ts.map +1 -1
  57. package/dist/client.js +243 -225
  58. package/dist/client.js.map +1 -1
  59. package/dist/copy/large.cjs +114 -71
  60. package/dist/copy/large.cjs.map +1 -1
  61. package/dist/copy/large.d.cts +6 -0
  62. package/dist/copy/large.d.cts.map +1 -1
  63. package/dist/copy/large.d.ts +6 -0
  64. package/dist/copy/large.d.ts.map +1 -1
  65. package/dist/copy/large.js +112 -69
  66. package/dist/copy/large.js.map +1 -1
  67. package/dist/download/checksum.cjs +89 -0
  68. package/dist/download/checksum.cjs.map +1 -0
  69. package/dist/download/checksum.d.cts +40 -0
  70. package/dist/download/checksum.d.cts.map +1 -0
  71. package/dist/download/checksum.d.ts +40 -0
  72. package/dist/download/checksum.d.ts.map +1 -0
  73. package/dist/download/checksum.js +87 -0
  74. package/dist/download/checksum.js.map +1 -0
  75. package/dist/download/parallel.cjs +214 -118
  76. package/dist/download/parallel.cjs.map +1 -1
  77. package/dist/download/parallel.d.cts +5 -1
  78. package/dist/download/parallel.d.cts.map +1 -1
  79. package/dist/download/parallel.d.ts +5 -1
  80. package/dist/download/parallel.d.ts.map +1 -1
  81. package/dist/download/parallel.js +212 -116
  82. package/dist/download/parallel.js.map +1 -1
  83. package/dist/download/single.cjs +188 -97
  84. package/dist/download/single.cjs.map +1 -1
  85. package/dist/download/single.d.cts +6 -1
  86. package/dist/download/single.d.cts.map +1 -1
  87. package/dist/download/single.d.ts +6 -1
  88. package/dist/download/single.d.ts.map +1 -1
  89. package/dist/download/single.js +186 -98
  90. package/dist/download/single.js.map +1 -1
  91. package/dist/errors/index.cjs +699 -243
  92. package/dist/errors/index.cjs.map +1 -1
  93. package/dist/errors/index.d.cts +285 -82
  94. package/dist/errors/index.d.cts.map +1 -1
  95. package/dist/errors/index.d.ts +285 -82
  96. package/dist/errors/index.d.ts.map +1 -1
  97. package/dist/errors/index.js +678 -261
  98. package/dist/errors/index.js.map +1 -1
  99. package/dist/http/retry.cjs +45 -28
  100. package/dist/http/retry.cjs.map +1 -1
  101. package/dist/http/retry.d.cts +15 -2
  102. package/dist/http/retry.d.cts.map +1 -1
  103. package/dist/http/retry.d.ts +15 -2
  104. package/dist/http/retry.d.ts.map +1 -1
  105. package/dist/http/retry.js +46 -31
  106. package/dist/http/retry.js.map +1 -1
  107. package/dist/http/transport.cjs +438 -140
  108. package/dist/http/transport.cjs.map +1 -1
  109. package/dist/http/transport.d.cts +21 -2
  110. package/dist/http/transport.d.cts.map +1 -1
  111. package/dist/http/transport.d.ts +21 -2
  112. package/dist/http/transport.d.ts.map +1 -1
  113. package/dist/http/transport.js +437 -140
  114. package/dist/http/transport.js.map +1 -1
  115. package/dist/http/url-guard.cjs +154 -89
  116. package/dist/http/url-guard.cjs.map +1 -1
  117. package/dist/http/url-guard.d.cts +25 -3
  118. package/dist/http/url-guard.d.cts.map +1 -1
  119. package/dist/http/url-guard.d.ts +25 -3
  120. package/dist/http/url-guard.d.ts.map +1 -1
  121. package/dist/http/url-guard.js +152 -90
  122. package/dist/http/url-guard.js.map +1 -1
  123. package/dist/http/user-agent.cjs +84 -44
  124. package/dist/http/user-agent.cjs.map +1 -1
  125. package/dist/http/user-agent.js +84 -46
  126. package/dist/http/user-agent.js.map +1 -1
  127. package/dist/index.cjs +101 -77
  128. package/dist/index.d.cts +27 -21
  129. package/dist/index.d.cts.map +1 -1
  130. package/dist/index.d.ts +27 -21
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +15 -71
  133. package/dist/internal/b2-naming.cjs +66 -0
  134. package/dist/internal/b2-naming.cjs.map +1 -0
  135. package/dist/internal/b2-naming.d.cts +43 -0
  136. package/dist/internal/b2-naming.d.cts.map +1 -0
  137. package/dist/internal/b2-naming.d.ts +43 -0
  138. package/dist/internal/b2-naming.d.ts.map +1 -0
  139. package/dist/internal/b2-naming.js +60 -0
  140. package/dist/internal/b2-naming.js.map +1 -0
  141. package/dist/internal/upload-retry-options.cjs +21 -0
  142. package/dist/internal/upload-retry-options.cjs.map +1 -0
  143. package/dist/internal/upload-retry-options.d.cts +12 -0
  144. package/dist/internal/upload-retry-options.d.cts.map +1 -0
  145. package/dist/internal/upload-retry-options.d.ts +12 -0
  146. package/dist/internal/upload-retry-options.d.ts.map +1 -0
  147. package/dist/internal/upload-retry-options.js +21 -0
  148. package/dist/internal/upload-retry-options.js.map +1 -0
  149. package/dist/internal/url-redaction.cjs +31 -0
  150. package/dist/internal/url-redaction.cjs.map +1 -0
  151. package/dist/internal/url-redaction.d.cts +17 -0
  152. package/dist/internal/url-redaction.d.cts.map +1 -0
  153. package/dist/internal/url-redaction.d.ts +17 -0
  154. package/dist/internal/url-redaction.d.ts.map +1 -0
  155. package/dist/internal/url-redaction.js +31 -0
  156. package/dist/internal/url-redaction.js.map +1 -0
  157. package/dist/notifications/index.cjs +4 -6
  158. package/dist/notifications/index.d.cts +1 -1
  159. package/dist/notifications/index.d.cts.map +1 -1
  160. package/dist/notifications/index.d.ts +1 -1
  161. package/dist/notifications/index.d.ts.map +1 -1
  162. package/dist/notifications/index.js +1 -6
  163. package/dist/notifications/webhook.cjs +195 -85
  164. package/dist/notifications/webhook.cjs.map +1 -1
  165. package/dist/notifications/webhook.d.cts.map +1 -1
  166. package/dist/notifications/webhook.d.ts.map +1 -1
  167. package/dist/notifications/webhook.js +195 -87
  168. package/dist/notifications/webhook.js.map +1 -1
  169. package/dist/object.cjs +253 -210
  170. package/dist/object.cjs.map +1 -1
  171. package/dist/object.d.cts +9 -55
  172. package/dist/object.d.cts.map +1 -1
  173. package/dist/object.d.ts +9 -55
  174. package/dist/object.d.ts.map +1 -1
  175. package/dist/object.js +249 -206
  176. package/dist/object.js.map +1 -1
  177. package/dist/raw/encoding.cjs +74 -35
  178. package/dist/raw/encoding.cjs.map +1 -1
  179. package/dist/raw/encoding.js +74 -38
  180. package/dist/raw/encoding.js.map +1 -1
  181. package/dist/raw/index.cjs +678 -587
  182. package/dist/raw/index.cjs.map +1 -1
  183. package/dist/raw/index.d.cts +121 -18
  184. package/dist/raw/index.d.cts.map +1 -1
  185. package/dist/raw/index.d.ts +121 -18
  186. package/dist/raw/index.d.ts.map +1 -1
  187. package/dist/raw/index.js +674 -589
  188. package/dist/raw/index.js.map +1 -1
  189. package/dist/s3/index.cjs +355 -18
  190. package/dist/s3/index.cjs.map +1 -1
  191. package/dist/s3/index.d.cts +233 -5
  192. package/dist/s3/index.d.cts.map +1 -1
  193. package/dist/s3/index.d.ts +233 -5
  194. package/dist/s3/index.d.ts.map +1 -1
  195. package/dist/s3/index.js +351 -22
  196. package/dist/s3/index.js.map +1 -1
  197. package/dist/s3/sigv4.cjs +149 -0
  198. package/dist/s3/sigv4.cjs.map +1 -0
  199. package/dist/s3/sigv4.d.cts +43 -0
  200. package/dist/s3/sigv4.d.cts.map +1 -0
  201. package/dist/s3/sigv4.d.ts +43 -0
  202. package/dist/s3/sigv4.d.ts.map +1 -0
  203. package/dist/s3/sigv4.js +148 -0
  204. package/dist/s3/sigv4.js.map +1 -0
  205. package/dist/s3/validation.cjs +69 -0
  206. package/dist/s3/validation.cjs.map +1 -0
  207. package/dist/s3/validation.d.cts +43 -0
  208. package/dist/s3/validation.d.cts.map +1 -0
  209. package/dist/s3/validation.d.ts +43 -0
  210. package/dist/s3/validation.d.ts.map +1 -0
  211. package/dist/s3/validation.js +66 -0
  212. package/dist/s3/validation.js.map +1 -0
  213. package/dist/simulator/capabilities.cjs +63 -48
  214. package/dist/simulator/capabilities.cjs.map +1 -1
  215. package/dist/simulator/capabilities.js +63 -49
  216. package/dist/simulator/capabilities.js.map +1 -1
  217. package/dist/simulator/index.cjs +2124 -1548
  218. package/dist/simulator/index.cjs.map +1 -1
  219. package/dist/simulator/index.d.cts +79 -11
  220. package/dist/simulator/index.d.cts.map +1 -1
  221. package/dist/simulator/index.d.ts +79 -11
  222. package/dist/simulator/index.d.ts.map +1 -1
  223. package/dist/simulator/index.js +2112 -1546
  224. package/dist/simulator/index.js.map +1 -1
  225. package/dist/simulator/validation.cjs +191 -153
  226. package/dist/simulator/validation.cjs.map +1 -1
  227. package/dist/simulator/validation.d.cts +3 -21
  228. package/dist/simulator/validation.d.cts.map +1 -1
  229. package/dist/simulator/validation.d.ts +3 -21
  230. package/dist/simulator/validation.d.ts.map +1 -1
  231. package/dist/simulator/validation.js +188 -162
  232. package/dist/simulator/validation.js.map +1 -1
  233. package/dist/streams/collect.cjs +74 -24
  234. package/dist/streams/collect.cjs.map +1 -1
  235. package/dist/streams/collect.d.cts +14 -1
  236. package/dist/streams/collect.d.cts.map +1 -1
  237. package/dist/streams/collect.d.ts +14 -1
  238. package/dist/streams/collect.d.ts.map +1 -1
  239. package/dist/streams/collect.js +74 -25
  240. package/dist/streams/collect.js.map +1 -1
  241. package/dist/streams/file-source.cjs +287 -0
  242. package/dist/streams/file-source.cjs.map +1 -0
  243. package/dist/streams/file-source.d.cts +96 -0
  244. package/dist/streams/file-source.d.cts.map +1 -0
  245. package/dist/streams/file-source.d.ts +96 -0
  246. package/dist/streams/file-source.d.ts.map +1 -0
  247. package/dist/streams/file-source.js +286 -0
  248. package/dist/streams/file-source.js.map +1 -0
  249. package/dist/streams/hash.cjs +207 -115
  250. package/dist/streams/hash.cjs.map +1 -1
  251. package/dist/streams/hash.d.cts +5 -4
  252. package/dist/streams/hash.d.cts.map +1 -1
  253. package/dist/streams/hash.d.ts +5 -4
  254. package/dist/streams/hash.d.ts.map +1 -1
  255. package/dist/streams/hash.js +208 -95
  256. package/dist/streams/hash.js.map +1 -1
  257. package/dist/streams/index.cjs +12 -12
  258. package/dist/streams/index.d.cts +3 -3
  259. package/dist/streams/index.d.cts.map +1 -1
  260. package/dist/streams/index.d.ts +3 -3
  261. package/dist/streams/index.d.ts.map +1 -1
  262. package/dist/streams/index.js +2 -10
  263. package/dist/streams/progress.cjs +60 -46
  264. package/dist/streams/progress.cjs.map +1 -1
  265. package/dist/streams/progress.js +60 -46
  266. package/dist/streams/progress.js.map +1 -1
  267. package/dist/streams/source.cjs +316 -146
  268. package/dist/streams/source.cjs.map +1 -1
  269. package/dist/streams/source.d.cts +56 -18
  270. package/dist/streams/source.d.cts.map +1 -1
  271. package/dist/streams/source.d.ts +56 -18
  272. package/dist/streams/source.d.ts.map +1 -1
  273. package/dist/streams/source.js +312 -149
  274. package/dist/streams/source.js.map +1 -1
  275. package/dist/sync/actions/index.cjs +236 -184
  276. package/dist/sync/actions/index.cjs.map +1 -1
  277. package/dist/sync/actions/index.d.cts +29 -21
  278. package/dist/sync/actions/index.d.cts.map +1 -1
  279. package/dist/sync/actions/index.d.ts +29 -21
  280. package/dist/sync/actions/index.d.ts.map +1 -1
  281. package/dist/sync/actions/index.js +236 -190
  282. package/dist/sync/actions/index.js.map +1 -1
  283. package/dist/sync/b2-sha1-reader.cjs +148 -0
  284. package/dist/sync/b2-sha1-reader.cjs.map +1 -0
  285. package/dist/sync/b2-sha1-reader.d.cts +58 -0
  286. package/dist/sync/b2-sha1-reader.d.cts.map +1 -0
  287. package/dist/sync/b2-sha1-reader.d.ts +58 -0
  288. package/dist/sync/b2-sha1-reader.d.ts.map +1 -0
  289. package/dist/sync/b2-sha1-reader.js +145 -0
  290. package/dist/sync/b2-sha1-reader.js.map +1 -0
  291. package/dist/sync/download-staging.cjs +265 -0
  292. package/dist/sync/download-staging.cjs.map +1 -0
  293. package/dist/sync/download-staging.d.cts +54 -0
  294. package/dist/sync/download-staging.d.cts.map +1 -0
  295. package/dist/sync/download-staging.d.ts +54 -0
  296. package/dist/sync/download-staging.d.ts.map +1 -0
  297. package/dist/sync/download-staging.js +259 -0
  298. package/dist/sync/download-staging.js.map +1 -0
  299. package/dist/sync/filesystem-errors.cjs +32 -0
  300. package/dist/sync/filesystem-errors.cjs.map +1 -0
  301. package/dist/sync/filesystem-errors.d.cts +8 -0
  302. package/dist/sync/filesystem-errors.d.cts.map +1 -0
  303. package/dist/sync/filesystem-errors.d.ts +8 -0
  304. package/dist/sync/filesystem-errors.d.ts.map +1 -0
  305. package/dist/sync/filesystem-errors.js +32 -0
  306. package/dist/sync/filesystem-errors.js.map +1 -0
  307. package/dist/sync/filters.cjs +217 -0
  308. package/dist/sync/filters.cjs.map +1 -0
  309. package/dist/sync/filters.d.cts +51 -0
  310. package/dist/sync/filters.d.cts.map +1 -0
  311. package/dist/sync/filters.d.ts +51 -0
  312. package/dist/sync/filters.d.ts.map +1 -0
  313. package/dist/sync/filters.js +213 -0
  314. package/dist/sync/filters.js.map +1 -0
  315. package/dist/sync/index.cjs +39 -22
  316. package/dist/sync/index.d.cts +14 -9
  317. package/dist/sync/index.d.cts.map +1 -1
  318. package/dist/sync/index.d.ts +14 -9
  319. package/dist/sync/index.d.ts.map +1 -1
  320. package/dist/sync/index.js +9 -20
  321. package/dist/sync/local-file-identity.cjs +61 -0
  322. package/dist/sync/local-file-identity.cjs.map +1 -0
  323. package/dist/sync/local-file-identity.d.cts +37 -0
  324. package/dist/sync/local-file-identity.d.cts.map +1 -0
  325. package/dist/sync/local-file-identity.d.ts +37 -0
  326. package/dist/sync/local-file-identity.d.ts.map +1 -0
  327. package/dist/sync/local-file-identity.js +60 -0
  328. package/dist/sync/local-file-identity.js.map +1 -0
  329. package/dist/sync/local-file-io.cjs +364 -0
  330. package/dist/sync/local-file-io.cjs.map +1 -0
  331. package/dist/sync/local-file-io.d.cts +75 -0
  332. package/dist/sync/local-file-io.d.cts.map +1 -0
  333. package/dist/sync/local-file-io.d.ts +75 -0
  334. package/dist/sync/local-file-io.d.ts.map +1 -0
  335. package/dist/sync/local-file-io.js +360 -0
  336. package/dist/sync/local-file-io.js.map +1 -0
  337. package/dist/sync/local-filesystem-root.cjs +27 -0
  338. package/dist/sync/local-filesystem-root.cjs.map +1 -0
  339. package/dist/sync/local-filesystem-root.d.cts +18 -0
  340. package/dist/sync/local-filesystem-root.d.cts.map +1 -0
  341. package/dist/sync/local-filesystem-root.d.ts +18 -0
  342. package/dist/sync/local-filesystem-root.d.ts.map +1 -0
  343. package/dist/sync/local-filesystem-root.js +26 -0
  344. package/dist/sync/local-filesystem-root.js.map +1 -0
  345. package/dist/sync/local-sha1.cjs +119 -0
  346. package/dist/sync/local-sha1.cjs.map +1 -0
  347. package/dist/sync/local-sha1.d.cts +39 -0
  348. package/dist/sync/local-sha1.d.cts.map +1 -0
  349. package/dist/sync/local-sha1.d.ts +39 -0
  350. package/dist/sync/local-sha1.d.ts.map +1 -0
  351. package/dist/sync/local-sha1.js +117 -0
  352. package/dist/sync/local-sha1.js.map +1 -0
  353. package/dist/sync/pairing.cjs +118 -29
  354. package/dist/sync/pairing.cjs.map +1 -1
  355. package/dist/sync/pairing.d.cts +7 -2
  356. package/dist/sync/pairing.d.cts.map +1 -1
  357. package/dist/sync/pairing.d.ts +7 -2
  358. package/dist/sync/pairing.d.ts.map +1 -1
  359. package/dist/sync/pairing.js +120 -31
  360. package/dist/sync/pairing.js.map +1 -1
  361. package/dist/sync/path-order.cjs +30 -0
  362. package/dist/sync/path-order.cjs.map +1 -0
  363. package/dist/sync/path-order.d.cts +28 -0
  364. package/dist/sync/path-order.d.cts.map +1 -0
  365. package/dist/sync/path-order.d.ts +28 -0
  366. package/dist/sync/path-order.d.ts.map +1 -0
  367. package/dist/sync/path-order.js +29 -0
  368. package/dist/sync/path-order.js.map +1 -0
  369. package/dist/sync/path-safety.cjs +111 -0
  370. package/dist/sync/path-safety.cjs.map +1 -0
  371. package/dist/sync/path-safety.d.cts +78 -0
  372. package/dist/sync/path-safety.d.cts.map +1 -0
  373. package/dist/sync/path-safety.d.ts +78 -0
  374. package/dist/sync/path-safety.d.ts.map +1 -0
  375. package/dist/sync/path-safety.js +105 -0
  376. package/dist/sync/path-safety.js.map +1 -0
  377. package/dist/sync/paths.d.cts +19 -0
  378. package/dist/sync/paths.d.cts.map +1 -0
  379. package/dist/sync/paths.d.ts +19 -0
  380. package/dist/sync/paths.d.ts.map +1 -0
  381. package/dist/sync/policies/compare.cjs +389 -11
  382. package/dist/sync/policies/compare.cjs.map +1 -1
  383. package/dist/sync/policies/compare.d.cts +100 -2
  384. package/dist/sync/policies/compare.d.cts.map +1 -1
  385. package/dist/sync/policies/compare.d.ts +100 -2
  386. package/dist/sync/policies/compare.d.ts.map +1 -1
  387. package/dist/sync/policies/compare.js +387 -13
  388. package/dist/sync/policies/compare.js.map +1 -1
  389. package/dist/sync/policies/index.cjs +76 -65
  390. package/dist/sync/policies/index.cjs.map +1 -1
  391. package/dist/sync/policies/index.d.cts +35 -6
  392. package/dist/sync/policies/index.d.cts.map +1 -1
  393. package/dist/sync/policies/index.d.ts +35 -6
  394. package/dist/sync/policies/index.d.ts.map +1 -1
  395. package/dist/sync/policies/index.js +76 -65
  396. package/dist/sync/policies/index.js.map +1 -1
  397. package/dist/sync/prefix.cjs +96 -0
  398. package/dist/sync/prefix.cjs.map +1 -0
  399. package/dist/sync/prefix.d.cts +55 -0
  400. package/dist/sync/prefix.d.cts.map +1 -0
  401. package/dist/sync/prefix.d.ts +55 -0
  402. package/dist/sync/prefix.d.ts.map +1 -0
  403. package/dist/sync/prefix.js +92 -0
  404. package/dist/sync/prefix.js.map +1 -0
  405. package/dist/sync/regexp-safety.cjs +192 -0
  406. package/dist/sync/regexp-safety.cjs.map +1 -0
  407. package/dist/sync/regexp-safety.d.cts +29 -0
  408. package/dist/sync/regexp-safety.d.cts.map +1 -0
  409. package/dist/sync/regexp-safety.d.ts +29 -0
  410. package/dist/sync/regexp-safety.d.ts.map +1 -0
  411. package/dist/sync/regexp-safety.js +190 -0
  412. package/dist/sync/regexp-safety.js.map +1 -0
  413. package/dist/sync/scan-events.cjs +33 -0
  414. package/dist/sync/scan-events.cjs.map +1 -0
  415. package/dist/sync/scan-events.d.cts +17 -0
  416. package/dist/sync/scan-events.d.cts.map +1 -0
  417. package/dist/sync/scan-events.d.ts +17 -0
  418. package/dist/sync/scan-events.d.ts.map +1 -0
  419. package/dist/sync/scan-events.js +32 -0
  420. package/dist/sync/scan-events.js.map +1 -0
  421. package/dist/sync/scan-limit.cjs +33 -0
  422. package/dist/sync/scan-limit.cjs.map +1 -0
  423. package/dist/sync/scan-limit.d.cts +21 -0
  424. package/dist/sync/scan-limit.d.cts.map +1 -0
  425. package/dist/sync/scan-limit.d.ts +21 -0
  426. package/dist/sync/scan-limit.d.ts.map +1 -0
  427. package/dist/sync/scan-limit.js +31 -0
  428. package/dist/sync/scan-limit.js.map +1 -0
  429. package/dist/sync/scanners/b2.cjs +239 -55
  430. package/dist/sync/scanners/b2.cjs.map +1 -1
  431. package/dist/sync/scanners/b2.d.cts +26 -7
  432. package/dist/sync/scanners/b2.d.cts.map +1 -1
  433. package/dist/sync/scanners/b2.d.ts +26 -7
  434. package/dist/sync/scanners/b2.d.ts.map +1 -1
  435. package/dist/sync/scanners/b2.js +239 -55
  436. package/dist/sync/scanners/b2.js.map +1 -1
  437. package/dist/sync/scanners/local.cjs +215 -56
  438. package/dist/sync/scanners/local.cjs.map +1 -1
  439. package/dist/sync/scanners/local.d.cts +22 -7
  440. package/dist/sync/scanners/local.d.cts.map +1 -1
  441. package/dist/sync/scanners/local.d.ts +22 -7
  442. package/dist/sync/scanners/local.d.ts.map +1 -1
  443. package/dist/sync/scanners/local.js +216 -57
  444. package/dist/sync/scanners/local.js.map +1 -1
  445. package/dist/sync/sha1-metadata.cjs +94 -0
  446. package/dist/sync/sha1-metadata.cjs.map +1 -0
  447. package/dist/sync/sha1-metadata.d.cts +82 -0
  448. package/dist/sync/sha1-metadata.d.cts.map +1 -0
  449. package/dist/sync/sha1-metadata.d.ts +82 -0
  450. package/dist/sync/sha1-metadata.d.ts.map +1 -0
  451. package/dist/sync/sha1-metadata.js +89 -0
  452. package/dist/sync/sha1-metadata.js.map +1 -0
  453. package/dist/sync/sha1-options.cjs +23 -0
  454. package/dist/sync/sha1-options.cjs.map +1 -0
  455. package/dist/sync/sha1-options.d.cts +14 -0
  456. package/dist/sync/sha1-options.d.cts.map +1 -0
  457. package/dist/sync/sha1-options.d.ts +14 -0
  458. package/dist/sync/sha1-options.d.ts.map +1 -0
  459. package/dist/sync/sha1-options.js +21 -0
  460. package/dist/sync/sha1-options.js.map +1 -0
  461. package/dist/sync/synchronizer.cjs +782 -197
  462. package/dist/sync/synchronizer.cjs.map +1 -1
  463. package/dist/sync/synchronizer.d.cts +47 -1
  464. package/dist/sync/synchronizer.d.cts.map +1 -1
  465. package/dist/sync/synchronizer.d.ts +47 -1
  466. package/dist/sync/synchronizer.d.ts.map +1 -1
  467. package/dist/sync/synchronizer.js +779 -173
  468. package/dist/sync/synchronizer.js.map +1 -1
  469. package/dist/sync/types.d.cts +208 -16
  470. package/dist/sync/types.d.cts.map +1 -1
  471. package/dist/sync/types.d.ts +208 -16
  472. package/dist/sync/types.d.ts.map +1 -1
  473. package/dist/types/auth.cjs +76 -56
  474. package/dist/types/auth.cjs.map +1 -1
  475. package/dist/types/auth.d.cts +67 -9
  476. package/dist/types/auth.d.cts.map +1 -1
  477. package/dist/types/auth.d.ts +67 -9
  478. package/dist/types/auth.d.ts.map +1 -1
  479. package/dist/types/auth.js +77 -57
  480. package/dist/types/auth.js.map +1 -1
  481. package/dist/types/bucket.cjs +74 -38
  482. package/dist/types/bucket.cjs.map +1 -1
  483. package/dist/types/bucket.js +75 -41
  484. package/dist/types/bucket.js.map +1 -1
  485. package/dist/types/encryption.cjs +364 -327
  486. package/dist/types/encryption.cjs.map +1 -1
  487. package/dist/types/encryption.d.cts +16 -0
  488. package/dist/types/encryption.d.cts.map +1 -1
  489. package/dist/types/encryption.d.ts +16 -0
  490. package/dist/types/encryption.d.ts.map +1 -1
  491. package/dist/types/encryption.js +364 -310
  492. package/dist/types/encryption.js.map +1 -1
  493. package/dist/types/errors.cjs +47 -0
  494. package/dist/types/errors.cjs.map +1 -0
  495. package/dist/types/errors.d.cts +13 -4
  496. package/dist/types/errors.d.cts.map +1 -1
  497. package/dist/types/errors.d.ts +13 -4
  498. package/dist/types/errors.d.ts.map +1 -1
  499. package/dist/types/errors.js +47 -0
  500. package/dist/types/errors.js.map +1 -0
  501. package/dist/types/file.cjs +36 -19
  502. package/dist/types/file.cjs.map +1 -1
  503. package/dist/types/file.d.cts +2 -2
  504. package/dist/types/file.d.cts.map +1 -1
  505. package/dist/types/file.d.ts +2 -2
  506. package/dist/types/file.d.ts.map +1 -1
  507. package/dist/types/file.js +37 -21
  508. package/dist/types/file.js.map +1 -1
  509. package/dist/types/ids.cjs +53 -9
  510. package/dist/types/ids.cjs.map +1 -1
  511. package/dist/types/ids.js +54 -15
  512. package/dist/types/ids.js.map +1 -1
  513. package/dist/types/index.d.cts +12 -11
  514. package/dist/types/index.d.cts.map +1 -1
  515. package/dist/types/index.d.ts +12 -11
  516. package/dist/types/index.d.ts.map +1 -1
  517. package/dist/types/key.d.cts +44 -8
  518. package/dist/types/key.d.cts.map +1 -1
  519. package/dist/types/key.d.ts +44 -8
  520. package/dist/types/key.d.ts.map +1 -1
  521. package/dist/types/lock.cjs +33 -13
  522. package/dist/types/lock.cjs.map +1 -1
  523. package/dist/types/lock.js +34 -15
  524. package/dist/types/lock.js.map +1 -1
  525. package/dist/types/notifications.cjs +44 -22
  526. package/dist/types/notifications.cjs.map +1 -1
  527. package/dist/types/notifications.js +45 -23
  528. package/dist/types/notifications.js.map +1 -1
  529. package/dist/types/upload.d.cts +39 -5
  530. package/dist/types/upload.d.cts.map +1 -1
  531. package/dist/types/upload.d.ts +39 -5
  532. package/dist/types/upload.d.ts.map +1 -1
  533. package/dist/upload/abort-scope.cjs +91 -0
  534. package/dist/upload/abort-scope.cjs.map +1 -0
  535. package/dist/upload/abort-scope.d.cts +48 -0
  536. package/dist/upload/abort-scope.d.cts.map +1 -0
  537. package/dist/upload/abort-scope.d.ts +48 -0
  538. package/dist/upload/abort-scope.d.ts.map +1 -0
  539. package/dist/upload/abort-scope.js +88 -0
  540. package/dist/upload/abort-scope.js.map +1 -0
  541. package/dist/upload/cancel.cjs +183 -8
  542. package/dist/upload/cancel.cjs.map +1 -1
  543. package/dist/upload/cancel.d.cts +110 -2
  544. package/dist/upload/cancel.d.cts.map +1 -1
  545. package/dist/upload/cancel.d.ts +110 -2
  546. package/dist/upload/cancel.d.ts.map +1 -1
  547. package/dist/upload/cancel.js +178 -9
  548. package/dist/upload/cancel.js.map +1 -1
  549. package/dist/upload/concurrency.cjs +79 -52
  550. package/dist/upload/concurrency.cjs.map +1 -1
  551. package/dist/upload/concurrency.js +79 -53
  552. package/dist/upload/concurrency.js.map +1 -1
  553. package/dist/upload/finish.cjs +59 -0
  554. package/dist/upload/finish.cjs.map +1 -0
  555. package/dist/upload/finish.d.cts +26 -0
  556. package/dist/upload/finish.d.cts.map +1 -0
  557. package/dist/upload/finish.d.ts +26 -0
  558. package/dist/upload/finish.d.ts.map +1 -0
  559. package/dist/upload/finish.js +59 -0
  560. package/dist/upload/finish.js.map +1 -0
  561. package/dist/upload/large.cjs +301 -218
  562. package/dist/upload/large.cjs.map +1 -1
  563. package/dist/upload/large.d.cts +76 -9
  564. package/dist/upload/large.d.cts.map +1 -1
  565. package/dist/upload/large.d.ts +76 -9
  566. package/dist/upload/large.d.ts.map +1 -1
  567. package/dist/upload/large.js +301 -218
  568. package/dist/upload/large.js.map +1 -1
  569. package/dist/upload/options.cjs +28 -0
  570. package/dist/upload/options.cjs.map +1 -0
  571. package/dist/upload/options.d.cts +104 -0
  572. package/dist/upload/options.d.cts.map +1 -0
  573. package/dist/upload/options.d.ts +104 -0
  574. package/dist/upload/options.d.ts.map +1 -0
  575. package/dist/upload/options.js +27 -0
  576. package/dist/upload/options.js.map +1 -0
  577. package/dist/upload/resume.cjs +333 -33
  578. package/dist/upload/resume.cjs.map +1 -1
  579. package/dist/upload/resume.d.cts +82 -12
  580. package/dist/upload/resume.d.cts.map +1 -1
  581. package/dist/upload/resume.d.ts +82 -12
  582. package/dist/upload/resume.d.ts.map +1 -1
  583. package/dist/upload/resume.js +330 -33
  584. package/dist/upload/resume.js.map +1 -1
  585. package/dist/upload/retry.cjs +186 -0
  586. package/dist/upload/retry.cjs.map +1 -0
  587. package/dist/upload/retry.d.cts +127 -0
  588. package/dist/upload/retry.d.cts.map +1 -0
  589. package/dist/upload/retry.d.ts +127 -0
  590. package/dist/upload/retry.d.ts.map +1 -0
  591. package/dist/upload/retry.js +182 -0
  592. package/dist/upload/retry.js.map +1 -0
  593. package/dist/upload/single.cjs +68 -44
  594. package/dist/upload/single.cjs.map +1 -1
  595. package/dist/upload/single.d.cts +2 -1
  596. package/dist/upload/single.d.cts.map +1 -1
  597. package/dist/upload/single.d.ts +2 -1
  598. package/dist/upload/single.d.ts.map +1 -1
  599. package/dist/upload/single.js +68 -44
  600. package/dist/upload/single.js.map +1 -1
  601. package/dist/upload/stream.cjs +317 -193
  602. package/dist/upload/stream.cjs.map +1 -1
  603. package/dist/upload/stream.d.cts +3 -1
  604. package/dist/upload/stream.d.cts.map +1 -1
  605. package/dist/upload/stream.d.ts +3 -1
  606. package/dist/upload/stream.d.ts.map +1 -1
  607. package/dist/upload/stream.js +316 -192
  608. package/dist/upload/stream.js.map +1 -1
  609. package/dist/util/best-effort.cjs +42 -8
  610. package/dist/util/best-effort.cjs.map +1 -1
  611. package/dist/util/best-effort.d.cts +2 -1
  612. package/dist/util/best-effort.d.cts.map +1 -1
  613. package/dist/util/best-effort.d.ts +2 -1
  614. package/dist/util/best-effort.d.ts.map +1 -1
  615. package/dist/util/best-effort.js +43 -9
  616. package/dist/util/best-effort.js.map +1 -1
  617. package/dist/util/bytes.cjs +23 -0
  618. package/dist/util/bytes.cjs.map +1 -0
  619. package/dist/util/bytes.d.cts +15 -0
  620. package/dist/util/bytes.d.cts.map +1 -0
  621. package/dist/util/bytes.d.ts +15 -0
  622. package/dist/util/bytes.d.ts.map +1 -0
  623. package/dist/util/bytes.js +23 -0
  624. package/dist/util/bytes.js.map +1 -0
  625. package/dist/util/crypto.cjs +68 -0
  626. package/dist/util/crypto.cjs.map +1 -0
  627. package/dist/util/crypto.d.cts +26 -0
  628. package/dist/util/crypto.d.cts.map +1 -0
  629. package/dist/util/crypto.d.ts +26 -0
  630. package/dist/util/crypto.d.ts.map +1 -0
  631. package/dist/util/crypto.js +66 -0
  632. package/dist/util/crypto.js.map +1 -0
  633. package/dist/util/defaults.cjs +25 -9
  634. package/dist/util/defaults.cjs.map +1 -1
  635. package/dist/util/defaults.js +26 -11
  636. package/dist/util/defaults.js.map +1 -1
  637. package/dist/util/error-reason.cjs +41 -0
  638. package/dist/util/error-reason.cjs.map +1 -0
  639. package/dist/util/error-reason.d.cts +9 -0
  640. package/dist/util/error-reason.d.cts.map +1 -0
  641. package/dist/util/error-reason.d.ts +9 -0
  642. package/dist/util/error-reason.d.ts.map +1 -0
  643. package/dist/util/error-reason.js +41 -0
  644. package/dist/util/error-reason.js.map +1 -0
  645. package/dist/util/http.cjs +23 -0
  646. package/dist/util/http.cjs.map +1 -0
  647. package/dist/util/http.d.cts +13 -0
  648. package/dist/util/http.d.cts.map +1 -0
  649. package/dist/util/http.d.ts +13 -0
  650. package/dist/util/http.d.ts.map +1 -0
  651. package/dist/util/http.js +23 -0
  652. package/dist/util/http.js.map +1 -0
  653. package/dist/util/normalize.cjs +66 -7
  654. package/dist/util/normalize.cjs.map +1 -1
  655. package/dist/util/normalize.js +67 -10
  656. package/dist/util/normalize.js.map +1 -1
  657. package/dist/util/paginator.cjs +63 -14
  658. package/dist/util/paginator.cjs.map +1 -1
  659. package/dist/util/paginator.js +64 -16
  660. package/dist/util/paginator.js.map +1 -1
  661. package/dist/util/plan-ranges.cjs +47 -22
  662. package/dist/util/plan-ranges.cjs.map +1 -1
  663. package/dist/util/plan-ranges.js +48 -24
  664. package/dist/util/plan-ranges.js.map +1 -1
  665. package/dist/util/sha1.cjs +27 -0
  666. package/dist/util/sha1.cjs.map +1 -0
  667. package/dist/util/sha1.d.cts +17 -0
  668. package/dist/util/sha1.d.cts.map +1 -0
  669. package/dist/util/sha1.d.ts +17 -0
  670. package/dist/util/sha1.d.ts.map +1 -0
  671. package/dist/util/sha1.js +26 -0
  672. package/dist/util/sha1.js.map +1 -0
  673. package/dist/util/text-codec.cjs +29 -5
  674. package/dist/util/text-codec.cjs.map +1 -1
  675. package/dist/util/text-codec.js +30 -7
  676. package/dist/util/text-codec.js.map +1 -1
  677. package/dist/util/to-error.cjs +18 -4
  678. package/dist/util/to-error.cjs.map +1 -1
  679. package/dist/util/to-error.js +19 -5
  680. package/dist/util/to-error.js.map +1 -1
  681. package/dist/version.cjs +17 -5
  682. package/dist/version.cjs.map +1 -1
  683. package/dist/version.d.cts +3 -3
  684. package/dist/version.d.ts +3 -3
  685. package/dist/version.js +19 -6
  686. package/dist/version.js.map +1 -1
  687. package/package.json +19 -16
  688. package/dist/auth/index.cjs.map +0 -1
  689. package/dist/auth/index.js.map +0 -1
  690. package/dist/index.cjs.map +0 -1
  691. package/dist/index.js.map +0 -1
  692. package/dist/notifications/index.cjs.map +0 -1
  693. package/dist/notifications/index.js.map +0 -1
  694. package/dist/package.json.cjs +0 -9
  695. package/dist/package.json.cjs.map +0 -1
  696. package/dist/package.json.js +0 -9
  697. package/dist/package.json.js.map +0 -1
  698. package/dist/streams/index.cjs.map +0 -1
  699. package/dist/streams/index.js.map +0 -1
  700. package/dist/sync/index.cjs.map +0 -1
  701. package/dist/sync/index.js.map +0 -1
@@ -1,6 +1,81 @@
1
1
  import { AccountInfo } from '../auth/account-info.js';
2
+ import { ResumeFileIdMismatchError } from '../errors/index.js';
2
3
  import { RawClient } from '../raw/index.js';
4
+ import { BucketRetentionPolicy } from '../types/bucket.js';
5
+ import { EncryptionSetting } from '../types/encryption.js';
3
6
  import { BucketId, LargeFileId } from '../types/ids.js';
7
+ import { FileRetentionValue, LegalHoldValue } from '../types/lock.js';
8
+ export { ResumeFileIdMismatchError };
9
+ /** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */
10
+ export declare const RESUME_SOURCE_SIZE_INFO_KEY = "b2_sdk_resume_source_size";
11
+ /** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */
12
+ export declare const RESUME_PART_SIZE_INFO_KEY = "b2_sdk_resume_part_size";
13
+ /** One planned part from the local upload source. */
14
+ export interface ResumePartPlan {
15
+ /** 1-based B2 part number. */
16
+ readonly partNumber: number;
17
+ /** Expected byte length for this part. */
18
+ readonly length: number;
19
+ }
20
+ /** Reason an unfinished same-name large file was not reused for resume. */
21
+ export type ResumeCandidateRejectedReason = 'search-truncated' | 'candidate-limit' | 'file-name-mismatch' | 'content-type-mismatch' | 'file-info-mismatch' | 'source-size-mismatch' | 'part-size-mismatch' | 'encryption-mismatch' | 'sse-c-unsupported' | 'retention-mismatch' | 'legal-hold-mismatch' | 'part-length-mismatch';
22
+ /** Diagnostic event emitted when resume discovery declines a candidate. */
23
+ export interface ResumeCandidateRejectedEvent {
24
+ /** ID of the unfinished large file, when the event is candidate-specific. */
25
+ readonly fileId?: LargeFileId;
26
+ /** Requested destination file name. */
27
+ readonly requestedFileName: string;
28
+ /** Actual candidate file name, when the event is candidate-specific. */
29
+ readonly candidateFileName?: string;
30
+ /** Machine-readable rejection reason. */
31
+ readonly reason: ResumeCandidateRejectedReason;
32
+ }
33
+ /** Diagnostic callback for declined resume candidates. */
34
+ export type ResumeCandidateRejectedListener = (event: ResumeCandidateRejectedEvent) => void;
35
+ /** Compatibility requirements an unfinished large file must satisfy before reuse. */
36
+ export interface ResumeCandidateCriteria {
37
+ /** Effective MIME type for the upload, including SDK defaults. */
38
+ readonly contentType: string;
39
+ /** Caller-owned file info. Legacy SDK resume keys on candidates are ignored separately. */
40
+ readonly fileInfo: Record<string, string>;
41
+ /** Source size in bytes, checked against legacy SDK metadata when a candidate carries it. */
42
+ readonly sourceSize: number;
43
+ /** Effective multipart part size, checked against legacy SDK metadata when present. */
44
+ readonly partSize: number;
45
+ /** Planned local parts used to verify already-uploaded server part lengths. */
46
+ readonly parts: readonly ResumePartPlan[];
47
+ /** Explicit server-side encryption option, if configured by the caller. */
48
+ readonly serverSideEncryption?: EncryptionSetting;
49
+ /** Explicit Object Lock retention option, if configured by the caller. */
50
+ readonly fileRetention?: FileRetentionValue;
51
+ /** Effective readable bucket default retention when the caller omits fileRetention. */
52
+ readonly defaultFileRetention?: BucketRetentionPolicy;
53
+ /** Whether bucket default retention exists but cannot be read by the caller. */
54
+ readonly defaultFileRetentionUnreadable?: boolean;
55
+ /** Explicit legal hold option, if configured by the caller. */
56
+ readonly legalHold?: LegalHoldValue;
57
+ /** Explicit unfinished large-file ID to verify before reuse. */
58
+ readonly resumeFileId?: LargeFileId;
59
+ /** Abort signal used for B2 list requests and checked between pages. */
60
+ readonly signal?: AbortSignal;
61
+ /** Optional diagnostic callback for candidates that are found but not reused. */
62
+ readonly onCandidateRejected?: ResumeCandidateRejectedListener;
63
+ /** Maximum `b2_list_unfinished_large_files` pages to inspect. */
64
+ readonly maxListPages?: number;
65
+ /** Maximum metadata-compatible candidates whose parts may be listed. */
66
+ readonly maxPartCandidates?: number;
67
+ /** Maximum `b2_list_parts` pages to inspect for each metadata-compatible candidate. */
68
+ readonly maxPartPages?: number;
69
+ /** Caller-supplied aggregate resume discovery timeout. */
70
+ readonly discoveryTimeoutMs?: number;
71
+ }
72
+ /** Uploaded part metadata used by the resume planner. */
73
+ export interface ResumePartInfo {
74
+ /** SHA-1 stored by B2 for this uploaded part. */
75
+ readonly contentSha1: string;
76
+ /** Byte length stored by B2 for this uploaded part. */
77
+ readonly contentLength: number;
78
+ }
4
79
  /** Information about an unfinished large file eligible for resume. */
5
80
  export interface ResumeCandidate {
6
81
  /** ID of the unfinished large file. */
@@ -10,24 +85,19 @@ export interface ResumeCandidate {
10
85
  }
11
86
  /**
12
87
  * Finds an unfinished large file matching the given bucket and file name.
13
- * Returns `null` when no matching candidate exists.
88
+ * Returns `null` when no compatible candidate exists.
89
+ *
90
+ * With criteria, the newest compatible candidate is selected; incompatible
91
+ * same-name uploads are ignored and optionally reported via
92
+ * `onCandidateRejected`.
14
93
  *
15
94
  * @param raw - Low-level B2 API client.
16
95
  * @param accountInfo - Authorized account state.
17
96
  * @param bucketId - Target bucket of the upload.
18
97
  * @param fileName - Destination file name of the upload.
98
+ * @param criteria - Upload identity and option checks.
19
99
  *
20
100
  * @returns A {@link ResumeCandidate} describing the candidate and its uploaded parts, or `null`.
21
101
  */
22
- export declare function findResumeCandidate(raw: RawClient, accountInfo: AccountInfo, bucketId: BucketId, fileName: string): Promise<ResumeCandidate | null>;
23
- /**
24
- * Lists all uploaded parts for a large file, paginating until exhausted.
25
- *
26
- * @param raw - Low-level B2 API client.
27
- * @param accountInfo - Authorized account state.
28
- * @param fileId - ID of the large file to inspect.
29
- *
30
- * @returns A map from 1-based part number to its server-stored SHA-1.
31
- */
32
- export declare function collectPartSha1s(raw: RawClient, accountInfo: AccountInfo, fileId: LargeFileId): Promise<Map<number, string>>;
102
+ export declare function findResumeCandidate(raw: RawClient, accountInfo: AccountInfo, bucketId: BucketId, fileName: string, criteria: ResumeCandidateCriteria): Promise<ResumeCandidate | null>;
33
103
  //# sourceMappingURL=resume.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../src/upload/resume.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG5D,sEAAsE;AACtE,MAAM,WAAW,eAAe;IAC9B,uCAAuC;IACvC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,iBAAiB,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACxD;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAcjC;AAED;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAiB9B"}
1
+ {"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../src/upload/resume.js"],"names":[],"mappings":"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"}
@@ -1,34 +1,331 @@
1
1
  import { largeFileId } from "../types/ids.js";
2
- async function findResumeCandidate(raw, accountInfo, bucketId, fileName) {
3
- const unfinished = await raw.listUnfinishedLargeFiles(
4
- accountInfo.getApiUrl(),
5
- accountInfo.getAuthToken(),
6
- { bucketId }
7
- );
8
- const match = unfinished.files.find((f) => f.fileName === fileName);
9
- if (!match) return null;
10
- const fileId = largeFileId(match.fileId);
11
- const uploadedPartSha1s = await collectPartSha1s(raw, accountInfo, fileId);
12
- return { fileId, uploadedPartSha1s };
13
- }
14
- async function collectPartSha1s(raw, accountInfo, fileId) {
15
- const sha1s = /* @__PURE__ */ new Map();
16
- let startPartNumber;
17
- while (true) {
18
- const page = await raw.listParts(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
19
- fileId,
20
- ...startPartNumber !== void 0 ? { startPartNumber } : {}
21
- });
22
- for (const part of page.parts) {
23
- sha1s.set(part.partNumber, part.contentSha1);
24
- }
25
- if (page.nextPartNumber === null) break;
26
- startPartNumber = page.nextPartNumber;
27
- }
28
- return sha1s;
29
- }
30
- export {
31
- collectPartSha1s,
32
- findResumeCandidate
33
- };
34
- //# sourceMappingURL=resume.js.map
2
+ import { ResumeFileIdMismatchError } from "../errors/index.js";
3
+ import { BucketRetentionMode } from "../types/bucket.js";
4
+ import { EncryptionMode } from "../types/encryption.js";
5
+ //#region src/upload/resume.ts
6
+ /** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */
7
+ var RESUME_SOURCE_SIZE_INFO_KEY = "b2_sdk_resume_source_size";
8
+ /** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */
9
+ var RESUME_PART_SIZE_INFO_KEY = "b2_sdk_resume_part_size";
10
+ var DEFAULT_MAX_RESUME_LIST_PAGES = 10;
11
+ var DEFAULT_MAX_RESUME_PART_CANDIDATES = 25;
12
+ var DEFAULT_MAX_RESUME_PART_PAGES = 10;
13
+ var LIST_PARTS_PAGE_SIZE = 100;
14
+ /**
15
+ * Finds an unfinished large file matching the given bucket and file name.
16
+ * Returns `null` when no compatible candidate exists.
17
+ *
18
+ * With criteria, the newest compatible candidate is selected; incompatible
19
+ * same-name uploads are ignored and optionally reported via
20
+ * `onCandidateRejected`.
21
+ *
22
+ * @param raw - Low-level B2 API client.
23
+ * @param accountInfo - Authorized account state.
24
+ * @param bucketId - Target bucket of the upload.
25
+ * @param fileName - Destination file name of the upload.
26
+ * @param criteria - Upload identity and option checks.
27
+ *
28
+ * @returns A {@link ResumeCandidate} describing the candidate and its uploaded parts, or `null`.
29
+ */
30
+ async function findResumeCandidate(raw, accountInfo, bucketId, fileName, criteria) {
31
+ const discoverySignal = createResumeDiscoverySignal(criteria);
32
+ try {
33
+ return await findResumeCandidateWithSignal(raw, accountInfo, bucketId, fileName, criteria, discoverySignal.signal);
34
+ } finally {
35
+ discoverySignal.dispose();
36
+ }
37
+ }
38
+ async function findResumeCandidateWithSignal(raw, accountInfo, bucketId, fileName, criteria, signal) {
39
+ const matches = [];
40
+ const maxListPages = criteria.maxListPages ?? DEFAULT_MAX_RESUME_LIST_PAGES;
41
+ const maxPartCandidates = criteria.maxPartCandidates ?? DEFAULT_MAX_RESUME_PART_CANDIDATES;
42
+ let sequence = 0;
43
+ let pageCount = 0;
44
+ const explicitResumeFileId = criteria.resumeFileId;
45
+ let startFileId = explicitResumeFileId;
46
+ let truncated = false;
47
+ while (pageCount < maxListPages) {
48
+ signal?.throwIfAborted();
49
+ const unfinished = await abortableRequest(raw.listUnfinishedLargeFiles(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
50
+ bucketId,
51
+ maxFileCount: explicitResumeFileId !== void 0 ? 1 : 100,
52
+ namePrefix: fileName,
53
+ ...startFileId !== void 0 ? { startFileId } : {}
54
+ }, signal !== void 0 ? { signal } : void 0), signal);
55
+ pageCount++;
56
+ for (const file of unfinished.files) {
57
+ if (explicitResumeFileId !== void 0 ? file.fileId === explicitResumeFileId : file.fileName === fileName) matches.push({
58
+ file,
59
+ sequence
60
+ });
61
+ sequence++;
62
+ }
63
+ if (explicitResumeFileId !== void 0) break;
64
+ if (unfinished.nextFileId === null) break;
65
+ startFileId = unfinished.nextFileId;
66
+ truncated = pageCount >= maxListPages;
67
+ }
68
+ if (truncated) emitCandidateRejected(criteria, {
69
+ requestedFileName: fileName,
70
+ reason: "search-truncated"
71
+ });
72
+ matches.sort(compareNewestFirst);
73
+ let partCandidatesInspected = 0;
74
+ for (const match of matches) {
75
+ signal?.throwIfAborted();
76
+ const rejection = candidateMetadataRejectReason(match.file, fileName, criteria);
77
+ if (rejection !== null) {
78
+ notifyCandidateRejected(criteria, match.file, fileName, rejection);
79
+ continue;
80
+ }
81
+ if (partCandidatesInspected >= maxPartCandidates) {
82
+ notifyCandidateRejected(criteria, match.file, fileName, "candidate-limit");
83
+ break;
84
+ }
85
+ partCandidatesInspected++;
86
+ const fileId = largeFileId(match.file.fileId);
87
+ const uploadedPartsResult = await collectResumePartInfo(raw, accountInfo, fileId, {
88
+ maxPages: criteria.maxPartPages ?? DEFAULT_MAX_RESUME_PART_PAGES,
89
+ maxParts: criteria.parts.length,
90
+ ...signal !== void 0 ? { signal } : {}
91
+ });
92
+ const uploadedParts = uploadedPartsResult.parts;
93
+ if (uploadedPartsResult.truncated || !uploadedPartsMatchPlan(uploadedParts, criteria.parts)) {
94
+ notifyCandidateRejected(criteria, match.file, fileName, "part-length-mismatch");
95
+ continue;
96
+ }
97
+ return {
98
+ fileId,
99
+ uploadedPartSha1s: partInfoToSha1s(uploadedParts)
100
+ };
101
+ }
102
+ return null;
103
+ }
104
+ async function collectResumePartInfo(raw, accountInfo, fileId, options) {
105
+ const parts = /* @__PURE__ */ new Map();
106
+ const maxPages = options.maxPages ?? Number.POSITIVE_INFINITY;
107
+ const maxParts = options.maxParts ?? Number.POSITIVE_INFINITY;
108
+ let startPartNumber;
109
+ let pageCount = 0;
110
+ while (pageCount < maxPages) {
111
+ options.signal?.throwIfAborted();
112
+ const remainingParts = maxParts === Number.POSITIVE_INFINITY ? void 0 : Math.max(1, Math.min(LIST_PARTS_PAGE_SIZE, maxParts - parts.size + 1));
113
+ const page = await abortableRequest(raw.listParts(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
114
+ fileId,
115
+ ...startPartNumber !== void 0 ? { startPartNumber } : {},
116
+ ...remainingParts !== void 0 ? { maxPartCount: remainingParts } : {}
117
+ }, options.signal !== void 0 ? { signal: options.signal } : void 0), options.signal);
118
+ pageCount++;
119
+ for (const part of page.parts) {
120
+ parts.set(part.partNumber, {
121
+ contentSha1: part.contentSha1,
122
+ contentLength: part.contentLength
123
+ });
124
+ if (parts.size > maxParts) return {
125
+ parts,
126
+ truncated: true
127
+ };
128
+ }
129
+ if (page.nextPartNumber === null) return {
130
+ parts,
131
+ truncated: false
132
+ };
133
+ assertAdvancingPartCursor(fileId, startPartNumber, page.nextPartNumber);
134
+ startPartNumber = page.nextPartNumber;
135
+ }
136
+ return {
137
+ parts,
138
+ truncated: true
139
+ };
140
+ }
141
+ function compareNewestFirst(a, b) {
142
+ const aTime = a.file.uploadTimestamp ?? Number.NEGATIVE_INFINITY;
143
+ const bTime = b.file.uploadTimestamp ?? Number.NEGATIVE_INFINITY;
144
+ if (aTime !== bTime) return bTime - aTime;
145
+ return b.sequence - a.sequence;
146
+ }
147
+ function candidateMetadataRejectReason(candidate, fileName, criteria) {
148
+ if (candidate.fileName !== fileName) return "file-name-mismatch";
149
+ if (criteria.contentType === "b2/x-auto" && criteria.resumeFileId === void 0 && candidate.contentType !== "b2/x-auto") return "content-type-mismatch";
150
+ if (criteria.contentType !== "b2/x-auto" && candidate.contentType !== criteria.contentType) return "content-type-mismatch";
151
+ const candidateInfo = splitResumeFileInfo(candidate.fileInfo ?? {});
152
+ if (!recordEquals(candidateInfo.fileInfo, criteria.fileInfo)) return "file-info-mismatch";
153
+ if (candidateInfo.sourceSize !== void 0 && candidateInfo.sourceSize !== String(criteria.sourceSize)) return "source-size-mismatch";
154
+ if (candidateInfo.partSize !== void 0 && candidateInfo.partSize !== String(criteria.partSize)) return "part-size-mismatch";
155
+ const encryptionRejectReason = serverSideEncryptionRejectReason(candidate.serverSideEncryption, criteria.serverSideEncryption);
156
+ if (encryptionRejectReason !== null) return encryptionRejectReason;
157
+ if (!fileRetentionMatches(candidate.fileRetention, criteria.fileRetention, criteria.defaultFileRetention, criteria.defaultFileRetentionUnreadable === true, candidate.uploadTimestamp)) return "retention-mismatch";
158
+ if (!legalHoldMatches(candidate.legalHold, criteria.legalHold)) return "legal-hold-mismatch";
159
+ return null;
160
+ }
161
+ function notifyCandidateRejected(criteria, candidate, requestedFileName, reason) {
162
+ emitCandidateRejected(criteria, {
163
+ fileId: largeFileId(candidate.fileId),
164
+ requestedFileName,
165
+ candidateFileName: candidate.fileName,
166
+ reason
167
+ });
168
+ }
169
+ function emitCandidateRejected(criteria, event) {
170
+ try {
171
+ criteria.onCandidateRejected?.(event);
172
+ } catch {}
173
+ }
174
+ function uploadedPartsMatchPlan(uploadedParts, plans) {
175
+ for (const [partNumber, part] of uploadedParts) {
176
+ const planned = plans[partNumber - 1];
177
+ if (planned === void 0) return false;
178
+ if (planned.partNumber !== partNumber) return false;
179
+ if (planned.length !== part.contentLength) return false;
180
+ }
181
+ return true;
182
+ }
183
+ function partInfoToSha1s(parts) {
184
+ const sha1s = /* @__PURE__ */ new Map();
185
+ for (const [partNumber, part] of parts) sha1s.set(partNumber, part.contentSha1);
186
+ return sha1s;
187
+ }
188
+ function recordEquals(a, b) {
189
+ const aKeys = Object.keys(a);
190
+ const bKeys = Object.keys(b);
191
+ if (aKeys.length !== bKeys.length) return false;
192
+ for (const key of aKeys) if (a[key] !== b[key]) return false;
193
+ return true;
194
+ }
195
+ function splitResumeFileInfo(fileInfo) {
196
+ const userFileInfo = Object.create(null);
197
+ let sourceSize;
198
+ let partSize;
199
+ for (const [key, value] of Object.entries(fileInfo)) if (key === "b2_sdk_resume_source_size") sourceSize = value;
200
+ else if (key === "b2_sdk_resume_part_size") partSize = value;
201
+ else userFileInfo[key] = value;
202
+ return {
203
+ fileInfo: userFileInfo,
204
+ ...sourceSize !== void 0 ? { sourceSize } : {},
205
+ ...partSize !== void 0 ? { partSize } : {}
206
+ };
207
+ }
208
+ function fileRetentionMatches(candidate, expected, defaultExpected, defaultUnreadable, uploadTimestamp) {
209
+ if (expected === void 0 && defaultUnreadable) return false;
210
+ if (expected === void 0 && defaultExpected !== void 0) {
211
+ if (defaultExpected.mode === BucketRetentionMode.None) {
212
+ if (candidate === void 0) return true;
213
+ if (!candidate.isClientAuthorizedToRead) return false;
214
+ return fileRetentionValueEquals(candidate.value, null);
215
+ }
216
+ if (candidate === void 0 || !candidate.isClientAuthorizedToRead) return false;
217
+ return fileRetentionValueMatchesBucketDefault(candidate.value, defaultExpected, uploadTimestamp);
218
+ }
219
+ if (expected === void 0) {
220
+ if (candidate === void 0) return true;
221
+ if (!candidate.isClientAuthorizedToRead) return false;
222
+ return fileRetentionValueEquals(candidate.value, null);
223
+ }
224
+ if (candidate === void 0 || !candidate.isClientAuthorizedToRead) return false;
225
+ return fileRetentionValueEquals(candidate.value, expected);
226
+ }
227
+ function fileRetentionValueMatchesBucketDefault(candidate, expected, uploadTimestamp) {
228
+ if (expected.period === null) return false;
229
+ if (candidate?.mode !== expected.mode || candidate.retainUntilTimestamp === null) return false;
230
+ if (uploadTimestamp === void 0) return false;
231
+ return candidate.retainUntilTimestamp === uploadTimestamp + retentionPeriodMillis(expected.period);
232
+ }
233
+ function retentionPeriodMillis(period) {
234
+ if (period === null) return 0;
235
+ return (period.unit === "days" ? period.duration : period.duration * 365) * 24 * 60 * 60 * 1e3;
236
+ }
237
+ function fileRetentionValueEquals(a, b) {
238
+ return (a?.mode ?? null) === (b?.mode ?? null) && (a?.retainUntilTimestamp ?? null) === (b?.retainUntilTimestamp ?? null);
239
+ }
240
+ function legalHoldMatches(candidate, expected) {
241
+ if (expected === void 0) {
242
+ if (candidate === void 0) return true;
243
+ if (!candidate.isClientAuthorizedToRead) return false;
244
+ return candidate.value === null || candidate.value === "off";
245
+ }
246
+ if (candidate === void 0 || !candidate.isClientAuthorizedToRead) return false;
247
+ return candidate.value === expected;
248
+ }
249
+ function createResumeDiscoverySignal(criteria) {
250
+ if (criteria.signal !== void 0) return {
251
+ signal: criteria.signal,
252
+ dispose() {}
253
+ };
254
+ if (criteria.discoveryTimeoutMs === void 0) return { dispose() {} };
255
+ const timeoutMs = criteria.discoveryTimeoutMs;
256
+ if (timeoutMs === Number.POSITIVE_INFINITY) return { dispose() {} };
257
+ const controller = new AbortController();
258
+ const timeout = setTimeout(() => {
259
+ controller.abort(resumeDiscoveryTimeoutReason(timeoutMs));
260
+ }, Math.max(0, timeoutMs));
261
+ return {
262
+ signal: controller.signal,
263
+ dispose() {
264
+ clearTimeout(timeout);
265
+ }
266
+ };
267
+ }
268
+ async function abortableRequest(request, signal) {
269
+ if (signal === void 0) return request;
270
+ if (signal.aborted) throw resumeAbortReason(signal);
271
+ let removeAbortListener;
272
+ const aborted = new Promise((_resolve, reject) => {
273
+ const onAbort = () => reject(resumeAbortReason(signal));
274
+ signal.addEventListener("abort", onAbort, { once: true });
275
+ removeAbortListener = () => signal.removeEventListener("abort", onAbort);
276
+ });
277
+ try {
278
+ return await Promise.race([request, aborted]);
279
+ } finally {
280
+ removeAbortListener?.();
281
+ request.catch(() => {});
282
+ }
283
+ }
284
+ function resumeAbortReason(signal) {
285
+ return signal.reason ?? resumeAbortFallbackReason();
286
+ }
287
+ function resumeAbortFallbackReason() {
288
+ if (typeof DOMException === "function") return new DOMException("Resume discovery aborted", "AbortError");
289
+ const error = /* @__PURE__ */ new Error("Resume discovery aborted");
290
+ error.name = "AbortError";
291
+ return error;
292
+ }
293
+ function resumeDiscoveryTimeoutReason(timeoutMs) {
294
+ if (typeof DOMException === "function") return new DOMException(`Resume discovery timed out after ${timeoutMs} ms`, "TimeoutError");
295
+ const error = /* @__PURE__ */ new Error(`Resume discovery timed out after ${timeoutMs} ms`);
296
+ error.name = "TimeoutError";
297
+ return error;
298
+ }
299
+ function serverSideEncryptionRejectReason(candidate, expected) {
300
+ if (expected?.mode === EncryptionMode.SseC) return "sse-c-unsupported";
301
+ const actual = normalizeEncryption(candidate);
302
+ if (expected === void 0) {
303
+ if (candidate === void 0) return null;
304
+ if (actual === void 0) return "encryption-mismatch";
305
+ if (actual.mode === EncryptionMode.None) return null;
306
+ if (actual.mode === EncryptionMode.SseB2) return null;
307
+ return actual.mode === EncryptionMode.SseC ? "sse-c-unsupported" : "encryption-mismatch";
308
+ }
309
+ const normalizedExpected = normalizeEncryption(expected);
310
+ if (normalizedExpected?.mode === EncryptionMode.None && candidate === void 0) return null;
311
+ if (actual === void 0 || normalizedExpected === void 0) return "encryption-mismatch";
312
+ if (actual.mode !== normalizedExpected.mode) return "encryption-mismatch";
313
+ if (actual.mode === EncryptionMode.None) return null;
314
+ return actual.algorithm === normalizedExpected.algorithm ? null : "encryption-mismatch";
315
+ }
316
+ function normalizeEncryption(encryption) {
317
+ if (encryption === void 0) return void 0;
318
+ if (encryption.mode === null || encryption.mode === EncryptionMode.None) return { mode: EncryptionMode.None };
319
+ if (encryption.mode !== EncryptionMode.SseB2 && encryption.mode !== EncryptionMode.SseC) return;
320
+ return {
321
+ mode: encryption.mode,
322
+ algorithm: encryption.algorithm
323
+ };
324
+ }
325
+ function assertAdvancingPartCursor(fileId, previous, next) {
326
+ if (!Number.isInteger(next) || next < 1 || previous !== void 0 && next <= previous) throw new Error(`uploadLargeFile: listParts returned a non-advancing nextPartNumber for ${fileId}; aborting resume.`);
327
+ }
328
+ //#endregion
329
+ export { RESUME_PART_SIZE_INFO_KEY, RESUME_SOURCE_SIZE_INFO_KEY, ResumeFileIdMismatchError, findResumeCandidate };
330
+
331
+ //# sourceMappingURL=resume.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resume.js","sources":["../../src/upload/resume.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport type { BucketId, LargeFileId } from '../types/ids.ts'\nimport { largeFileId as largeFileIdOf } from '../types/ids.ts'\n\n/** Information about an unfinished large file eligible for resume. */\nexport interface ResumeCandidate {\n /** ID of the unfinished large file. */\n readonly fileId: LargeFileId\n /** SHA-1 of each part already uploaded, indexed by 1-based part number. */\n readonly uploadedPartSha1s: ReadonlyMap<number, string>\n}\n\n/**\n * Finds an unfinished large file matching the given bucket and file name.\n * Returns `null` when no matching candidate exists.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state.\n * @param bucketId - Target bucket of the upload.\n * @param fileName - Destination file name of the upload.\n *\n * @returns A {@link ResumeCandidate} describing the candidate and its uploaded parts, or `null`.\n */\nexport async function findResumeCandidate(\n raw: RawClient,\n accountInfo: AccountInfo,\n bucketId: BucketId,\n fileName: string,\n): Promise<ResumeCandidate | null> {\n const unfinished = await raw.listUnfinishedLargeFiles(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n { bucketId },\n )\n\n const match = unfinished.files.find((f) => f.fileName === fileName)\n if (!match) return null\n\n const fileId = largeFileIdOf(match.fileId)\n const uploadedPartSha1s = await collectPartSha1s(raw, accountInfo, fileId)\n\n return { fileId, uploadedPartSha1s }\n}\n\n/**\n * Lists all uploaded parts for a large file, paginating until exhausted.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state.\n * @param fileId - ID of the large file to inspect.\n *\n * @returns A map from 1-based part number to its server-stored SHA-1.\n */\nexport async function collectPartSha1s(\n raw: RawClient,\n accountInfo: AccountInfo,\n fileId: LargeFileId,\n): Promise<Map<number, string>> {\n const sha1s = new Map<number, string>()\n let startPartNumber: number | undefined\n\n while (true) {\n const page = await raw.listParts(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {\n fileId,\n ...(startPartNumber !== undefined ? { startPartNumber } : {}),\n })\n for (const part of page.parts) {\n sha1s.set(part.partNumber, part.contentSha1)\n }\n if (page.nextPartNumber === null) break\n startPartNumber = page.nextPartNumber\n }\n\n return sha1s\n}\n"],"names":["largeFileIdOf"],"mappings":";AAwBA,eAAsB,oBACpB,KACA,aACA,UACA,UACiC;AACjC,QAAM,aAAa,MAAM,IAAI;AAAA,IAC3B,YAAY,UAAA;AAAA,IACZ,YAAY,aAAA;AAAA,IACZ,EAAE,SAAA;AAAA,EAAS;AAGb,QAAM,QAAQ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ;AAClE,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,SAASA,YAAc,MAAM,MAAM;AACzC,QAAM,oBAAoB,MAAM,iBAAiB,KAAK,aAAa,MAAM;AAEzE,SAAO,EAAE,QAAQ,kBAAA;AACnB;AAWA,eAAsB,iBACpB,KACA,aACA,QAC8B;AAC9B,QAAM,4BAAY,IAAA;AAClB,MAAI;AAEJ,SAAO,MAAM;AACX,UAAM,OAAO,MAAM,IAAI,UAAU,YAAY,UAAA,GAAa,YAAY,gBAAgB;AAAA,MACpF;AAAA,MACA,GAAI,oBAAoB,SAAY,EAAE,oBAAoB,CAAA;AAAA,IAAC,CAC5D;AACD,eAAW,QAAQ,KAAK,OAAO;AAC7B,YAAM,IAAI,KAAK,YAAY,KAAK,WAAW;AAAA,IAC7C;AACA,QAAI,KAAK,mBAAmB,KAAM;AAClC,sBAAkB,KAAK;AAAA,EACzB;AAEA,SAAO;AACT;"}
1
+ {"version":3,"file":"resume.js","names":[],"sources":["../../src/upload/resume.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport { ResumeFileIdMismatchError } from '../errors/index.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport { BucketRetentionMode, type BucketRetentionPolicy } from '../types/bucket.ts'\nimport {\n EncryptionMode,\n type EncryptionSetting,\n type PublicEncryptionSetting,\n} from '../types/encryption.ts'\nimport type { BucketId, LargeFileId } from '../types/ids.ts'\nimport { largeFileId as largeFileIdOf } from '../types/ids.ts'\nimport type { FileRetentionValue, LegalHoldValue } from '../types/lock.ts'\nimport type {\n ReadableFileRetention,\n ReadableLegalHold,\n UnfinishedLargeFile,\n} from '../types/upload.ts'\n\nexport { ResumeFileIdMismatchError }\n\n/** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */\nexport const RESUME_SOURCE_SIZE_INFO_KEY = 'b2_sdk_resume_source_size'\n\n/** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */\nexport const RESUME_PART_SIZE_INFO_KEY = 'b2_sdk_resume_part_size'\n\nconst DEFAULT_MAX_RESUME_LIST_PAGES = 10\nconst DEFAULT_MAX_RESUME_PART_CANDIDATES = 25\nconst DEFAULT_MAX_RESUME_PART_PAGES = 10\n\n/** One planned part from the local upload source. */\nexport interface ResumePartPlan {\n /** 1-based B2 part number. */\n readonly partNumber: number\n /** Expected byte length for this part. */\n readonly length: number\n}\n\n/** Reason an unfinished same-name large file was not reused for resume. */\nexport type ResumeCandidateRejectedReason =\n | 'search-truncated'\n | 'candidate-limit'\n | 'file-name-mismatch'\n | 'content-type-mismatch'\n | 'file-info-mismatch'\n | 'source-size-mismatch'\n | 'part-size-mismatch'\n | 'encryption-mismatch'\n | 'sse-c-unsupported'\n | 'retention-mismatch'\n | 'legal-hold-mismatch'\n | 'part-length-mismatch'\n\n/** Diagnostic event emitted when resume discovery declines a candidate. */\nexport interface ResumeCandidateRejectedEvent {\n /** ID of the unfinished large file, when the event is candidate-specific. */\n readonly fileId?: LargeFileId\n /** Requested destination file name. */\n readonly requestedFileName: string\n /** Actual candidate file name, when the event is candidate-specific. */\n readonly candidateFileName?: string\n /** Machine-readable rejection reason. */\n readonly reason: ResumeCandidateRejectedReason\n}\n\n/** Diagnostic callback for declined resume candidates. */\nexport type ResumeCandidateRejectedListener = (event: ResumeCandidateRejectedEvent) => void\n\n/** Compatibility requirements an unfinished large file must satisfy before reuse. */\nexport interface ResumeCandidateCriteria {\n /** Effective MIME type for the upload, including SDK defaults. */\n readonly contentType: string\n /** Caller-owned file info. Legacy SDK resume keys on candidates are ignored separately. */\n readonly fileInfo: Record<string, string>\n /** Source size in bytes, checked against legacy SDK metadata when a candidate carries it. */\n readonly sourceSize: number\n /** Effective multipart part size, checked against legacy SDK metadata when present. */\n readonly partSize: number\n /** Planned local parts used to verify already-uploaded server part lengths. */\n readonly parts: readonly ResumePartPlan[]\n /** Explicit server-side encryption option, if configured by the caller. */\n readonly serverSideEncryption?: EncryptionSetting\n /** Explicit Object Lock retention option, if configured by the caller. */\n readonly fileRetention?: FileRetentionValue\n /** Effective readable bucket default retention when the caller omits fileRetention. */\n readonly defaultFileRetention?: BucketRetentionPolicy\n /** Whether bucket default retention exists but cannot be read by the caller. */\n readonly defaultFileRetentionUnreadable?: boolean\n /** Explicit legal hold option, if configured by the caller. */\n readonly legalHold?: LegalHoldValue\n /** Explicit unfinished large-file ID to verify before reuse. */\n readonly resumeFileId?: LargeFileId\n /** Abort signal used for B2 list requests and checked between pages. */\n readonly signal?: AbortSignal\n /** Optional diagnostic callback for candidates that are found but not reused. */\n readonly onCandidateRejected?: ResumeCandidateRejectedListener\n /** Maximum `b2_list_unfinished_large_files` pages to inspect. */\n readonly maxListPages?: number\n /** Maximum metadata-compatible candidates whose parts may be listed. */\n readonly maxPartCandidates?: number\n /** Maximum `b2_list_parts` pages to inspect for each metadata-compatible candidate. */\n readonly maxPartPages?: number\n /** Caller-supplied aggregate resume discovery timeout. */\n readonly discoveryTimeoutMs?: number\n}\n\n/** Uploaded part metadata used by the resume planner. */\nexport interface ResumePartInfo {\n /** SHA-1 stored by B2 for this uploaded part. */\n readonly contentSha1: string\n /** Byte length stored by B2 for this uploaded part. */\n readonly contentLength: number\n}\n\nconst LIST_PARTS_PAGE_SIZE = 100\n\n/** Information about an unfinished large file eligible for resume. */\nexport interface ResumeCandidate {\n /** ID of the unfinished large file. */\n readonly fileId: LargeFileId\n /** SHA-1 of each part already uploaded, indexed by 1-based part number. */\n readonly uploadedPartSha1s: ReadonlyMap<number, string>\n}\n\n/**\n * Finds an unfinished large file matching the given bucket and file name.\n * Returns `null` when no compatible candidate exists.\n *\n * With criteria, the newest compatible candidate is selected; incompatible\n * same-name uploads are ignored and optionally reported via\n * `onCandidateRejected`.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state.\n * @param bucketId - Target bucket of the upload.\n * @param fileName - Destination file name of the upload.\n * @param criteria - Upload identity and option checks.\n *\n * @returns A {@link ResumeCandidate} describing the candidate and its uploaded parts, or `null`.\n */\nexport async function findResumeCandidate(\n raw: RawClient,\n accountInfo: AccountInfo,\n bucketId: BucketId,\n fileName: string,\n criteria: ResumeCandidateCriteria,\n): Promise<ResumeCandidate | null> {\n const discoverySignal = createResumeDiscoverySignal(criteria)\n try {\n return await findResumeCandidateWithSignal(\n raw,\n accountInfo,\n bucketId,\n fileName,\n criteria,\n discoverySignal.signal,\n )\n } finally {\n discoverySignal.dispose()\n }\n}\n\nasync function findResumeCandidateWithSignal(\n raw: RawClient,\n accountInfo: AccountInfo,\n bucketId: BucketId,\n fileName: string,\n criteria: ResumeCandidateCriteria,\n signal: AbortSignal | undefined,\n): Promise<ResumeCandidate | null> {\n const matches: Array<{ file: UnfinishedLargeFile; sequence: number }> = []\n const maxListPages = criteria.maxListPages ?? DEFAULT_MAX_RESUME_LIST_PAGES\n const maxPartCandidates = criteria.maxPartCandidates ?? DEFAULT_MAX_RESUME_PART_CANDIDATES\n let sequence = 0\n let pageCount = 0\n const explicitResumeFileId = criteria.resumeFileId\n let startFileId: LargeFileId | undefined = explicitResumeFileId\n let truncated = false\n\n while (pageCount < maxListPages) {\n signal?.throwIfAborted()\n const unfinished = await abortableRequest(\n raw.listUnfinishedLargeFiles(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n {\n bucketId,\n maxFileCount: explicitResumeFileId !== undefined ? 1 : 100,\n namePrefix: fileName,\n ...(startFileId !== undefined ? { startFileId } : {}),\n },\n signal !== undefined ? { signal } : undefined,\n ),\n signal,\n )\n pageCount++\n\n for (const file of unfinished.files) {\n const isMatch =\n explicitResumeFileId !== undefined\n ? file.fileId === explicitResumeFileId\n : file.fileName === fileName\n if (isMatch) {\n matches.push({ file, sequence })\n }\n sequence++\n }\n\n if (explicitResumeFileId !== undefined) break\n if (unfinished.nextFileId === null) break\n startFileId = unfinished.nextFileId\n truncated = pageCount >= maxListPages\n }\n\n if (truncated) {\n emitCandidateRejected(criteria, {\n requestedFileName: fileName,\n reason: 'search-truncated',\n })\n }\n\n matches.sort(compareNewestFirst)\n\n let partCandidatesInspected = 0\n for (const match of matches) {\n signal?.throwIfAborted()\n const rejection = candidateMetadataRejectReason(match.file, fileName, criteria)\n if (rejection !== null) {\n notifyCandidateRejected(criteria, match.file, fileName, rejection)\n continue\n }\n\n if (partCandidatesInspected >= maxPartCandidates) {\n notifyCandidateRejected(criteria, match.file, fileName, 'candidate-limit')\n break\n }\n\n partCandidatesInspected++\n const fileId = largeFileIdOf(match.file.fileId)\n const uploadedPartsResult = await collectResumePartInfo(raw, accountInfo, fileId, {\n maxPages: criteria.maxPartPages ?? DEFAULT_MAX_RESUME_PART_PAGES,\n maxParts: criteria.parts.length,\n ...(signal !== undefined ? { signal } : {}),\n })\n const uploadedParts = uploadedPartsResult.parts\n if (uploadedPartsResult.truncated || !uploadedPartsMatchPlan(uploadedParts, criteria.parts)) {\n notifyCandidateRejected(criteria, match.file, fileName, 'part-length-mismatch')\n continue\n }\n\n return { fileId, uploadedPartSha1s: partInfoToSha1s(uploadedParts) }\n }\n\n return null\n}\n\ninterface CollectResumePartInfoOptions {\n readonly signal?: AbortSignal\n readonly maxPages?: number\n readonly maxParts?: number\n}\n\nasync function collectResumePartInfo(\n raw: RawClient,\n accountInfo: AccountInfo,\n fileId: LargeFileId,\n options: CollectResumePartInfoOptions,\n): Promise<{ readonly parts: Map<number, ResumePartInfo>; readonly truncated: boolean }> {\n const parts = new Map<number, ResumePartInfo>()\n const maxPages = options.maxPages ?? Number.POSITIVE_INFINITY\n const maxParts = options.maxParts ?? Number.POSITIVE_INFINITY\n let startPartNumber: number | undefined\n let pageCount = 0\n\n while (pageCount < maxPages) {\n options.signal?.throwIfAborted()\n // Fetch one part beyond the local plan so a candidate with extra uploaded\n // parts is detected and rejected instead of silently reused.\n const remainingParts =\n maxParts === Number.POSITIVE_INFINITY\n ? undefined\n : Math.max(1, Math.min(LIST_PARTS_PAGE_SIZE, maxParts - parts.size + 1))\n const page = await abortableRequest(\n raw.listParts(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n {\n fileId,\n ...(startPartNumber !== undefined ? { startPartNumber } : {}),\n ...(remainingParts !== undefined ? { maxPartCount: remainingParts } : {}),\n },\n options.signal !== undefined ? { signal: options.signal } : undefined,\n ),\n options.signal,\n )\n pageCount++\n for (const part of page.parts) {\n parts.set(part.partNumber, {\n contentSha1: part.contentSha1,\n contentLength: part.contentLength,\n })\n if (parts.size > maxParts) return { parts, truncated: true }\n }\n if (page.nextPartNumber === null) return { parts, truncated: false }\n assertAdvancingPartCursor(fileId, startPartNumber, page.nextPartNumber)\n startPartNumber = page.nextPartNumber\n }\n\n return { parts, truncated: true }\n}\n\nfunction compareNewestFirst(\n a: { file: UnfinishedLargeFile; sequence: number },\n b: { file: UnfinishedLargeFile; sequence: number },\n): number {\n const aTime = a.file.uploadTimestamp ?? Number.NEGATIVE_INFINITY\n const bTime = b.file.uploadTimestamp ?? Number.NEGATIVE_INFINITY\n if (aTime !== bTime) return bTime - aTime\n return b.sequence - a.sequence\n}\n\nfunction candidateMetadataRejectReason(\n candidate: UnfinishedLargeFile,\n fileName: string,\n criteria: ResumeCandidateCriteria,\n): ResumeCandidateRejectedReason | null {\n if (candidate.fileName !== fileName) return 'file-name-mismatch'\n if (\n criteria.contentType === 'b2/x-auto' &&\n criteria.resumeFileId === undefined &&\n candidate.contentType !== 'b2/x-auto'\n ) {\n return 'content-type-mismatch'\n }\n if (criteria.contentType !== 'b2/x-auto' && candidate.contentType !== criteria.contentType) {\n return 'content-type-mismatch'\n }\n\n const candidateInfo = splitResumeFileInfo(candidate.fileInfo ?? {})\n if (!recordEquals(candidateInfo.fileInfo, criteria.fileInfo)) return 'file-info-mismatch'\n if (\n candidateInfo.sourceSize !== undefined &&\n candidateInfo.sourceSize !== String(criteria.sourceSize)\n ) {\n return 'source-size-mismatch'\n }\n if (\n candidateInfo.partSize !== undefined &&\n candidateInfo.partSize !== String(criteria.partSize)\n ) {\n return 'part-size-mismatch'\n }\n\n const encryptionRejectReason = serverSideEncryptionRejectReason(\n candidate.serverSideEncryption,\n criteria.serverSideEncryption,\n )\n if (encryptionRejectReason !== null) return encryptionRejectReason\n if (\n !fileRetentionMatches(\n candidate.fileRetention,\n criteria.fileRetention,\n criteria.defaultFileRetention,\n criteria.defaultFileRetentionUnreadable === true,\n candidate.uploadTimestamp,\n )\n ) {\n return 'retention-mismatch'\n }\n if (!legalHoldMatches(candidate.legalHold, criteria.legalHold)) {\n return 'legal-hold-mismatch'\n }\n\n return null\n}\n\nfunction notifyCandidateRejected(\n criteria: ResumeCandidateCriteria,\n candidate: UnfinishedLargeFile,\n requestedFileName: string,\n reason: ResumeCandidateRejectedReason,\n): void {\n emitCandidateRejected(criteria, {\n fileId: largeFileIdOf(candidate.fileId),\n requestedFileName,\n candidateFileName: candidate.fileName,\n reason,\n })\n}\n\nfunction emitCandidateRejected(\n criteria: ResumeCandidateCriteria,\n event: ResumeCandidateRejectedEvent,\n): void {\n try {\n criteria.onCandidateRejected?.(event)\n } catch {\n // Diagnostic listeners should not make an otherwise valid upload fail.\n }\n}\n\nfunction uploadedPartsMatchPlan(\n uploadedParts: ReadonlyMap<number, ResumePartInfo>,\n plans: readonly ResumePartPlan[],\n): boolean {\n for (const [partNumber, part] of uploadedParts) {\n const planned = plans[partNumber - 1]\n if (planned === undefined) return false\n if (planned.partNumber !== partNumber) return false\n if (planned.length !== part.contentLength) return false\n }\n return true\n}\n\nfunction partInfoToSha1s(parts: ReadonlyMap<number, ResumePartInfo>): Map<number, string> {\n const sha1s = new Map<number, string>()\n for (const [partNumber, part] of parts) {\n sha1s.set(partNumber, part.contentSha1)\n }\n return sha1s\n}\n\nfunction recordEquals(a: Record<string, string>, b: Record<string, string>): boolean {\n const aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n if (aKeys.length !== bKeys.length) return false\n for (const key of aKeys) {\n if (a[key] !== b[key]) return false\n }\n return true\n}\n\ninterface SplitResumeFileInfo {\n readonly fileInfo: Record<string, string>\n readonly sourceSize?: string\n readonly partSize?: string\n}\n\nfunction splitResumeFileInfo(fileInfo: Record<string, string>): SplitResumeFileInfo {\n const userFileInfo: Record<string, string> = Object.create(null) as Record<string, string>\n let sourceSize: string | undefined\n let partSize: string | undefined\n for (const [key, value] of Object.entries(fileInfo)) {\n if (key === RESUME_SOURCE_SIZE_INFO_KEY) {\n sourceSize = value\n } else if (key === RESUME_PART_SIZE_INFO_KEY) {\n partSize = value\n } else {\n userFileInfo[key] = value\n }\n }\n return {\n fileInfo: userFileInfo,\n ...(sourceSize !== undefined ? { sourceSize } : {}),\n ...(partSize !== undefined ? { partSize } : {}),\n }\n}\n\nfunction fileRetentionMatches(\n candidate: ReadableFileRetention | undefined,\n expected: FileRetentionValue | undefined,\n defaultExpected: BucketRetentionPolicy | undefined,\n defaultUnreadable: boolean,\n uploadTimestamp: number | undefined,\n): boolean {\n if (expected === undefined && defaultUnreadable) return false\n if (expected === undefined && defaultExpected !== undefined) {\n if (defaultExpected.mode === BucketRetentionMode.None) {\n if (candidate === undefined) return true\n if (!candidate.isClientAuthorizedToRead) return false\n return fileRetentionValueEquals(candidate.value, null)\n }\n if (candidate === undefined || !candidate.isClientAuthorizedToRead) return false\n return fileRetentionValueMatchesBucketDefault(candidate.value, defaultExpected, uploadTimestamp)\n }\n if (expected === undefined) {\n if (candidate === undefined) return true\n if (!candidate.isClientAuthorizedToRead) return false\n return fileRetentionValueEquals(candidate.value, null)\n }\n if (candidate === undefined || !candidate.isClientAuthorizedToRead) return false\n return fileRetentionValueEquals(candidate.value, expected)\n}\n\nfunction fileRetentionValueMatchesBucketDefault(\n candidate: FileRetentionValue | null,\n expected: BucketRetentionPolicy,\n uploadTimestamp: number | undefined,\n): boolean {\n if (expected.period === null) return false\n if (candidate?.mode !== expected.mode || candidate.retainUntilTimestamp === null) return false\n if (uploadTimestamp === undefined) return false\n return candidate.retainUntilTimestamp === uploadTimestamp + retentionPeriodMillis(expected.period)\n}\n\nfunction retentionPeriodMillis(period: BucketRetentionPolicy['period']): number {\n if (period === null) return 0\n const days = period.unit === 'days' ? period.duration : period.duration * 365\n return days * 24 * 60 * 60 * 1000\n}\n\nfunction fileRetentionValueEquals(\n a: FileRetentionValue | null,\n b: FileRetentionValue | null,\n): boolean {\n return (\n (a?.mode ?? null) === (b?.mode ?? null) &&\n (a?.retainUntilTimestamp ?? null) === (b?.retainUntilTimestamp ?? null)\n )\n}\n\nfunction legalHoldMatches(\n candidate: ReadableLegalHold | undefined,\n expected: LegalHoldValue | undefined,\n): boolean {\n if (expected === undefined) {\n if (candidate === undefined) return true\n if (!candidate.isClientAuthorizedToRead) return false\n return candidate.value === null || candidate.value === 'off'\n }\n if (candidate === undefined || !candidate.isClientAuthorizedToRead) return false\n return candidate.value === expected\n}\n\ninterface ResumeDiscoverySignal {\n readonly signal?: AbortSignal\n dispose(): void\n}\n\nfunction createResumeDiscoverySignal(criteria: ResumeCandidateCriteria): ResumeDiscoverySignal {\n if (criteria.signal !== undefined) {\n return {\n signal: criteria.signal,\n dispose() {},\n }\n }\n\n if (criteria.discoveryTimeoutMs === undefined) {\n return {\n dispose() {},\n }\n }\n\n const timeoutMs = criteria.discoveryTimeoutMs\n if (timeoutMs === Number.POSITIVE_INFINITY) {\n return {\n dispose() {},\n }\n }\n\n const controller = new AbortController()\n const timeout = setTimeout(\n () => {\n controller.abort(resumeDiscoveryTimeoutReason(timeoutMs))\n },\n Math.max(0, timeoutMs),\n )\n\n return {\n signal: controller.signal,\n dispose() {\n clearTimeout(timeout)\n },\n }\n}\n\nasync function abortableRequest<T>(\n request: Promise<T>,\n signal: AbortSignal | undefined,\n): Promise<T> {\n if (signal === undefined) return request\n if (signal.aborted) throw resumeAbortReason(signal)\n\n let removeAbortListener: (() => void) | undefined\n const aborted = new Promise<never>((_resolve, reject) => {\n const onAbort = () => reject(resumeAbortReason(signal))\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n return await Promise.race([request, aborted])\n } finally {\n removeAbortListener?.()\n void request.catch(() => {})\n }\n}\n\nfunction resumeAbortReason(signal: AbortSignal): unknown {\n return signal.reason ?? resumeAbortFallbackReason()\n}\n\nfunction resumeAbortFallbackReason(): Error {\n if (typeof DOMException === 'function') {\n return new DOMException('Resume discovery aborted', 'AbortError')\n }\n const error = new Error('Resume discovery aborted')\n error.name = 'AbortError'\n return error\n}\n\nfunction resumeDiscoveryTimeoutReason(timeoutMs: number): Error {\n if (typeof DOMException === 'function') {\n return new DOMException(`Resume discovery timed out after ${timeoutMs} ms`, 'TimeoutError')\n }\n const error = new Error(`Resume discovery timed out after ${timeoutMs} ms`)\n error.name = 'TimeoutError'\n return error\n}\n\ntype ListedEncryption = PublicEncryptionSetting | undefined\n\nfunction serverSideEncryptionRejectReason(\n candidate: ListedEncryption,\n expected: EncryptionSetting | undefined,\n): 'encryption-mismatch' | 'sse-c-unsupported' | null {\n if (expected?.mode === EncryptionMode.SseC) return 'sse-c-unsupported'\n\n const actual = normalizeEncryption(candidate)\n if (expected === undefined) {\n if (candidate === undefined) return null\n if (actual === undefined) return 'encryption-mismatch'\n if (actual.mode === EncryptionMode.None) return null\n if (actual.mode === EncryptionMode.SseB2) return null\n return actual.mode === EncryptionMode.SseC ? 'sse-c-unsupported' : 'encryption-mismatch'\n }\n\n const normalizedExpected = normalizeEncryption(expected)\n if (normalizedExpected?.mode === EncryptionMode.None && candidate === undefined) return null\n if (actual === undefined || normalizedExpected === undefined) return 'encryption-mismatch'\n if (actual.mode !== normalizedExpected.mode) return 'encryption-mismatch'\n if (actual.mode === EncryptionMode.None) return null\n return actual.algorithm === normalizedExpected.algorithm ? null : 'encryption-mismatch'\n}\n\ninterface NormalizedEncryption {\n readonly mode: EncryptionMode\n readonly algorithm?: string\n}\n\nfunction normalizeEncryption(\n encryption: EncryptionSetting | ListedEncryption,\n): NormalizedEncryption | undefined {\n if (encryption === undefined) return undefined\n // Real B2 responses may spell no encryption as `{ mode: null, algorithm: null }`.\n if (encryption.mode === null || encryption.mode === EncryptionMode.None) {\n return { mode: EncryptionMode.None }\n }\n if (encryption.mode !== EncryptionMode.SseB2 && encryption.mode !== EncryptionMode.SseC) {\n return undefined\n }\n return {\n mode: encryption.mode,\n algorithm: encryption.algorithm,\n }\n}\n\nfunction assertAdvancingPartCursor(\n fileId: LargeFileId,\n previous: number | undefined,\n next: number,\n): void {\n if (!Number.isInteger(next) || next < 1 || (previous !== undefined && next <= previous)) {\n throw new Error(\n `uploadLargeFile: listParts returned a non-advancing nextPartNumber for ${fileId}; aborting resume.`,\n )\n }\n}\n"],"mappings":"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"}