@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.
- package/CHANGELOG.md +110 -5
- package/README.md +144 -33
- package/dist/_virtual/_b2-sdk-version-json.cjs +4 -0
- package/dist/_virtual/_b2-sdk-version-json.js +4 -0
- package/dist/auth/account-info.d.cts +32 -0
- package/dist/auth/account-info.d.cts.map +1 -1
- package/dist/auth/account-info.d.ts +32 -0
- package/dist/auth/account-info.d.ts.map +1 -1
- package/dist/auth/file.cjs +408 -207
- package/dist/auth/file.cjs.map +1 -1
- package/dist/auth/file.d.cts +77 -3
- package/dist/auth/file.d.cts.map +1 -1
- package/dist/auth/file.d.ts +77 -3
- package/dist/auth/file.d.ts.map +1 -1
- package/dist/auth/file.js +407 -207
- package/dist/auth/file.js.map +1 -1
- package/dist/auth/in-memory.cjs +212 -183
- package/dist/auth/in-memory.cjs.map +1 -1
- package/dist/auth/in-memory.d.cts +8 -0
- package/dist/auth/in-memory.d.cts.map +1 -1
- package/dist/auth/in-memory.d.ts +8 -0
- package/dist/auth/in-memory.d.ts.map +1 -1
- package/dist/auth/in-memory.js +211 -182
- package/dist/auth/in-memory.js.map +1 -1
- package/dist/auth/index.cjs +7 -9
- package/dist/auth/index.d.cts +3 -2
- package/dist/auth/index.d.cts.map +1 -1
- package/dist/auth/index.d.ts +3 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +2 -8
- package/dist/auth/realms.cjs +80 -7
- package/dist/auth/realms.cjs.map +1 -1
- package/dist/auth/realms.d.cts +27 -4
- package/dist/auth/realms.d.cts.map +1 -1
- package/dist/auth/realms.d.ts +27 -4
- package/dist/auth/realms.d.ts.map +1 -1
- package/dist/auth/realms.js +80 -9
- package/dist/auth/realms.js.map +1 -1
- package/dist/auth/upload-url-pool.cjs +55 -51
- package/dist/auth/upload-url-pool.cjs.map +1 -1
- package/dist/auth/upload-url-pool.js +55 -51
- package/dist/auth/upload-url-pool.js.map +1 -1
- package/dist/bucket.cjs +785 -787
- package/dist/bucket.cjs.map +1 -1
- package/dist/bucket.d.cts +35 -47
- package/dist/bucket.d.cts.map +1 -1
- package/dist/bucket.d.ts +35 -47
- package/dist/bucket.d.ts.map +1 -1
- package/dist/bucket.js +780 -782
- package/dist/bucket.js.map +1 -1
- package/dist/client.cjs +246 -228
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +25 -17
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.ts +25 -17
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +243 -225
- package/dist/client.js.map +1 -1
- package/dist/copy/large.cjs +114 -71
- package/dist/copy/large.cjs.map +1 -1
- package/dist/copy/large.d.cts +6 -0
- package/dist/copy/large.d.cts.map +1 -1
- package/dist/copy/large.d.ts +6 -0
- package/dist/copy/large.d.ts.map +1 -1
- package/dist/copy/large.js +112 -69
- package/dist/copy/large.js.map +1 -1
- package/dist/download/checksum.cjs +89 -0
- package/dist/download/checksum.cjs.map +1 -0
- package/dist/download/checksum.d.cts +40 -0
- package/dist/download/checksum.d.cts.map +1 -0
- package/dist/download/checksum.d.ts +40 -0
- package/dist/download/checksum.d.ts.map +1 -0
- package/dist/download/checksum.js +87 -0
- package/dist/download/checksum.js.map +1 -0
- package/dist/download/parallel.cjs +214 -118
- package/dist/download/parallel.cjs.map +1 -1
- package/dist/download/parallel.d.cts +5 -1
- package/dist/download/parallel.d.cts.map +1 -1
- package/dist/download/parallel.d.ts +5 -1
- package/dist/download/parallel.d.ts.map +1 -1
- package/dist/download/parallel.js +212 -116
- package/dist/download/parallel.js.map +1 -1
- package/dist/download/single.cjs +188 -97
- package/dist/download/single.cjs.map +1 -1
- package/dist/download/single.d.cts +6 -1
- package/dist/download/single.d.cts.map +1 -1
- package/dist/download/single.d.ts +6 -1
- package/dist/download/single.d.ts.map +1 -1
- package/dist/download/single.js +186 -98
- package/dist/download/single.js.map +1 -1
- package/dist/errors/index.cjs +699 -243
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.cts +285 -82
- package/dist/errors/index.d.cts.map +1 -1
- package/dist/errors/index.d.ts +285 -82
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +678 -261
- package/dist/errors/index.js.map +1 -1
- package/dist/http/retry.cjs +45 -28
- package/dist/http/retry.cjs.map +1 -1
- package/dist/http/retry.d.cts +15 -2
- package/dist/http/retry.d.cts.map +1 -1
- package/dist/http/retry.d.ts +15 -2
- package/dist/http/retry.d.ts.map +1 -1
- package/dist/http/retry.js +46 -31
- package/dist/http/retry.js.map +1 -1
- package/dist/http/transport.cjs +438 -140
- package/dist/http/transport.cjs.map +1 -1
- package/dist/http/transport.d.cts +21 -2
- package/dist/http/transport.d.cts.map +1 -1
- package/dist/http/transport.d.ts +21 -2
- package/dist/http/transport.d.ts.map +1 -1
- package/dist/http/transport.js +437 -140
- package/dist/http/transport.js.map +1 -1
- package/dist/http/url-guard.cjs +154 -89
- package/dist/http/url-guard.cjs.map +1 -1
- package/dist/http/url-guard.d.cts +25 -3
- package/dist/http/url-guard.d.cts.map +1 -1
- package/dist/http/url-guard.d.ts +25 -3
- package/dist/http/url-guard.d.ts.map +1 -1
- package/dist/http/url-guard.js +152 -90
- package/dist/http/url-guard.js.map +1 -1
- package/dist/http/user-agent.cjs +84 -44
- package/dist/http/user-agent.cjs.map +1 -1
- package/dist/http/user-agent.js +84 -46
- package/dist/http/user-agent.js.map +1 -1
- package/dist/index.cjs +101 -77
- package/dist/index.d.cts +27 -21
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +27 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -71
- package/dist/internal/b2-naming.cjs +66 -0
- package/dist/internal/b2-naming.cjs.map +1 -0
- package/dist/internal/b2-naming.d.cts +43 -0
- package/dist/internal/b2-naming.d.cts.map +1 -0
- package/dist/internal/b2-naming.d.ts +43 -0
- package/dist/internal/b2-naming.d.ts.map +1 -0
- package/dist/internal/b2-naming.js +60 -0
- package/dist/internal/b2-naming.js.map +1 -0
- package/dist/internal/upload-retry-options.cjs +21 -0
- package/dist/internal/upload-retry-options.cjs.map +1 -0
- package/dist/internal/upload-retry-options.d.cts +12 -0
- package/dist/internal/upload-retry-options.d.cts.map +1 -0
- package/dist/internal/upload-retry-options.d.ts +12 -0
- package/dist/internal/upload-retry-options.d.ts.map +1 -0
- package/dist/internal/upload-retry-options.js +21 -0
- package/dist/internal/upload-retry-options.js.map +1 -0
- package/dist/internal/url-redaction.cjs +31 -0
- package/dist/internal/url-redaction.cjs.map +1 -0
- package/dist/internal/url-redaction.d.cts +17 -0
- package/dist/internal/url-redaction.d.cts.map +1 -0
- package/dist/internal/url-redaction.d.ts +17 -0
- package/dist/internal/url-redaction.d.ts.map +1 -0
- package/dist/internal/url-redaction.js +31 -0
- package/dist/internal/url-redaction.js.map +1 -0
- package/dist/notifications/index.cjs +4 -6
- package/dist/notifications/index.d.cts +1 -1
- package/dist/notifications/index.d.cts.map +1 -1
- package/dist/notifications/index.d.ts +1 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +1 -6
- package/dist/notifications/webhook.cjs +195 -85
- package/dist/notifications/webhook.cjs.map +1 -1
- package/dist/notifications/webhook.d.cts.map +1 -1
- package/dist/notifications/webhook.d.ts.map +1 -1
- package/dist/notifications/webhook.js +195 -87
- package/dist/notifications/webhook.js.map +1 -1
- package/dist/object.cjs +253 -210
- package/dist/object.cjs.map +1 -1
- package/dist/object.d.cts +9 -55
- package/dist/object.d.cts.map +1 -1
- package/dist/object.d.ts +9 -55
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +249 -206
- package/dist/object.js.map +1 -1
- package/dist/raw/encoding.cjs +74 -35
- package/dist/raw/encoding.cjs.map +1 -1
- package/dist/raw/encoding.js +74 -38
- package/dist/raw/encoding.js.map +1 -1
- package/dist/raw/index.cjs +678 -587
- package/dist/raw/index.cjs.map +1 -1
- package/dist/raw/index.d.cts +121 -18
- package/dist/raw/index.d.cts.map +1 -1
- package/dist/raw/index.d.ts +121 -18
- package/dist/raw/index.d.ts.map +1 -1
- package/dist/raw/index.js +674 -589
- package/dist/raw/index.js.map +1 -1
- package/dist/s3/index.cjs +355 -18
- package/dist/s3/index.cjs.map +1 -1
- package/dist/s3/index.d.cts +233 -5
- package/dist/s3/index.d.cts.map +1 -1
- package/dist/s3/index.d.ts +233 -5
- package/dist/s3/index.d.ts.map +1 -1
- package/dist/s3/index.js +351 -22
- package/dist/s3/index.js.map +1 -1
- package/dist/s3/sigv4.cjs +149 -0
- package/dist/s3/sigv4.cjs.map +1 -0
- package/dist/s3/sigv4.d.cts +43 -0
- package/dist/s3/sigv4.d.cts.map +1 -0
- package/dist/s3/sigv4.d.ts +43 -0
- package/dist/s3/sigv4.d.ts.map +1 -0
- package/dist/s3/sigv4.js +148 -0
- package/dist/s3/sigv4.js.map +1 -0
- package/dist/s3/validation.cjs +69 -0
- package/dist/s3/validation.cjs.map +1 -0
- package/dist/s3/validation.d.cts +43 -0
- package/dist/s3/validation.d.cts.map +1 -0
- package/dist/s3/validation.d.ts +43 -0
- package/dist/s3/validation.d.ts.map +1 -0
- package/dist/s3/validation.js +66 -0
- package/dist/s3/validation.js.map +1 -0
- package/dist/simulator/capabilities.cjs +63 -48
- package/dist/simulator/capabilities.cjs.map +1 -1
- package/dist/simulator/capabilities.js +63 -49
- package/dist/simulator/capabilities.js.map +1 -1
- package/dist/simulator/index.cjs +2124 -1548
- package/dist/simulator/index.cjs.map +1 -1
- package/dist/simulator/index.d.cts +79 -11
- package/dist/simulator/index.d.cts.map +1 -1
- package/dist/simulator/index.d.ts +79 -11
- package/dist/simulator/index.d.ts.map +1 -1
- package/dist/simulator/index.js +2112 -1546
- package/dist/simulator/index.js.map +1 -1
- package/dist/simulator/validation.cjs +191 -153
- package/dist/simulator/validation.cjs.map +1 -1
- package/dist/simulator/validation.d.cts +3 -21
- package/dist/simulator/validation.d.cts.map +1 -1
- package/dist/simulator/validation.d.ts +3 -21
- package/dist/simulator/validation.d.ts.map +1 -1
- package/dist/simulator/validation.js +188 -162
- package/dist/simulator/validation.js.map +1 -1
- package/dist/streams/collect.cjs +74 -24
- package/dist/streams/collect.cjs.map +1 -1
- package/dist/streams/collect.d.cts +14 -1
- package/dist/streams/collect.d.cts.map +1 -1
- package/dist/streams/collect.d.ts +14 -1
- package/dist/streams/collect.d.ts.map +1 -1
- package/dist/streams/collect.js +74 -25
- package/dist/streams/collect.js.map +1 -1
- package/dist/streams/file-source.cjs +287 -0
- package/dist/streams/file-source.cjs.map +1 -0
- package/dist/streams/file-source.d.cts +96 -0
- package/dist/streams/file-source.d.cts.map +1 -0
- package/dist/streams/file-source.d.ts +96 -0
- package/dist/streams/file-source.d.ts.map +1 -0
- package/dist/streams/file-source.js +286 -0
- package/dist/streams/file-source.js.map +1 -0
- package/dist/streams/hash.cjs +207 -115
- package/dist/streams/hash.cjs.map +1 -1
- package/dist/streams/hash.d.cts +5 -4
- package/dist/streams/hash.d.cts.map +1 -1
- package/dist/streams/hash.d.ts +5 -4
- package/dist/streams/hash.d.ts.map +1 -1
- package/dist/streams/hash.js +208 -95
- package/dist/streams/hash.js.map +1 -1
- package/dist/streams/index.cjs +12 -12
- package/dist/streams/index.d.cts +3 -3
- package/dist/streams/index.d.cts.map +1 -1
- package/dist/streams/index.d.ts +3 -3
- package/dist/streams/index.d.ts.map +1 -1
- package/dist/streams/index.js +2 -10
- package/dist/streams/progress.cjs +60 -46
- package/dist/streams/progress.cjs.map +1 -1
- package/dist/streams/progress.js +60 -46
- package/dist/streams/progress.js.map +1 -1
- package/dist/streams/source.cjs +316 -146
- package/dist/streams/source.cjs.map +1 -1
- package/dist/streams/source.d.cts +56 -18
- package/dist/streams/source.d.cts.map +1 -1
- package/dist/streams/source.d.ts +56 -18
- package/dist/streams/source.d.ts.map +1 -1
- package/dist/streams/source.js +312 -149
- package/dist/streams/source.js.map +1 -1
- package/dist/sync/actions/index.cjs +236 -184
- package/dist/sync/actions/index.cjs.map +1 -1
- package/dist/sync/actions/index.d.cts +29 -21
- package/dist/sync/actions/index.d.cts.map +1 -1
- package/dist/sync/actions/index.d.ts +29 -21
- package/dist/sync/actions/index.d.ts.map +1 -1
- package/dist/sync/actions/index.js +236 -190
- package/dist/sync/actions/index.js.map +1 -1
- package/dist/sync/b2-sha1-reader.cjs +148 -0
- package/dist/sync/b2-sha1-reader.cjs.map +1 -0
- package/dist/sync/b2-sha1-reader.d.cts +58 -0
- package/dist/sync/b2-sha1-reader.d.cts.map +1 -0
- package/dist/sync/b2-sha1-reader.d.ts +58 -0
- package/dist/sync/b2-sha1-reader.d.ts.map +1 -0
- package/dist/sync/b2-sha1-reader.js +145 -0
- package/dist/sync/b2-sha1-reader.js.map +1 -0
- package/dist/sync/download-staging.cjs +265 -0
- package/dist/sync/download-staging.cjs.map +1 -0
- package/dist/sync/download-staging.d.cts +54 -0
- package/dist/sync/download-staging.d.cts.map +1 -0
- package/dist/sync/download-staging.d.ts +54 -0
- package/dist/sync/download-staging.d.ts.map +1 -0
- package/dist/sync/download-staging.js +259 -0
- package/dist/sync/download-staging.js.map +1 -0
- package/dist/sync/filesystem-errors.cjs +32 -0
- package/dist/sync/filesystem-errors.cjs.map +1 -0
- package/dist/sync/filesystem-errors.d.cts +8 -0
- package/dist/sync/filesystem-errors.d.cts.map +1 -0
- package/dist/sync/filesystem-errors.d.ts +8 -0
- package/dist/sync/filesystem-errors.d.ts.map +1 -0
- package/dist/sync/filesystem-errors.js +32 -0
- package/dist/sync/filesystem-errors.js.map +1 -0
- package/dist/sync/filters.cjs +217 -0
- package/dist/sync/filters.cjs.map +1 -0
- package/dist/sync/filters.d.cts +51 -0
- package/dist/sync/filters.d.cts.map +1 -0
- package/dist/sync/filters.d.ts +51 -0
- package/dist/sync/filters.d.ts.map +1 -0
- package/dist/sync/filters.js +213 -0
- package/dist/sync/filters.js.map +1 -0
- package/dist/sync/index.cjs +39 -22
- package/dist/sync/index.d.cts +14 -9
- package/dist/sync/index.d.cts.map +1 -1
- package/dist/sync/index.d.ts +14 -9
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +9 -20
- package/dist/sync/local-file-identity.cjs +61 -0
- package/dist/sync/local-file-identity.cjs.map +1 -0
- package/dist/sync/local-file-identity.d.cts +37 -0
- package/dist/sync/local-file-identity.d.cts.map +1 -0
- package/dist/sync/local-file-identity.d.ts +37 -0
- package/dist/sync/local-file-identity.d.ts.map +1 -0
- package/dist/sync/local-file-identity.js +60 -0
- package/dist/sync/local-file-identity.js.map +1 -0
- package/dist/sync/local-file-io.cjs +364 -0
- package/dist/sync/local-file-io.cjs.map +1 -0
- package/dist/sync/local-file-io.d.cts +75 -0
- package/dist/sync/local-file-io.d.cts.map +1 -0
- package/dist/sync/local-file-io.d.ts +75 -0
- package/dist/sync/local-file-io.d.ts.map +1 -0
- package/dist/sync/local-file-io.js +360 -0
- package/dist/sync/local-file-io.js.map +1 -0
- package/dist/sync/local-filesystem-root.cjs +27 -0
- package/dist/sync/local-filesystem-root.cjs.map +1 -0
- package/dist/sync/local-filesystem-root.d.cts +18 -0
- package/dist/sync/local-filesystem-root.d.cts.map +1 -0
- package/dist/sync/local-filesystem-root.d.ts +18 -0
- package/dist/sync/local-filesystem-root.d.ts.map +1 -0
- package/dist/sync/local-filesystem-root.js +26 -0
- package/dist/sync/local-filesystem-root.js.map +1 -0
- package/dist/sync/local-sha1.cjs +119 -0
- package/dist/sync/local-sha1.cjs.map +1 -0
- package/dist/sync/local-sha1.d.cts +39 -0
- package/dist/sync/local-sha1.d.cts.map +1 -0
- package/dist/sync/local-sha1.d.ts +39 -0
- package/dist/sync/local-sha1.d.ts.map +1 -0
- package/dist/sync/local-sha1.js +117 -0
- package/dist/sync/local-sha1.js.map +1 -0
- package/dist/sync/pairing.cjs +118 -29
- package/dist/sync/pairing.cjs.map +1 -1
- package/dist/sync/pairing.d.cts +7 -2
- package/dist/sync/pairing.d.cts.map +1 -1
- package/dist/sync/pairing.d.ts +7 -2
- package/dist/sync/pairing.d.ts.map +1 -1
- package/dist/sync/pairing.js +120 -31
- package/dist/sync/pairing.js.map +1 -1
- package/dist/sync/path-order.cjs +30 -0
- package/dist/sync/path-order.cjs.map +1 -0
- package/dist/sync/path-order.d.cts +28 -0
- package/dist/sync/path-order.d.cts.map +1 -0
- package/dist/sync/path-order.d.ts +28 -0
- package/dist/sync/path-order.d.ts.map +1 -0
- package/dist/sync/path-order.js +29 -0
- package/dist/sync/path-order.js.map +1 -0
- package/dist/sync/path-safety.cjs +111 -0
- package/dist/sync/path-safety.cjs.map +1 -0
- package/dist/sync/path-safety.d.cts +78 -0
- package/dist/sync/path-safety.d.cts.map +1 -0
- package/dist/sync/path-safety.d.ts +78 -0
- package/dist/sync/path-safety.d.ts.map +1 -0
- package/dist/sync/path-safety.js +105 -0
- package/dist/sync/path-safety.js.map +1 -0
- package/dist/sync/paths.d.cts +19 -0
- package/dist/sync/paths.d.cts.map +1 -0
- package/dist/sync/paths.d.ts +19 -0
- package/dist/sync/paths.d.ts.map +1 -0
- package/dist/sync/policies/compare.cjs +389 -11
- package/dist/sync/policies/compare.cjs.map +1 -1
- package/dist/sync/policies/compare.d.cts +100 -2
- package/dist/sync/policies/compare.d.cts.map +1 -1
- package/dist/sync/policies/compare.d.ts +100 -2
- package/dist/sync/policies/compare.d.ts.map +1 -1
- package/dist/sync/policies/compare.js +387 -13
- package/dist/sync/policies/compare.js.map +1 -1
- package/dist/sync/policies/index.cjs +76 -65
- package/dist/sync/policies/index.cjs.map +1 -1
- package/dist/sync/policies/index.d.cts +35 -6
- package/dist/sync/policies/index.d.cts.map +1 -1
- package/dist/sync/policies/index.d.ts +35 -6
- package/dist/sync/policies/index.d.ts.map +1 -1
- package/dist/sync/policies/index.js +76 -65
- package/dist/sync/policies/index.js.map +1 -1
- package/dist/sync/prefix.cjs +96 -0
- package/dist/sync/prefix.cjs.map +1 -0
- package/dist/sync/prefix.d.cts +55 -0
- package/dist/sync/prefix.d.cts.map +1 -0
- package/dist/sync/prefix.d.ts +55 -0
- package/dist/sync/prefix.d.ts.map +1 -0
- package/dist/sync/prefix.js +92 -0
- package/dist/sync/prefix.js.map +1 -0
- package/dist/sync/regexp-safety.cjs +192 -0
- package/dist/sync/regexp-safety.cjs.map +1 -0
- package/dist/sync/regexp-safety.d.cts +29 -0
- package/dist/sync/regexp-safety.d.cts.map +1 -0
- package/dist/sync/regexp-safety.d.ts +29 -0
- package/dist/sync/regexp-safety.d.ts.map +1 -0
- package/dist/sync/regexp-safety.js +190 -0
- package/dist/sync/regexp-safety.js.map +1 -0
- package/dist/sync/scan-events.cjs +33 -0
- package/dist/sync/scan-events.cjs.map +1 -0
- package/dist/sync/scan-events.d.cts +17 -0
- package/dist/sync/scan-events.d.cts.map +1 -0
- package/dist/sync/scan-events.d.ts +17 -0
- package/dist/sync/scan-events.d.ts.map +1 -0
- package/dist/sync/scan-events.js +32 -0
- package/dist/sync/scan-events.js.map +1 -0
- package/dist/sync/scan-limit.cjs +33 -0
- package/dist/sync/scan-limit.cjs.map +1 -0
- package/dist/sync/scan-limit.d.cts +21 -0
- package/dist/sync/scan-limit.d.cts.map +1 -0
- package/dist/sync/scan-limit.d.ts +21 -0
- package/dist/sync/scan-limit.d.ts.map +1 -0
- package/dist/sync/scan-limit.js +31 -0
- package/dist/sync/scan-limit.js.map +1 -0
- package/dist/sync/scanners/b2.cjs +239 -55
- package/dist/sync/scanners/b2.cjs.map +1 -1
- package/dist/sync/scanners/b2.d.cts +26 -7
- package/dist/sync/scanners/b2.d.cts.map +1 -1
- package/dist/sync/scanners/b2.d.ts +26 -7
- package/dist/sync/scanners/b2.d.ts.map +1 -1
- package/dist/sync/scanners/b2.js +239 -55
- package/dist/sync/scanners/b2.js.map +1 -1
- package/dist/sync/scanners/local.cjs +215 -56
- package/dist/sync/scanners/local.cjs.map +1 -1
- package/dist/sync/scanners/local.d.cts +22 -7
- package/dist/sync/scanners/local.d.cts.map +1 -1
- package/dist/sync/scanners/local.d.ts +22 -7
- package/dist/sync/scanners/local.d.ts.map +1 -1
- package/dist/sync/scanners/local.js +216 -57
- package/dist/sync/scanners/local.js.map +1 -1
- package/dist/sync/sha1-metadata.cjs +94 -0
- package/dist/sync/sha1-metadata.cjs.map +1 -0
- package/dist/sync/sha1-metadata.d.cts +82 -0
- package/dist/sync/sha1-metadata.d.cts.map +1 -0
- package/dist/sync/sha1-metadata.d.ts +82 -0
- package/dist/sync/sha1-metadata.d.ts.map +1 -0
- package/dist/sync/sha1-metadata.js +89 -0
- package/dist/sync/sha1-metadata.js.map +1 -0
- package/dist/sync/sha1-options.cjs +23 -0
- package/dist/sync/sha1-options.cjs.map +1 -0
- package/dist/sync/sha1-options.d.cts +14 -0
- package/dist/sync/sha1-options.d.cts.map +1 -0
- package/dist/sync/sha1-options.d.ts +14 -0
- package/dist/sync/sha1-options.d.ts.map +1 -0
- package/dist/sync/sha1-options.js +21 -0
- package/dist/sync/sha1-options.js.map +1 -0
- package/dist/sync/synchronizer.cjs +782 -197
- package/dist/sync/synchronizer.cjs.map +1 -1
- package/dist/sync/synchronizer.d.cts +47 -1
- package/dist/sync/synchronizer.d.cts.map +1 -1
- package/dist/sync/synchronizer.d.ts +47 -1
- package/dist/sync/synchronizer.d.ts.map +1 -1
- package/dist/sync/synchronizer.js +779 -173
- package/dist/sync/synchronizer.js.map +1 -1
- package/dist/sync/types.d.cts +208 -16
- package/dist/sync/types.d.cts.map +1 -1
- package/dist/sync/types.d.ts +208 -16
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/types/auth.cjs +76 -56
- package/dist/types/auth.cjs.map +1 -1
- package/dist/types/auth.d.cts +67 -9
- package/dist/types/auth.d.cts.map +1 -1
- package/dist/types/auth.d.ts +67 -9
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/auth.js +77 -57
- package/dist/types/auth.js.map +1 -1
- package/dist/types/bucket.cjs +74 -38
- package/dist/types/bucket.cjs.map +1 -1
- package/dist/types/bucket.js +75 -41
- package/dist/types/bucket.js.map +1 -1
- package/dist/types/encryption.cjs +364 -327
- package/dist/types/encryption.cjs.map +1 -1
- package/dist/types/encryption.d.cts +16 -0
- package/dist/types/encryption.d.cts.map +1 -1
- package/dist/types/encryption.d.ts +16 -0
- package/dist/types/encryption.d.ts.map +1 -1
- package/dist/types/encryption.js +364 -310
- package/dist/types/encryption.js.map +1 -1
- package/dist/types/errors.cjs +47 -0
- package/dist/types/errors.cjs.map +1 -0
- package/dist/types/errors.d.cts +13 -4
- package/dist/types/errors.d.cts.map +1 -1
- package/dist/types/errors.d.ts +13 -4
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +47 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/file.cjs +36 -19
- package/dist/types/file.cjs.map +1 -1
- package/dist/types/file.d.cts +2 -2
- package/dist/types/file.d.cts.map +1 -1
- package/dist/types/file.d.ts +2 -2
- package/dist/types/file.d.ts.map +1 -1
- package/dist/types/file.js +37 -21
- package/dist/types/file.js.map +1 -1
- package/dist/types/ids.cjs +53 -9
- package/dist/types/ids.cjs.map +1 -1
- package/dist/types/ids.js +54 -15
- package/dist/types/ids.js.map +1 -1
- package/dist/types/index.d.cts +12 -11
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +12 -11
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/key.d.cts +44 -8
- package/dist/types/key.d.cts.map +1 -1
- package/dist/types/key.d.ts +44 -8
- package/dist/types/key.d.ts.map +1 -1
- package/dist/types/lock.cjs +33 -13
- package/dist/types/lock.cjs.map +1 -1
- package/dist/types/lock.js +34 -15
- package/dist/types/lock.js.map +1 -1
- package/dist/types/notifications.cjs +44 -22
- package/dist/types/notifications.cjs.map +1 -1
- package/dist/types/notifications.js +45 -23
- package/dist/types/notifications.js.map +1 -1
- package/dist/types/upload.d.cts +39 -5
- package/dist/types/upload.d.cts.map +1 -1
- package/dist/types/upload.d.ts +39 -5
- package/dist/types/upload.d.ts.map +1 -1
- package/dist/upload/abort-scope.cjs +91 -0
- package/dist/upload/abort-scope.cjs.map +1 -0
- package/dist/upload/abort-scope.d.cts +48 -0
- package/dist/upload/abort-scope.d.cts.map +1 -0
- package/dist/upload/abort-scope.d.ts +48 -0
- package/dist/upload/abort-scope.d.ts.map +1 -0
- package/dist/upload/abort-scope.js +88 -0
- package/dist/upload/abort-scope.js.map +1 -0
- package/dist/upload/cancel.cjs +183 -8
- package/dist/upload/cancel.cjs.map +1 -1
- package/dist/upload/cancel.d.cts +110 -2
- package/dist/upload/cancel.d.cts.map +1 -1
- package/dist/upload/cancel.d.ts +110 -2
- package/dist/upload/cancel.d.ts.map +1 -1
- package/dist/upload/cancel.js +178 -9
- package/dist/upload/cancel.js.map +1 -1
- package/dist/upload/concurrency.cjs +79 -52
- package/dist/upload/concurrency.cjs.map +1 -1
- package/dist/upload/concurrency.js +79 -53
- package/dist/upload/concurrency.js.map +1 -1
- package/dist/upload/finish.cjs +59 -0
- package/dist/upload/finish.cjs.map +1 -0
- package/dist/upload/finish.d.cts +26 -0
- package/dist/upload/finish.d.cts.map +1 -0
- package/dist/upload/finish.d.ts +26 -0
- package/dist/upload/finish.d.ts.map +1 -0
- package/dist/upload/finish.js +59 -0
- package/dist/upload/finish.js.map +1 -0
- package/dist/upload/large.cjs +301 -218
- package/dist/upload/large.cjs.map +1 -1
- package/dist/upload/large.d.cts +76 -9
- package/dist/upload/large.d.cts.map +1 -1
- package/dist/upload/large.d.ts +76 -9
- package/dist/upload/large.d.ts.map +1 -1
- package/dist/upload/large.js +301 -218
- package/dist/upload/large.js.map +1 -1
- package/dist/upload/options.cjs +28 -0
- package/dist/upload/options.cjs.map +1 -0
- package/dist/upload/options.d.cts +104 -0
- package/dist/upload/options.d.cts.map +1 -0
- package/dist/upload/options.d.ts +104 -0
- package/dist/upload/options.d.ts.map +1 -0
- package/dist/upload/options.js +27 -0
- package/dist/upload/options.js.map +1 -0
- package/dist/upload/resume.cjs +333 -33
- package/dist/upload/resume.cjs.map +1 -1
- package/dist/upload/resume.d.cts +82 -12
- package/dist/upload/resume.d.cts.map +1 -1
- package/dist/upload/resume.d.ts +82 -12
- package/dist/upload/resume.d.ts.map +1 -1
- package/dist/upload/resume.js +330 -33
- package/dist/upload/resume.js.map +1 -1
- package/dist/upload/retry.cjs +186 -0
- package/dist/upload/retry.cjs.map +1 -0
- package/dist/upload/retry.d.cts +127 -0
- package/dist/upload/retry.d.cts.map +1 -0
- package/dist/upload/retry.d.ts +127 -0
- package/dist/upload/retry.d.ts.map +1 -0
- package/dist/upload/retry.js +182 -0
- package/dist/upload/retry.js.map +1 -0
- package/dist/upload/single.cjs +68 -44
- package/dist/upload/single.cjs.map +1 -1
- package/dist/upload/single.d.cts +2 -1
- package/dist/upload/single.d.cts.map +1 -1
- package/dist/upload/single.d.ts +2 -1
- package/dist/upload/single.d.ts.map +1 -1
- package/dist/upload/single.js +68 -44
- package/dist/upload/single.js.map +1 -1
- package/dist/upload/stream.cjs +317 -193
- package/dist/upload/stream.cjs.map +1 -1
- package/dist/upload/stream.d.cts +3 -1
- package/dist/upload/stream.d.cts.map +1 -1
- package/dist/upload/stream.d.ts +3 -1
- package/dist/upload/stream.d.ts.map +1 -1
- package/dist/upload/stream.js +316 -192
- package/dist/upload/stream.js.map +1 -1
- package/dist/util/best-effort.cjs +42 -8
- package/dist/util/best-effort.cjs.map +1 -1
- package/dist/util/best-effort.d.cts +2 -1
- package/dist/util/best-effort.d.cts.map +1 -1
- package/dist/util/best-effort.d.ts +2 -1
- package/dist/util/best-effort.d.ts.map +1 -1
- package/dist/util/best-effort.js +43 -9
- package/dist/util/best-effort.js.map +1 -1
- package/dist/util/bytes.cjs +23 -0
- package/dist/util/bytes.cjs.map +1 -0
- package/dist/util/bytes.d.cts +15 -0
- package/dist/util/bytes.d.cts.map +1 -0
- package/dist/util/bytes.d.ts +15 -0
- package/dist/util/bytes.d.ts.map +1 -0
- package/dist/util/bytes.js +23 -0
- package/dist/util/bytes.js.map +1 -0
- package/dist/util/crypto.cjs +68 -0
- package/dist/util/crypto.cjs.map +1 -0
- package/dist/util/crypto.d.cts +26 -0
- package/dist/util/crypto.d.cts.map +1 -0
- package/dist/util/crypto.d.ts +26 -0
- package/dist/util/crypto.d.ts.map +1 -0
- package/dist/util/crypto.js +66 -0
- package/dist/util/crypto.js.map +1 -0
- package/dist/util/defaults.cjs +25 -9
- package/dist/util/defaults.cjs.map +1 -1
- package/dist/util/defaults.js +26 -11
- package/dist/util/defaults.js.map +1 -1
- package/dist/util/error-reason.cjs +41 -0
- package/dist/util/error-reason.cjs.map +1 -0
- package/dist/util/error-reason.d.cts +9 -0
- package/dist/util/error-reason.d.cts.map +1 -0
- package/dist/util/error-reason.d.ts +9 -0
- package/dist/util/error-reason.d.ts.map +1 -0
- package/dist/util/error-reason.js +41 -0
- package/dist/util/error-reason.js.map +1 -0
- package/dist/util/http.cjs +23 -0
- package/dist/util/http.cjs.map +1 -0
- package/dist/util/http.d.cts +13 -0
- package/dist/util/http.d.cts.map +1 -0
- package/dist/util/http.d.ts +13 -0
- package/dist/util/http.d.ts.map +1 -0
- package/dist/util/http.js +23 -0
- package/dist/util/http.js.map +1 -0
- package/dist/util/normalize.cjs +66 -7
- package/dist/util/normalize.cjs.map +1 -1
- package/dist/util/normalize.js +67 -10
- package/dist/util/normalize.js.map +1 -1
- package/dist/util/paginator.cjs +63 -14
- package/dist/util/paginator.cjs.map +1 -1
- package/dist/util/paginator.js +64 -16
- package/dist/util/paginator.js.map +1 -1
- package/dist/util/plan-ranges.cjs +47 -22
- package/dist/util/plan-ranges.cjs.map +1 -1
- package/dist/util/plan-ranges.js +48 -24
- package/dist/util/plan-ranges.js.map +1 -1
- package/dist/util/sha1.cjs +27 -0
- package/dist/util/sha1.cjs.map +1 -0
- package/dist/util/sha1.d.cts +17 -0
- package/dist/util/sha1.d.cts.map +1 -0
- package/dist/util/sha1.d.ts +17 -0
- package/dist/util/sha1.d.ts.map +1 -0
- package/dist/util/sha1.js +26 -0
- package/dist/util/sha1.js.map +1 -0
- package/dist/util/text-codec.cjs +29 -5
- package/dist/util/text-codec.cjs.map +1 -1
- package/dist/util/text-codec.js +30 -7
- package/dist/util/text-codec.js.map +1 -1
- package/dist/util/to-error.cjs +18 -4
- package/dist/util/to-error.cjs.map +1 -1
- package/dist/util/to-error.js +19 -5
- package/dist/util/to-error.js.map +1 -1
- package/dist/version.cjs +17 -5
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +3 -3
- package/dist/version.d.ts +3 -3
- package/dist/version.js +19 -6
- package/dist/version.js.map +1 -1
- package/package.json +19 -16
- package/dist/auth/index.cjs.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/notifications/index.cjs.map +0 -1
- package/dist/notifications/index.js.map +0 -1
- package/dist/package.json.cjs +0 -9
- package/dist/package.json.cjs.map +0 -1
- package/dist/package.json.js +0 -9
- package/dist/package.json.js.map +0 -1
- package/dist/streams/index.cjs.map +0 -1
- package/dist/streams/index.js.map +0 -1
- package/dist/sync/index.cjs.map +0 -1
- package/dist/sync/index.js.map +0 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
const require_errors_index = require("../errors/index.cjs");
|
|
2
|
+
const require_retry = require("../http/retry.cjs");
|
|
3
|
+
//#region src/upload/retry.ts
|
|
4
|
+
var freshUrlRetryOverride = { maxRetries: 0 };
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the public default for `retryResponseBodyFailures`. Callers must
|
|
7
|
+
* opt into replaying ambiguous upload POST failures for every upload mode.
|
|
8
|
+
*
|
|
9
|
+
* @param value - Caller-provided override, if any.
|
|
10
|
+
*
|
|
11
|
+
* @returns The boolean value passed to the upload retry helper.
|
|
12
|
+
*/
|
|
13
|
+
function resolveRetryResponseBodyFailures(value) {
|
|
14
|
+
return value ?? false;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Fetches a small-file upload URL, bypassing the pool.
|
|
18
|
+
*
|
|
19
|
+
* @param raw - Low-level B2 API client.
|
|
20
|
+
* @param accountInfo - Authorized account state.
|
|
21
|
+
* @param bucketId - Bucket to upload into.
|
|
22
|
+
* @param signal - Optional abort signal for the fresh URL request.
|
|
23
|
+
*
|
|
24
|
+
* @returns A fresh upload URL entry.
|
|
25
|
+
*/
|
|
26
|
+
async function fetchFreshUploadUrl(raw, accountInfo, bucketId, signal) {
|
|
27
|
+
const resp = await raw.getUploadUrl(accountInfo.getApiUrl(), accountInfo.getAuthToken(), { bucketId }, {
|
|
28
|
+
...signal !== void 0 ? { signal } : {},
|
|
29
|
+
retry: freshUrlRetryOverride
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
uploadUrl: resp.uploadUrl,
|
|
33
|
+
authorizationToken: resp.authorizationToken
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Fetches a large-file part upload URL, bypassing the pool.
|
|
38
|
+
*
|
|
39
|
+
* @param raw - Low-level B2 API client.
|
|
40
|
+
* @param accountInfo - Authorized account state.
|
|
41
|
+
* @param fileId - Large file to upload a part into.
|
|
42
|
+
* @param signal - Optional abort signal for the fresh URL request.
|
|
43
|
+
*
|
|
44
|
+
* @returns A fresh part upload URL entry.
|
|
45
|
+
*/
|
|
46
|
+
async function fetchFreshPartUploadUrl(raw, accountInfo, fileId, signal) {
|
|
47
|
+
const resp = await raw.getUploadPartUrl(accountInfo.getApiUrl(), accountInfo.getAuthToken(), { fileId }, {
|
|
48
|
+
...signal !== void 0 ? { signal } : {},
|
|
49
|
+
retry: freshUrlRetryOverride
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
uploadUrl: resp.uploadUrl,
|
|
53
|
+
authorizationToken: resp.authorizationToken
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Uploads one multipart part with fresh-URL retry.
|
|
58
|
+
*
|
|
59
|
+
* @param raw - Low-level B2 API client.
|
|
60
|
+
* @param accountInfo - Authorized account state.
|
|
61
|
+
* @param fileId - Large file to upload a part into.
|
|
62
|
+
* @param options - Part upload parameters and retry settings.
|
|
63
|
+
*
|
|
64
|
+
* @returns The uploaded part response.
|
|
65
|
+
*/
|
|
66
|
+
function uploadPartWithFreshUrl(raw, accountInfo, fileId, options) {
|
|
67
|
+
return withFreshUploadUrlRetry({
|
|
68
|
+
fileName: options.fileName,
|
|
69
|
+
partNumber: options.partNumber,
|
|
70
|
+
retry: options.retry,
|
|
71
|
+
signal: options.signal,
|
|
72
|
+
onUploadRetry: options.onUploadRetry,
|
|
73
|
+
retryResponseBodyFailures: options.retryResponseBodyFailures,
|
|
74
|
+
checkout: () => accountInfo.checkoutPartUploadUrl(fileId),
|
|
75
|
+
fetchFresh: () => fetchFreshPartUploadUrl(raw, accountInfo, fileId, options.signal),
|
|
76
|
+
returnEntry: (entry) => accountInfo.returnPartUploadUrl(fileId, entry),
|
|
77
|
+
evictEntry: (entry) => accountInfo.evictPartUploadUrl(fileId, entry),
|
|
78
|
+
upload: (entry) => raw.uploadPart(entry.uploadUrl, {
|
|
79
|
+
authorization: entry.authorizationToken,
|
|
80
|
+
partNumber: options.partNumber,
|
|
81
|
+
contentLength: options.contentLength,
|
|
82
|
+
contentSha1: options.contentSha1,
|
|
83
|
+
...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {}
|
|
84
|
+
}, options.data, {
|
|
85
|
+
...options.signal !== void 0 ? { signal: options.signal } : {},
|
|
86
|
+
...options.retry !== void 0 ? { retry: options.retry } : {}
|
|
87
|
+
})
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Runs an upload operation with B2's documented retry flow: evict the failed
|
|
92
|
+
* upload URL, back off, fetch a fresh upload URL, and retry there.
|
|
93
|
+
*
|
|
94
|
+
* For single-request file uploads, sending the POST again after a lost success
|
|
95
|
+
* response can create a duplicate file version. Multipart retries re-send the
|
|
96
|
+
* same part number instead. Response-body retry defaults are caller-specific:
|
|
97
|
+
* single-request uploads keep them off by default, while multipart callers can
|
|
98
|
+
* opt in with `retryResponseBodyFailures: true` when replaying the same part
|
|
99
|
+
* number is acceptable.
|
|
100
|
+
*
|
|
101
|
+
* @param options - URL checkout, upload, eviction, and retry callbacks.
|
|
102
|
+
*
|
|
103
|
+
* @returns The successful upload result.
|
|
104
|
+
*/
|
|
105
|
+
async function withFreshUploadUrlRetry(options) {
|
|
106
|
+
const retryOptions = {
|
|
107
|
+
...require_retry.DEFAULT_RETRY_OPTIONS,
|
|
108
|
+
...options.retry
|
|
109
|
+
};
|
|
110
|
+
for (let attempt = 0; attempt <= retryOptions.maxRetries; attempt++) {
|
|
111
|
+
let uploadEntry;
|
|
112
|
+
let uploadStarted = false;
|
|
113
|
+
try {
|
|
114
|
+
options.signal?.throwIfAborted();
|
|
115
|
+
uploadEntry = attempt === 0 ? options.checkout() ?? await options.fetchFresh() : await options.fetchFresh();
|
|
116
|
+
uploadStarted = true;
|
|
117
|
+
const result = await options.upload(uploadEntry);
|
|
118
|
+
options.returnEntry(uploadEntry);
|
|
119
|
+
return result;
|
|
120
|
+
} catch (err) {
|
|
121
|
+
const retryError = normalizeUploadRetryError(err, options);
|
|
122
|
+
if (uploadEntry !== void 0) if (isUploadRateLimitError(retryError)) options.returnEntry(uploadEntry);
|
|
123
|
+
else options.evictEntry(uploadEntry);
|
|
124
|
+
if (options.signal?.aborted) throw err;
|
|
125
|
+
if (isUploadRateLimitError(retryError) && uploadEntry !== void 0) throw retryError;
|
|
126
|
+
if (!isUploadRetryable(retryError, {
|
|
127
|
+
...options,
|
|
128
|
+
uploadStarted
|
|
129
|
+
}) || attempt === retryOptions.maxRetries) throw retryError;
|
|
130
|
+
const retryAttempt = attempt + 1;
|
|
131
|
+
const retryAfter = retryError instanceof require_errors_index.B2Error ? retryError.retryAfter : void 0;
|
|
132
|
+
const delayMs = require_retry.computeBackoff(attempt, retryOptions, retryAfter);
|
|
133
|
+
notifyUploadRetry(options, {
|
|
134
|
+
fileName: options.fileName,
|
|
135
|
+
partNumber: options.partNumber,
|
|
136
|
+
attempt: retryAttempt,
|
|
137
|
+
maxRetries: retryOptions.maxRetries,
|
|
138
|
+
delayMs,
|
|
139
|
+
error: retryError
|
|
140
|
+
});
|
|
141
|
+
await require_retry.sleep(delayMs, options.signal);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/* v8 ignore next -- defensive return-path guard. */
|
|
145
|
+
throw new require_errors_index.NetworkError("Upload retry budget exhausted");
|
|
146
|
+
}
|
|
147
|
+
function notifyUploadRetry(options, event) {
|
|
148
|
+
try {
|
|
149
|
+
options.onUploadRetry?.(event);
|
|
150
|
+
} catch {}
|
|
151
|
+
}
|
|
152
|
+
function isUploadRetryable(err, options) {
|
|
153
|
+
if (err instanceof require_errors_index.NetworkError) {
|
|
154
|
+
if (err.cause instanceof require_errors_index.B2SsrfError) return false;
|
|
155
|
+
if (!options.uploadStarted) return true;
|
|
156
|
+
return options.retryResponseBodyFailures === true;
|
|
157
|
+
}
|
|
158
|
+
if (err instanceof require_errors_index.BadAuthTokenError) return true;
|
|
159
|
+
if (isUploadUrlInvalidationError(err)) return true;
|
|
160
|
+
return err instanceof require_errors_index.B2Error && err.retryable;
|
|
161
|
+
}
|
|
162
|
+
function isUploadRateLimitError(err) {
|
|
163
|
+
return err instanceof require_errors_index.B2Error && err.status === 429;
|
|
164
|
+
}
|
|
165
|
+
function normalizeUploadRetryError(err, options) {
|
|
166
|
+
if (err instanceof require_errors_index.B2Error || err instanceof require_errors_index.NetworkError) return err;
|
|
167
|
+
if (err instanceof require_errors_index.UploadResponseBodyError) {
|
|
168
|
+
if (!options.retryResponseBodyFailures) return err;
|
|
169
|
+
return new require_errors_index.NetworkError(err.message, err);
|
|
170
|
+
}
|
|
171
|
+
if (err instanceof DOMException && err.name === "AbortError") return err;
|
|
172
|
+
if (err instanceof TypeError || err instanceof SyntaxError || err instanceof DOMException) return new require_errors_index.NetworkError(err instanceof Error ? err.message : "Upload response read failed", err);
|
|
173
|
+
return err;
|
|
174
|
+
}
|
|
175
|
+
function isUploadUrlInvalidationError(err) {
|
|
176
|
+
if (err instanceof require_errors_index.BadUploadUrlError) return true;
|
|
177
|
+
return err instanceof require_errors_index.BadRequestError && /upload url/i.test(err.message);
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
exports.fetchFreshPartUploadUrl = fetchFreshPartUploadUrl;
|
|
181
|
+
exports.fetchFreshUploadUrl = fetchFreshUploadUrl;
|
|
182
|
+
exports.resolveRetryResponseBodyFailures = resolveRetryResponseBodyFailures;
|
|
183
|
+
exports.uploadPartWithFreshUrl = uploadPartWithFreshUrl;
|
|
184
|
+
exports.withFreshUploadUrlRetry = withFreshUploadUrlRetry;
|
|
185
|
+
|
|
186
|
+
//# sourceMappingURL=retry.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.cjs","names":[],"sources":["../../src/upload/retry.ts"],"sourcesContent":["import type { AccountInfo, UploadUrlEntry } from '../auth/account-info.ts'\nimport {\n B2Error,\n B2SsrfError,\n BadAuthTokenError,\n BadRequestError,\n BadUploadUrlError,\n NetworkError,\n UploadResponseBodyError,\n} from '../errors/index.ts'\nimport { computeBackoff, DEFAULT_RETRY_OPTIONS, type RetryOptions, sleep } from '../http/retry.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport type { EncryptionSetting } from '../types/encryption.ts'\nimport type { BucketId, LargeFileId } from '../types/ids.ts'\nimport type { UploadPartResponse } from '../types/upload.ts'\n\n/** Event emitted before an upload is retried against a fresh upload URL. */\nexport interface UploadRetryEvent {\n /** File name being uploaded. */\n readonly fileName: string\n /** Multipart part number, or `null` for a single-request file upload. */\n readonly partNumber: number | null\n /** One-based retry attempt that is about to run. */\n readonly attempt: number\n /** Maximum number of retry attempts allowed for this upload operation. */\n readonly maxRetries: number\n /** Backoff delay in milliseconds before the fresh URL is fetched. */\n readonly delayMs: number\n /** Classified error that triggered the fresh-URL retry. */\n readonly error: B2Error | NetworkError\n}\n\n/** Callback invoked before an upload retry fetches a fresh upload URL. */\nexport type UploadRetryListener = (event: UploadRetryEvent) => void\n\n/** Shared public options for upload-layer fresh-URL retries. */\nexport interface UploadRetryOptions {\n /** Retry settings shared with the main transport retry configuration. */\n readonly retry?: Partial<RetryOptions> | undefined\n /** Callback invoked before a fresh-URL upload retry. */\n readonly onUploadRetry?: UploadRetryListener | undefined\n /**\n * Whether ambiguous failures after an upload POST should be retried,\n * including response-body read failures and transport errors where B2 may\n * have stored the payload before the success response was lost.\n * Defaults to false. Set true only when duplicate versions or parts are\n * acceptable.\n */\n readonly retryResponseBodyFailures?: boolean | undefined\n}\n\ninterface UploadLayerRetryOptions extends Omit<UploadRetryOptions, 'retryResponseBodyFailures'> {\n readonly retryResponseBodyFailures: boolean\n /** Abort signal for cancelling upload attempts and retry backoff sleeps. */\n readonly signal?: AbortSignal | undefined\n}\n\ninterface FreshUrlRetryOptions<T> extends UploadLayerRetryOptions {\n readonly fileName: string\n readonly partNumber: number | null\n readonly checkout: () => UploadUrlEntry | null\n readonly fetchFresh: () => Promise<UploadUrlEntry>\n readonly returnEntry: (entry: UploadUrlEntry) => void\n readonly evictEntry: (entry: UploadUrlEntry) => void\n readonly upload: (entry: UploadUrlEntry) => Promise<T>\n}\n\nconst freshUrlRetryOverride: Partial<RetryOptions> = { maxRetries: 0 }\n\n/**\n * Resolves the public default for `retryResponseBodyFailures`. Callers must\n * opt into replaying ambiguous upload POST failures for every upload mode.\n *\n * @param value - Caller-provided override, if any.\n *\n * @returns The boolean value passed to the upload retry helper.\n */\nexport function resolveRetryResponseBodyFailures(value: boolean | undefined): boolean {\n return value ?? false\n}\n\n/**\n * Fetches a small-file upload URL, bypassing the pool.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state.\n * @param bucketId - Bucket to upload into.\n * @param signal - Optional abort signal for the fresh URL request.\n *\n * @returns A fresh upload URL entry.\n */\nexport async function fetchFreshUploadUrl(\n raw: RawClient,\n accountInfo: AccountInfo,\n bucketId: BucketId,\n signal?: AbortSignal,\n): Promise<UploadUrlEntry> {\n const resp = await raw.getUploadUrl(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n {\n bucketId,\n },\n {\n ...(signal !== undefined ? { signal } : {}),\n retry: freshUrlRetryOverride,\n },\n )\n return { uploadUrl: resp.uploadUrl, authorizationToken: resp.authorizationToken }\n}\n\n/**\n * Fetches a large-file part upload URL, bypassing the pool.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state.\n * @param fileId - Large file to upload a part into.\n * @param signal - Optional abort signal for the fresh URL request.\n *\n * @returns A fresh part upload URL entry.\n */\nexport async function fetchFreshPartUploadUrl(\n raw: RawClient,\n accountInfo: AccountInfo,\n fileId: LargeFileId,\n signal?: AbortSignal,\n): Promise<UploadUrlEntry> {\n const resp = await raw.getUploadPartUrl(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n {\n fileId,\n },\n {\n ...(signal !== undefined ? { signal } : {}),\n retry: freshUrlRetryOverride,\n },\n )\n return { uploadUrl: resp.uploadUrl, authorizationToken: resp.authorizationToken }\n}\n\ninterface UploadPartWithFreshUrlOptions extends UploadLayerRetryOptions {\n /** File name associated with the large-file upload. */\n readonly fileName: string\n /** One-based part number. */\n readonly partNumber: number\n /** Part bytes to upload. */\n readonly data: BodyInit\n /** Number of bytes in the part. */\n readonly contentLength: number\n /** SHA-1 hex digest of the part bytes. */\n readonly contentSha1: string\n /** Server-side encryption settings for this part. */\n readonly serverSideEncryption?: EncryptionSetting | undefined\n}\n\n/**\n * Uploads one multipart part with fresh-URL retry.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state.\n * @param fileId - Large file to upload a part into.\n * @param options - Part upload parameters and retry settings.\n *\n * @returns The uploaded part response.\n */\nexport function uploadPartWithFreshUrl(\n raw: RawClient,\n accountInfo: AccountInfo,\n fileId: LargeFileId,\n options: UploadPartWithFreshUrlOptions,\n): Promise<UploadPartResponse> {\n return withFreshUploadUrlRetry({\n fileName: options.fileName,\n partNumber: options.partNumber,\n retry: options.retry,\n signal: options.signal,\n onUploadRetry: options.onUploadRetry,\n retryResponseBodyFailures: options.retryResponseBodyFailures,\n checkout: () => accountInfo.checkoutPartUploadUrl(fileId),\n fetchFresh: () => fetchFreshPartUploadUrl(raw, accountInfo, fileId, options.signal),\n returnEntry: (entry) => accountInfo.returnPartUploadUrl(fileId, entry),\n evictEntry: (entry) => accountInfo.evictPartUploadUrl(fileId, entry),\n upload: (entry) =>\n raw.uploadPart(\n entry.uploadUrl,\n {\n authorization: entry.authorizationToken,\n partNumber: options.partNumber,\n contentLength: options.contentLength,\n contentSha1: options.contentSha1,\n ...(options.serverSideEncryption !== undefined\n ? { serverSideEncryption: options.serverSideEncryption }\n : {}),\n },\n options.data,\n {\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.retry !== undefined ? { retry: options.retry } : {}),\n },\n ),\n })\n}\n\n/**\n * Runs an upload operation with B2's documented retry flow: evict the failed\n * upload URL, back off, fetch a fresh upload URL, and retry there.\n *\n * For single-request file uploads, sending the POST again after a lost success\n * response can create a duplicate file version. Multipart retries re-send the\n * same part number instead. Response-body retry defaults are caller-specific:\n * single-request uploads keep them off by default, while multipart callers can\n * opt in with `retryResponseBodyFailures: true` when replaying the same part\n * number is acceptable.\n *\n * @param options - URL checkout, upload, eviction, and retry callbacks.\n *\n * @returns The successful upload result.\n */\nexport async function withFreshUploadUrlRetry<T>(options: FreshUrlRetryOptions<T>): Promise<T> {\n const retryOptions = { ...DEFAULT_RETRY_OPTIONS, ...options.retry }\n\n for (let attempt = 0; attempt <= retryOptions.maxRetries; attempt++) {\n let uploadEntry: UploadUrlEntry | undefined\n let uploadStarted = false\n\n try {\n options.signal?.throwIfAborted()\n uploadEntry =\n attempt === 0\n ? (options.checkout() ?? (await options.fetchFresh()))\n : await options.fetchFresh()\n\n uploadStarted = true\n const result = await options.upload(uploadEntry)\n options.returnEntry(uploadEntry)\n return result\n } catch (err) {\n const retryError = normalizeUploadRetryError(err, options)\n if (uploadEntry !== undefined) {\n if (isUploadRateLimitError(retryError)) {\n options.returnEntry(uploadEntry)\n } else {\n options.evictEntry(uploadEntry)\n }\n }\n if (options.signal?.aborted) {\n throw err\n }\n if (isUploadRateLimitError(retryError) && uploadEntry !== undefined) {\n throw retryError\n }\n if (\n !isUploadRetryable(retryError, { ...options, uploadStarted }) ||\n attempt === retryOptions.maxRetries\n ) {\n throw retryError\n }\n\n const retryAttempt = attempt + 1\n const retryAfter = retryError instanceof B2Error ? retryError.retryAfter : undefined\n const delayMs = computeBackoff(attempt, retryOptions, retryAfter)\n notifyUploadRetry(options, {\n fileName: options.fileName,\n partNumber: options.partNumber,\n attempt: retryAttempt,\n maxRetries: retryOptions.maxRetries,\n delayMs,\n error: retryError,\n })\n await sleep(delayMs, options.signal)\n }\n }\n\n // Unreachable at runtime: the loop returns on success or throws from the\n // final failed attempt. This satisfies TypeScript's return-path analysis.\n /* v8 ignore next -- defensive return-path guard. */\n throw new NetworkError('Upload retry budget exhausted')\n}\n\nfunction notifyUploadRetry(options: UploadLayerRetryOptions, event: UploadRetryEvent): void {\n try {\n options.onUploadRetry?.(event)\n } catch {\n // Telemetry observers must not replace the underlying upload failure or\n // prevent a retry that can recover with a fresh upload URL.\n }\n}\n\nfunction isUploadRetryable(\n err: unknown,\n options: UploadLayerRetryOptions & {\n readonly partNumber: number | null\n readonly uploadStarted: boolean\n },\n): err is B2Error | NetworkError {\n if (err instanceof NetworkError) {\n if (err.cause instanceof B2SsrfError) return false\n if (!options.uploadStarted) return true\n return options.retryResponseBodyFailures === true\n }\n if (err instanceof BadAuthTokenError) return true\n if (isUploadUrlInvalidationError(err)) return true\n return err instanceof B2Error && err.retryable\n}\n\nfunction isUploadRateLimitError(err: unknown): err is B2Error {\n return err instanceof B2Error && err.status === 429\n}\n\nfunction normalizeUploadRetryError(err: unknown, options: UploadLayerRetryOptions): unknown {\n if (err instanceof B2Error || err instanceof NetworkError) return err\n if (err instanceof UploadResponseBodyError) {\n if (!options.retryResponseBodyFailures) return err\n return new NetworkError(err.message, err)\n }\n if (err instanceof DOMException && err.name === 'AbortError') return err\n if (err instanceof TypeError || err instanceof SyntaxError || err instanceof DOMException) {\n const message = err instanceof Error ? err.message : 'Upload response read failed'\n return new NetworkError(message, err)\n }\n return err\n}\n\nfunction isUploadUrlInvalidationError(err: unknown): boolean {\n if (err instanceof BadUploadUrlError) return true\n return err instanceof BadRequestError && /upload url/i.test(err.message)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { AccountInfo, UploadUrlEntry } from '../auth/account-info.js';
|
|
2
|
+
import { B2Error, NetworkError } from '../errors/index.js';
|
|
3
|
+
import { RetryOptions } from '../http/retry.js';
|
|
4
|
+
import { RawClient } from '../raw/index.js';
|
|
5
|
+
import { EncryptionSetting } from '../types/encryption.js';
|
|
6
|
+
import { BucketId, LargeFileId } from '../types/ids.js';
|
|
7
|
+
import { UploadPartResponse } from '../types/upload.js';
|
|
8
|
+
/** Event emitted before an upload is retried against a fresh upload URL. */
|
|
9
|
+
export interface UploadRetryEvent {
|
|
10
|
+
/** File name being uploaded. */
|
|
11
|
+
readonly fileName: string;
|
|
12
|
+
/** Multipart part number, or `null` for a single-request file upload. */
|
|
13
|
+
readonly partNumber: number | null;
|
|
14
|
+
/** One-based retry attempt that is about to run. */
|
|
15
|
+
readonly attempt: number;
|
|
16
|
+
/** Maximum number of retry attempts allowed for this upload operation. */
|
|
17
|
+
readonly maxRetries: number;
|
|
18
|
+
/** Backoff delay in milliseconds before the fresh URL is fetched. */
|
|
19
|
+
readonly delayMs: number;
|
|
20
|
+
/** Classified error that triggered the fresh-URL retry. */
|
|
21
|
+
readonly error: B2Error | NetworkError;
|
|
22
|
+
}
|
|
23
|
+
/** Callback invoked before an upload retry fetches a fresh upload URL. */
|
|
24
|
+
export type UploadRetryListener = (event: UploadRetryEvent) => void;
|
|
25
|
+
/** Shared public options for upload-layer fresh-URL retries. */
|
|
26
|
+
export interface UploadRetryOptions {
|
|
27
|
+
/** Retry settings shared with the main transport retry configuration. */
|
|
28
|
+
readonly retry?: Partial<RetryOptions> | undefined;
|
|
29
|
+
/** Callback invoked before a fresh-URL upload retry. */
|
|
30
|
+
readonly onUploadRetry?: UploadRetryListener | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Whether ambiguous failures after an upload POST should be retried,
|
|
33
|
+
* including response-body read failures and transport errors where B2 may
|
|
34
|
+
* have stored the payload before the success response was lost.
|
|
35
|
+
* Defaults to false. Set true only when duplicate versions or parts are
|
|
36
|
+
* acceptable.
|
|
37
|
+
*/
|
|
38
|
+
readonly retryResponseBodyFailures?: boolean | undefined;
|
|
39
|
+
}
|
|
40
|
+
interface UploadLayerRetryOptions extends Omit<UploadRetryOptions, 'retryResponseBodyFailures'> {
|
|
41
|
+
readonly retryResponseBodyFailures: boolean;
|
|
42
|
+
/** Abort signal for cancelling upload attempts and retry backoff sleeps. */
|
|
43
|
+
readonly signal?: AbortSignal | undefined;
|
|
44
|
+
}
|
|
45
|
+
interface FreshUrlRetryOptions<T> extends UploadLayerRetryOptions {
|
|
46
|
+
readonly fileName: string;
|
|
47
|
+
readonly partNumber: number | null;
|
|
48
|
+
readonly checkout: () => UploadUrlEntry | null;
|
|
49
|
+
readonly fetchFresh: () => Promise<UploadUrlEntry>;
|
|
50
|
+
readonly returnEntry: (entry: UploadUrlEntry) => void;
|
|
51
|
+
readonly evictEntry: (entry: UploadUrlEntry) => void;
|
|
52
|
+
readonly upload: (entry: UploadUrlEntry) => Promise<T>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolves the public default for `retryResponseBodyFailures`. Callers must
|
|
56
|
+
* opt into replaying ambiguous upload POST failures for every upload mode.
|
|
57
|
+
*
|
|
58
|
+
* @param value - Caller-provided override, if any.
|
|
59
|
+
*
|
|
60
|
+
* @returns The boolean value passed to the upload retry helper.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveRetryResponseBodyFailures(value: boolean | undefined): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Fetches a small-file upload URL, bypassing the pool.
|
|
65
|
+
*
|
|
66
|
+
* @param raw - Low-level B2 API client.
|
|
67
|
+
* @param accountInfo - Authorized account state.
|
|
68
|
+
* @param bucketId - Bucket to upload into.
|
|
69
|
+
* @param signal - Optional abort signal for the fresh URL request.
|
|
70
|
+
*
|
|
71
|
+
* @returns A fresh upload URL entry.
|
|
72
|
+
*/
|
|
73
|
+
export declare function fetchFreshUploadUrl(raw: RawClient, accountInfo: AccountInfo, bucketId: BucketId, signal?: AbortSignal): Promise<UploadUrlEntry>;
|
|
74
|
+
/**
|
|
75
|
+
* Fetches a large-file part upload URL, bypassing the pool.
|
|
76
|
+
*
|
|
77
|
+
* @param raw - Low-level B2 API client.
|
|
78
|
+
* @param accountInfo - Authorized account state.
|
|
79
|
+
* @param fileId - Large file to upload a part into.
|
|
80
|
+
* @param signal - Optional abort signal for the fresh URL request.
|
|
81
|
+
*
|
|
82
|
+
* @returns A fresh part upload URL entry.
|
|
83
|
+
*/
|
|
84
|
+
export declare function fetchFreshPartUploadUrl(raw: RawClient, accountInfo: AccountInfo, fileId: LargeFileId, signal?: AbortSignal): Promise<UploadUrlEntry>;
|
|
85
|
+
interface UploadPartWithFreshUrlOptions extends UploadLayerRetryOptions {
|
|
86
|
+
/** File name associated with the large-file upload. */
|
|
87
|
+
readonly fileName: string;
|
|
88
|
+
/** One-based part number. */
|
|
89
|
+
readonly partNumber: number;
|
|
90
|
+
/** Part bytes to upload. */
|
|
91
|
+
readonly data: BodyInit;
|
|
92
|
+
/** Number of bytes in the part. */
|
|
93
|
+
readonly contentLength: number;
|
|
94
|
+
/** SHA-1 hex digest of the part bytes. */
|
|
95
|
+
readonly contentSha1: string;
|
|
96
|
+
/** Server-side encryption settings for this part. */
|
|
97
|
+
readonly serverSideEncryption?: EncryptionSetting | undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Uploads one multipart part with fresh-URL retry.
|
|
101
|
+
*
|
|
102
|
+
* @param raw - Low-level B2 API client.
|
|
103
|
+
* @param accountInfo - Authorized account state.
|
|
104
|
+
* @param fileId - Large file to upload a part into.
|
|
105
|
+
* @param options - Part upload parameters and retry settings.
|
|
106
|
+
*
|
|
107
|
+
* @returns The uploaded part response.
|
|
108
|
+
*/
|
|
109
|
+
export declare function uploadPartWithFreshUrl(raw: RawClient, accountInfo: AccountInfo, fileId: LargeFileId, options: UploadPartWithFreshUrlOptions): Promise<UploadPartResponse>;
|
|
110
|
+
/**
|
|
111
|
+
* Runs an upload operation with B2's documented retry flow: evict the failed
|
|
112
|
+
* upload URL, back off, fetch a fresh upload URL, and retry there.
|
|
113
|
+
*
|
|
114
|
+
* For single-request file uploads, sending the POST again after a lost success
|
|
115
|
+
* response can create a duplicate file version. Multipart retries re-send the
|
|
116
|
+
* same part number instead. Response-body retry defaults are caller-specific:
|
|
117
|
+
* single-request uploads keep them off by default, while multipart callers can
|
|
118
|
+
* opt in with `retryResponseBodyFailures: true` when replaying the same part
|
|
119
|
+
* number is acceptable.
|
|
120
|
+
*
|
|
121
|
+
* @param options - URL checkout, upload, eviction, and retry callbacks.
|
|
122
|
+
*
|
|
123
|
+
* @returns The successful upload result.
|
|
124
|
+
*/
|
|
125
|
+
export declare function withFreshUploadUrlRetry<T>(options: FreshUrlRetryOptions<T>): Promise<T>;
|
|
126
|
+
export {};
|
|
127
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/upload/retry.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,EACL,OAAO,EAKP,YAAY,EAEb,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAyC,KAAK,YAAY,EAAS,MAAM,kBAAkB,CAAA;AAClG,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE5D,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,yEAAyE;IACzE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,oDAAoD;IACpD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAAA;CACvC;AAED,0EAA0E;AAC1E,MAAM,MAAM,mBAAmB,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAA;AAEnE,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;IAClD,wDAAwD;IACxD,QAAQ,CAAC,aAAa,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAA;IACxD;;;;;;OAMG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CACzD;AAED,UAAU,uBAAwB,SAAQ,IAAI,CAAC,kBAAkB,EAAE,2BAA2B,CAAC;IAC7F,QAAQ,CAAC,yBAAyB,EAAE,OAAO,CAAA;IAC3C,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;CAC1C;AAED,UAAU,oBAAoB,CAAC,CAAC,CAAE,SAAQ,uBAAuB;IAC/D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,cAAc,GAAG,IAAI,CAAA;IAC9C,QAAQ,CAAC,UAAU,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,CAAA;IAClD,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;IACrD,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAA;IACpD,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,CAAA;CACvD;AAID;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAEpF;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,EAClB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAazB;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,WAAW,EACnB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,cAAc,CAAC,CAazB;AAED,UAAU,6BAA8B,SAAQ,uBAAuB;IACrE,uDAAuD;IACvD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,6BAA6B;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,mCAAmC;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,0CAA0C;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAA;CAC9D;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,SAAS,EACd,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,kBAAkB,CAAC,CA+B7B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,uBAAuB,CAAC,CAAC,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA2D7F"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { AccountInfo, UploadUrlEntry } from '../auth/account-info.js';
|
|
2
|
+
import { B2Error, NetworkError } from '../errors/index.js';
|
|
3
|
+
import { RetryOptions } from '../http/retry.js';
|
|
4
|
+
import { RawClient } from '../raw/index.js';
|
|
5
|
+
import { EncryptionSetting } from '../types/encryption.js';
|
|
6
|
+
import { BucketId, LargeFileId } from '../types/ids.js';
|
|
7
|
+
import { UploadPartResponse } from '../types/upload.js';
|
|
8
|
+
/** Event emitted before an upload is retried against a fresh upload URL. */
|
|
9
|
+
export interface UploadRetryEvent {
|
|
10
|
+
/** File name being uploaded. */
|
|
11
|
+
readonly fileName: string;
|
|
12
|
+
/** Multipart part number, or `null` for a single-request file upload. */
|
|
13
|
+
readonly partNumber: number | null;
|
|
14
|
+
/** One-based retry attempt that is about to run. */
|
|
15
|
+
readonly attempt: number;
|
|
16
|
+
/** Maximum number of retry attempts allowed for this upload operation. */
|
|
17
|
+
readonly maxRetries: number;
|
|
18
|
+
/** Backoff delay in milliseconds before the fresh URL is fetched. */
|
|
19
|
+
readonly delayMs: number;
|
|
20
|
+
/** Classified error that triggered the fresh-URL retry. */
|
|
21
|
+
readonly error: B2Error | NetworkError;
|
|
22
|
+
}
|
|
23
|
+
/** Callback invoked before an upload retry fetches a fresh upload URL. */
|
|
24
|
+
export type UploadRetryListener = (event: UploadRetryEvent) => void;
|
|
25
|
+
/** Shared public options for upload-layer fresh-URL retries. */
|
|
26
|
+
export interface UploadRetryOptions {
|
|
27
|
+
/** Retry settings shared with the main transport retry configuration. */
|
|
28
|
+
readonly retry?: Partial<RetryOptions> | undefined;
|
|
29
|
+
/** Callback invoked before a fresh-URL upload retry. */
|
|
30
|
+
readonly onUploadRetry?: UploadRetryListener | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Whether ambiguous failures after an upload POST should be retried,
|
|
33
|
+
* including response-body read failures and transport errors where B2 may
|
|
34
|
+
* have stored the payload before the success response was lost.
|
|
35
|
+
* Defaults to false. Set true only when duplicate versions or parts are
|
|
36
|
+
* acceptable.
|
|
37
|
+
*/
|
|
38
|
+
readonly retryResponseBodyFailures?: boolean | undefined;
|
|
39
|
+
}
|
|
40
|
+
interface UploadLayerRetryOptions extends Omit<UploadRetryOptions, 'retryResponseBodyFailures'> {
|
|
41
|
+
readonly retryResponseBodyFailures: boolean;
|
|
42
|
+
/** Abort signal for cancelling upload attempts and retry backoff sleeps. */
|
|
43
|
+
readonly signal?: AbortSignal | undefined;
|
|
44
|
+
}
|
|
45
|
+
interface FreshUrlRetryOptions<T> extends UploadLayerRetryOptions {
|
|
46
|
+
readonly fileName: string;
|
|
47
|
+
readonly partNumber: number | null;
|
|
48
|
+
readonly checkout: () => UploadUrlEntry | null;
|
|
49
|
+
readonly fetchFresh: () => Promise<UploadUrlEntry>;
|
|
50
|
+
readonly returnEntry: (entry: UploadUrlEntry) => void;
|
|
51
|
+
readonly evictEntry: (entry: UploadUrlEntry) => void;
|
|
52
|
+
readonly upload: (entry: UploadUrlEntry) => Promise<T>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolves the public default for `retryResponseBodyFailures`. Callers must
|
|
56
|
+
* opt into replaying ambiguous upload POST failures for every upload mode.
|
|
57
|
+
*
|
|
58
|
+
* @param value - Caller-provided override, if any.
|
|
59
|
+
*
|
|
60
|
+
* @returns The boolean value passed to the upload retry helper.
|
|
61
|
+
*/
|
|
62
|
+
export declare function resolveRetryResponseBodyFailures(value: boolean | undefined): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Fetches a small-file upload URL, bypassing the pool.
|
|
65
|
+
*
|
|
66
|
+
* @param raw - Low-level B2 API client.
|
|
67
|
+
* @param accountInfo - Authorized account state.
|
|
68
|
+
* @param bucketId - Bucket to upload into.
|
|
69
|
+
* @param signal - Optional abort signal for the fresh URL request.
|
|
70
|
+
*
|
|
71
|
+
* @returns A fresh upload URL entry.
|
|
72
|
+
*/
|
|
73
|
+
export declare function fetchFreshUploadUrl(raw: RawClient, accountInfo: AccountInfo, bucketId: BucketId, signal?: AbortSignal): Promise<UploadUrlEntry>;
|
|
74
|
+
/**
|
|
75
|
+
* Fetches a large-file part upload URL, bypassing the pool.
|
|
76
|
+
*
|
|
77
|
+
* @param raw - Low-level B2 API client.
|
|
78
|
+
* @param accountInfo - Authorized account state.
|
|
79
|
+
* @param fileId - Large file to upload a part into.
|
|
80
|
+
* @param signal - Optional abort signal for the fresh URL request.
|
|
81
|
+
*
|
|
82
|
+
* @returns A fresh part upload URL entry.
|
|
83
|
+
*/
|
|
84
|
+
export declare function fetchFreshPartUploadUrl(raw: RawClient, accountInfo: AccountInfo, fileId: LargeFileId, signal?: AbortSignal): Promise<UploadUrlEntry>;
|
|
85
|
+
interface UploadPartWithFreshUrlOptions extends UploadLayerRetryOptions {
|
|
86
|
+
/** File name associated with the large-file upload. */
|
|
87
|
+
readonly fileName: string;
|
|
88
|
+
/** One-based part number. */
|
|
89
|
+
readonly partNumber: number;
|
|
90
|
+
/** Part bytes to upload. */
|
|
91
|
+
readonly data: BodyInit;
|
|
92
|
+
/** Number of bytes in the part. */
|
|
93
|
+
readonly contentLength: number;
|
|
94
|
+
/** SHA-1 hex digest of the part bytes. */
|
|
95
|
+
readonly contentSha1: string;
|
|
96
|
+
/** Server-side encryption settings for this part. */
|
|
97
|
+
readonly serverSideEncryption?: EncryptionSetting | undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Uploads one multipart part with fresh-URL retry.
|
|
101
|
+
*
|
|
102
|
+
* @param raw - Low-level B2 API client.
|
|
103
|
+
* @param accountInfo - Authorized account state.
|
|
104
|
+
* @param fileId - Large file to upload a part into.
|
|
105
|
+
* @param options - Part upload parameters and retry settings.
|
|
106
|
+
*
|
|
107
|
+
* @returns The uploaded part response.
|
|
108
|
+
*/
|
|
109
|
+
export declare function uploadPartWithFreshUrl(raw: RawClient, accountInfo: AccountInfo, fileId: LargeFileId, options: UploadPartWithFreshUrlOptions): Promise<UploadPartResponse>;
|
|
110
|
+
/**
|
|
111
|
+
* Runs an upload operation with B2's documented retry flow: evict the failed
|
|
112
|
+
* upload URL, back off, fetch a fresh upload URL, and retry there.
|
|
113
|
+
*
|
|
114
|
+
* For single-request file uploads, sending the POST again after a lost success
|
|
115
|
+
* response can create a duplicate file version. Multipart retries re-send the
|
|
116
|
+
* same part number instead. Response-body retry defaults are caller-specific:
|
|
117
|
+
* single-request uploads keep them off by default, while multipart callers can
|
|
118
|
+
* opt in with `retryResponseBodyFailures: true` when replaying the same part
|
|
119
|
+
* number is acceptable.
|
|
120
|
+
*
|
|
121
|
+
* @param options - URL checkout, upload, eviction, and retry callbacks.
|
|
122
|
+
*
|
|
123
|
+
* @returns The successful upload result.
|
|
124
|
+
*/
|
|
125
|
+
export declare function withFreshUploadUrlRetry<T>(options: FreshUrlRetryOptions<T>): Promise<T>;
|
|
126
|
+
export {};
|
|
127
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/upload/retry.js"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { B2Error, B2SsrfError, BadAuthTokenError, BadRequestError, BadUploadUrlError, NetworkError, UploadResponseBodyError } from "../errors/index.js";
|
|
2
|
+
import { DEFAULT_RETRY_OPTIONS, computeBackoff, sleep } from "../http/retry.js";
|
|
3
|
+
//#region src/upload/retry.ts
|
|
4
|
+
var freshUrlRetryOverride = { maxRetries: 0 };
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the public default for `retryResponseBodyFailures`. Callers must
|
|
7
|
+
* opt into replaying ambiguous upload POST failures for every upload mode.
|
|
8
|
+
*
|
|
9
|
+
* @param value - Caller-provided override, if any.
|
|
10
|
+
*
|
|
11
|
+
* @returns The boolean value passed to the upload retry helper.
|
|
12
|
+
*/
|
|
13
|
+
function resolveRetryResponseBodyFailures(value) {
|
|
14
|
+
return value ?? false;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Fetches a small-file upload URL, bypassing the pool.
|
|
18
|
+
*
|
|
19
|
+
* @param raw - Low-level B2 API client.
|
|
20
|
+
* @param accountInfo - Authorized account state.
|
|
21
|
+
* @param bucketId - Bucket to upload into.
|
|
22
|
+
* @param signal - Optional abort signal for the fresh URL request.
|
|
23
|
+
*
|
|
24
|
+
* @returns A fresh upload URL entry.
|
|
25
|
+
*/
|
|
26
|
+
async function fetchFreshUploadUrl(raw, accountInfo, bucketId, signal) {
|
|
27
|
+
const resp = await raw.getUploadUrl(accountInfo.getApiUrl(), accountInfo.getAuthToken(), { bucketId }, {
|
|
28
|
+
...signal !== void 0 ? { signal } : {},
|
|
29
|
+
retry: freshUrlRetryOverride
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
uploadUrl: resp.uploadUrl,
|
|
33
|
+
authorizationToken: resp.authorizationToken
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Fetches a large-file part upload URL, bypassing the pool.
|
|
38
|
+
*
|
|
39
|
+
* @param raw - Low-level B2 API client.
|
|
40
|
+
* @param accountInfo - Authorized account state.
|
|
41
|
+
* @param fileId - Large file to upload a part into.
|
|
42
|
+
* @param signal - Optional abort signal for the fresh URL request.
|
|
43
|
+
*
|
|
44
|
+
* @returns A fresh part upload URL entry.
|
|
45
|
+
*/
|
|
46
|
+
async function fetchFreshPartUploadUrl(raw, accountInfo, fileId, signal) {
|
|
47
|
+
const resp = await raw.getUploadPartUrl(accountInfo.getApiUrl(), accountInfo.getAuthToken(), { fileId }, {
|
|
48
|
+
...signal !== void 0 ? { signal } : {},
|
|
49
|
+
retry: freshUrlRetryOverride
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
uploadUrl: resp.uploadUrl,
|
|
53
|
+
authorizationToken: resp.authorizationToken
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Uploads one multipart part with fresh-URL retry.
|
|
58
|
+
*
|
|
59
|
+
* @param raw - Low-level B2 API client.
|
|
60
|
+
* @param accountInfo - Authorized account state.
|
|
61
|
+
* @param fileId - Large file to upload a part into.
|
|
62
|
+
* @param options - Part upload parameters and retry settings.
|
|
63
|
+
*
|
|
64
|
+
* @returns The uploaded part response.
|
|
65
|
+
*/
|
|
66
|
+
function uploadPartWithFreshUrl(raw, accountInfo, fileId, options) {
|
|
67
|
+
return withFreshUploadUrlRetry({
|
|
68
|
+
fileName: options.fileName,
|
|
69
|
+
partNumber: options.partNumber,
|
|
70
|
+
retry: options.retry,
|
|
71
|
+
signal: options.signal,
|
|
72
|
+
onUploadRetry: options.onUploadRetry,
|
|
73
|
+
retryResponseBodyFailures: options.retryResponseBodyFailures,
|
|
74
|
+
checkout: () => accountInfo.checkoutPartUploadUrl(fileId),
|
|
75
|
+
fetchFresh: () => fetchFreshPartUploadUrl(raw, accountInfo, fileId, options.signal),
|
|
76
|
+
returnEntry: (entry) => accountInfo.returnPartUploadUrl(fileId, entry),
|
|
77
|
+
evictEntry: (entry) => accountInfo.evictPartUploadUrl(fileId, entry),
|
|
78
|
+
upload: (entry) => raw.uploadPart(entry.uploadUrl, {
|
|
79
|
+
authorization: entry.authorizationToken,
|
|
80
|
+
partNumber: options.partNumber,
|
|
81
|
+
contentLength: options.contentLength,
|
|
82
|
+
contentSha1: options.contentSha1,
|
|
83
|
+
...options.serverSideEncryption !== void 0 ? { serverSideEncryption: options.serverSideEncryption } : {}
|
|
84
|
+
}, options.data, {
|
|
85
|
+
...options.signal !== void 0 ? { signal: options.signal } : {},
|
|
86
|
+
...options.retry !== void 0 ? { retry: options.retry } : {}
|
|
87
|
+
})
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Runs an upload operation with B2's documented retry flow: evict the failed
|
|
92
|
+
* upload URL, back off, fetch a fresh upload URL, and retry there.
|
|
93
|
+
*
|
|
94
|
+
* For single-request file uploads, sending the POST again after a lost success
|
|
95
|
+
* response can create a duplicate file version. Multipart retries re-send the
|
|
96
|
+
* same part number instead. Response-body retry defaults are caller-specific:
|
|
97
|
+
* single-request uploads keep them off by default, while multipart callers can
|
|
98
|
+
* opt in with `retryResponseBodyFailures: true` when replaying the same part
|
|
99
|
+
* number is acceptable.
|
|
100
|
+
*
|
|
101
|
+
* @param options - URL checkout, upload, eviction, and retry callbacks.
|
|
102
|
+
*
|
|
103
|
+
* @returns The successful upload result.
|
|
104
|
+
*/
|
|
105
|
+
async function withFreshUploadUrlRetry(options) {
|
|
106
|
+
const retryOptions = {
|
|
107
|
+
...DEFAULT_RETRY_OPTIONS,
|
|
108
|
+
...options.retry
|
|
109
|
+
};
|
|
110
|
+
for (let attempt = 0; attempt <= retryOptions.maxRetries; attempt++) {
|
|
111
|
+
let uploadEntry;
|
|
112
|
+
let uploadStarted = false;
|
|
113
|
+
try {
|
|
114
|
+
options.signal?.throwIfAborted();
|
|
115
|
+
uploadEntry = attempt === 0 ? options.checkout() ?? await options.fetchFresh() : await options.fetchFresh();
|
|
116
|
+
uploadStarted = true;
|
|
117
|
+
const result = await options.upload(uploadEntry);
|
|
118
|
+
options.returnEntry(uploadEntry);
|
|
119
|
+
return result;
|
|
120
|
+
} catch (err) {
|
|
121
|
+
const retryError = normalizeUploadRetryError(err, options);
|
|
122
|
+
if (uploadEntry !== void 0) if (isUploadRateLimitError(retryError)) options.returnEntry(uploadEntry);
|
|
123
|
+
else options.evictEntry(uploadEntry);
|
|
124
|
+
if (options.signal?.aborted) throw err;
|
|
125
|
+
if (isUploadRateLimitError(retryError) && uploadEntry !== void 0) throw retryError;
|
|
126
|
+
if (!isUploadRetryable(retryError, {
|
|
127
|
+
...options,
|
|
128
|
+
uploadStarted
|
|
129
|
+
}) || attempt === retryOptions.maxRetries) throw retryError;
|
|
130
|
+
const retryAttempt = attempt + 1;
|
|
131
|
+
const retryAfter = retryError instanceof B2Error ? retryError.retryAfter : void 0;
|
|
132
|
+
const delayMs = computeBackoff(attempt, retryOptions, retryAfter);
|
|
133
|
+
notifyUploadRetry(options, {
|
|
134
|
+
fileName: options.fileName,
|
|
135
|
+
partNumber: options.partNumber,
|
|
136
|
+
attempt: retryAttempt,
|
|
137
|
+
maxRetries: retryOptions.maxRetries,
|
|
138
|
+
delayMs,
|
|
139
|
+
error: retryError
|
|
140
|
+
});
|
|
141
|
+
await sleep(delayMs, options.signal);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/* v8 ignore next -- defensive return-path guard. */
|
|
145
|
+
throw new NetworkError("Upload retry budget exhausted");
|
|
146
|
+
}
|
|
147
|
+
function notifyUploadRetry(options, event) {
|
|
148
|
+
try {
|
|
149
|
+
options.onUploadRetry?.(event);
|
|
150
|
+
} catch {}
|
|
151
|
+
}
|
|
152
|
+
function isUploadRetryable(err, options) {
|
|
153
|
+
if (err instanceof NetworkError) {
|
|
154
|
+
if (err.cause instanceof B2SsrfError) return false;
|
|
155
|
+
if (!options.uploadStarted) return true;
|
|
156
|
+
return options.retryResponseBodyFailures === true;
|
|
157
|
+
}
|
|
158
|
+
if (err instanceof BadAuthTokenError) return true;
|
|
159
|
+
if (isUploadUrlInvalidationError(err)) return true;
|
|
160
|
+
return err instanceof B2Error && err.retryable;
|
|
161
|
+
}
|
|
162
|
+
function isUploadRateLimitError(err) {
|
|
163
|
+
return err instanceof B2Error && err.status === 429;
|
|
164
|
+
}
|
|
165
|
+
function normalizeUploadRetryError(err, options) {
|
|
166
|
+
if (err instanceof B2Error || err instanceof NetworkError) return err;
|
|
167
|
+
if (err instanceof UploadResponseBodyError) {
|
|
168
|
+
if (!options.retryResponseBodyFailures) return err;
|
|
169
|
+
return new NetworkError(err.message, err);
|
|
170
|
+
}
|
|
171
|
+
if (err instanceof DOMException && err.name === "AbortError") return err;
|
|
172
|
+
if (err instanceof TypeError || err instanceof SyntaxError || err instanceof DOMException) return new NetworkError(err instanceof Error ? err.message : "Upload response read failed", err);
|
|
173
|
+
return err;
|
|
174
|
+
}
|
|
175
|
+
function isUploadUrlInvalidationError(err) {
|
|
176
|
+
if (err instanceof BadUploadUrlError) return true;
|
|
177
|
+
return err instanceof BadRequestError && /upload url/i.test(err.message);
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
export { fetchFreshPartUploadUrl, fetchFreshUploadUrl, resolveRetryResponseBodyFailures, uploadPartWithFreshUrl, withFreshUploadUrlRetry };
|
|
181
|
+
|
|
182
|
+
//# sourceMappingURL=retry.js.map
|