@backblaze-labs/b2-sdk 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +86 -1
- package/README.md +38 -7
- package/dist/_virtual/_b2-sdk-version-json.cjs +1 -1
- package/dist/_virtual/_b2-sdk-version-json.js +1 -1
- package/dist/auth/file.cjs.map +1 -1
- package/dist/auth/reauth-coalescer.cjs +65 -0
- package/dist/auth/reauth-coalescer.cjs.map +1 -0
- package/dist/auth/reauth-coalescer.d.cts +34 -0
- package/dist/auth/reauth-coalescer.d.cts.map +1 -0
- package/dist/auth/reauth-coalescer.d.ts +34 -0
- package/dist/auth/reauth-coalescer.d.ts.map +1 -0
- package/dist/auth/reauth-coalescer.js +65 -0
- package/dist/auth/reauth-coalescer.js.map +1 -0
- package/dist/backup/client.cjs +206 -0
- package/dist/backup/client.cjs.map +1 -0
- package/dist/backup/client.d.cts +238 -0
- package/dist/backup/client.d.cts.map +1 -0
- package/dist/backup/client.d.ts +238 -0
- package/dist/backup/client.d.ts.map +1 -0
- package/dist/backup/client.js +206 -0
- package/dist/backup/client.js.map +1 -0
- package/dist/backup/index.cjs +15 -0
- package/dist/backup/index.d.cts +22 -0
- package/dist/backup/index.d.cts.map +1 -0
- package/dist/backup/index.d.ts +22 -0
- package/dist/backup/index.d.ts.map +1 -0
- package/dist/backup/index.js +7 -0
- package/dist/backup/raw.cjs +168 -0
- package/dist/backup/raw.cjs.map +1 -0
- package/dist/backup/raw.d.cts +122 -0
- package/dist/backup/raw.d.cts.map +1 -0
- package/dist/backup/raw.d.ts +122 -0
- package/dist/backup/raw.d.ts.map +1 -0
- package/dist/backup/raw.js +168 -0
- package/dist/backup/raw.js.map +1 -0
- package/dist/bucket-validation.cjs +111 -0
- package/dist/bucket-validation.cjs.map +1 -0
- package/dist/bucket-validation.d.cts +27 -0
- package/dist/bucket-validation.d.cts.map +1 -0
- package/dist/bucket-validation.d.ts +27 -0
- package/dist/bucket-validation.d.ts.map +1 -0
- package/dist/bucket-validation.js +109 -0
- package/dist/bucket-validation.js.map +1 -0
- package/dist/bucket.cjs +125 -74
- package/dist/bucket.cjs.map +1 -1
- package/dist/bucket.d.cts +156 -61
- package/dist/bucket.d.cts.map +1 -1
- package/dist/bucket.d.ts +156 -61
- package/dist/bucket.d.ts.map +1 -1
- package/dist/bucket.js +125 -74
- package/dist/bucket.js.map +1 -1
- package/dist/client.cjs +29 -8
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +30 -9
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.ts +30 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +29 -8
- package/dist/client.js.map +1 -1
- package/dist/copy/large.cjs +5 -3
- package/dist/copy/large.cjs.map +1 -1
- package/dist/copy/large.d.cts.map +1 -1
- package/dist/copy/large.d.ts.map +1 -1
- package/dist/copy/large.js +5 -3
- package/dist/copy/large.js.map +1 -1
- package/dist/download/checksum.cjs +6 -2
- package/dist/download/checksum.cjs.map +1 -1
- package/dist/download/checksum.js +6 -2
- package/dist/download/checksum.js.map +1 -1
- package/dist/download/parallel.cjs +52 -15
- package/dist/download/parallel.cjs.map +1 -1
- package/dist/download/parallel.d.cts +8 -1
- package/dist/download/parallel.d.cts.map +1 -1
- package/dist/download/parallel.d.ts +8 -1
- package/dist/download/parallel.d.ts.map +1 -1
- package/dist/download/parallel.js +52 -15
- package/dist/download/parallel.js.map +1 -1
- package/dist/download/single.cjs +179 -19
- package/dist/download/single.cjs.map +1 -1
- package/dist/download/single.d.cts +10 -4
- package/dist/download/single.d.cts.map +1 -1
- package/dist/download/single.d.ts +10 -4
- package/dist/download/single.d.ts.map +1 -1
- package/dist/download/single.js +179 -19
- package/dist/download/single.js.map +1 -1
- package/dist/errors/index.cjs +196 -3
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.cts +134 -0
- package/dist/errors/index.d.cts.map +1 -1
- package/dist/errors/index.d.ts +134 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +183 -4
- package/dist/errors/index.js.map +1 -1
- package/dist/http/non-idempotent-mutations.cjs +38 -0
- package/dist/http/non-idempotent-mutations.cjs.map +1 -0
- package/dist/http/non-idempotent-mutations.d.cts +25 -0
- package/dist/http/non-idempotent-mutations.d.cts.map +1 -0
- package/dist/http/non-idempotent-mutations.d.ts +25 -0
- package/dist/http/non-idempotent-mutations.d.ts.map +1 -0
- package/dist/http/non-idempotent-mutations.js +35 -0
- package/dist/http/non-idempotent-mutations.js.map +1 -0
- package/dist/http/retry.cjs +1 -1
- package/dist/http/retry.cjs.map +1 -1
- package/dist/http/retry.js +1 -1
- package/dist/http/retry.js.map +1 -1
- package/dist/http/transport.cjs +62 -23
- package/dist/http/transport.cjs.map +1 -1
- package/dist/http/transport.d.cts +30 -3
- package/dist/http/transport.d.cts.map +1 -1
- package/dist/http/transport.d.ts +30 -3
- package/dist/http/transport.d.ts.map +1 -1
- package/dist/http/transport.js +60 -22
- package/dist/http/transport.js.map +1 -1
- package/dist/http/user-agent.cjs +12 -1
- package/dist/http/user-agent.cjs.map +1 -1
- package/dist/http/user-agent.d.cts +8 -0
- package/dist/http/user-agent.d.cts.map +1 -1
- package/dist/http/user-agent.d.ts +8 -0
- package/dist/http/user-agent.d.ts.map +1 -1
- package/dist/http/user-agent.js +13 -3
- package/dist/http/user-agent.js.map +1 -1
- package/dist/index.cjs +50 -2
- package/dist/index.d.cts +15 -12
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +15 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -10
- package/dist/notifications/index.cjs +3 -0
- package/dist/notifications/index.d.cts +2 -0
- package/dist/notifications/index.d.cts.map +1 -1
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +2 -1
- package/dist/object.cjs +13 -2
- package/dist/object.cjs.map +1 -1
- package/dist/object.d.cts +11 -3
- package/dist/object.d.cts.map +1 -1
- package/dist/object.d.ts +11 -3
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +13 -2
- package/dist/object.js.map +1 -1
- package/dist/partner/account-info.d.cts +43 -0
- package/dist/partner/account-info.d.cts.map +1 -0
- package/dist/partner/account-info.d.ts +43 -0
- package/dist/partner/account-info.d.ts.map +1 -0
- package/dist/partner/auth-clone.cjs +64 -0
- package/dist/partner/auth-clone.cjs.map +1 -0
- package/dist/partner/auth-clone.d.cts +27 -0
- package/dist/partner/auth-clone.d.cts.map +1 -0
- package/dist/partner/auth-clone.d.ts +27 -0
- package/dist/partner/auth-clone.d.ts.map +1 -0
- package/dist/partner/auth-clone.js +63 -0
- package/dist/partner/auth-clone.js.map +1 -0
- package/dist/partner/auth-core.cjs +156 -0
- package/dist/partner/auth-core.cjs.map +1 -0
- package/dist/partner/auth-core.d.cts +111 -0
- package/dist/partner/auth-core.d.cts.map +1 -0
- package/dist/partner/auth-core.d.ts +111 -0
- package/dist/partner/auth-core.d.ts.map +1 -0
- package/dist/partner/auth-core.js +156 -0
- package/dist/partner/auth-core.js.map +1 -0
- package/dist/partner/auth-shape.cjs +36 -0
- package/dist/partner/auth-shape.cjs.map +1 -0
- package/dist/partner/auth-shape.d.cts +12 -0
- package/dist/partner/auth-shape.d.cts.map +1 -0
- package/dist/partner/auth-shape.d.ts +12 -0
- package/dist/partner/auth-shape.d.ts.map +1 -0
- package/dist/partner/auth-shape.js +36 -0
- package/dist/partner/auth-shape.js.map +1 -0
- package/dist/partner/client.cjs +270 -0
- package/dist/partner/client.cjs.map +1 -0
- package/dist/partner/client.d.cts +357 -0
- package/dist/partner/client.d.cts.map +1 -0
- package/dist/partner/client.d.ts +357 -0
- package/dist/partner/client.d.ts.map +1 -0
- package/dist/partner/client.js +270 -0
- package/dist/partner/client.js.map +1 -0
- package/dist/partner/endpoint-url.cjs +109 -0
- package/dist/partner/endpoint-url.cjs.map +1 -0
- package/dist/partner/endpoint-url.d.cts +74 -0
- package/dist/partner/endpoint-url.d.cts.map +1 -0
- package/dist/partner/endpoint-url.d.ts +74 -0
- package/dist/partner/endpoint-url.d.ts.map +1 -0
- package/dist/partner/endpoint-url.js +106 -0
- package/dist/partner/endpoint-url.js.map +1 -0
- package/dist/partner/in-memory.cjs +135 -0
- package/dist/partner/in-memory.cjs.map +1 -0
- package/dist/partner/in-memory.d.cts +99 -0
- package/dist/partner/in-memory.d.cts.map +1 -0
- package/dist/partner/in-memory.d.ts +99 -0
- package/dist/partner/in-memory.d.ts.map +1 -0
- package/dist/partner/in-memory.js +135 -0
- package/dist/partner/in-memory.js.map +1 -0
- package/dist/partner/index.cjs +27 -0
- package/dist/partner/index.d.cts +32 -0
- package/dist/partner/index.d.cts.map +1 -0
- package/dist/partner/index.d.ts +32 -0
- package/dist/partner/index.d.ts.map +1 -0
- package/dist/partner/index.js +9 -0
- package/dist/partner/raw.cjs +400 -0
- package/dist/partner/raw.cjs.map +1 -0
- package/dist/partner/raw.d.cts +220 -0
- package/dist/partner/raw.d.cts.map +1 -0
- package/dist/partner/raw.d.ts +220 -0
- package/dist/partner/raw.d.ts.map +1 -0
- package/dist/partner/raw.js +398 -0
- package/dist/partner/raw.js.map +1 -0
- package/dist/partner/redaction-placeholders.cjs +10 -0
- package/dist/partner/redaction-placeholders.cjs.map +1 -0
- package/dist/partner/redaction-placeholders.d.cts +5 -0
- package/dist/partner/redaction-placeholders.d.cts.map +1 -0
- package/dist/partner/redaction-placeholders.d.ts +5 -0
- package/dist/partner/redaction-placeholders.d.ts.map +1 -0
- package/dist/partner/redaction-placeholders.js +9 -0
- package/dist/partner/redaction-placeholders.js.map +1 -0
- package/dist/partner/redaction.cjs +292 -0
- package/dist/partner/redaction.cjs.map +1 -0
- package/dist/partner/redaction.d.cts +158 -0
- package/dist/partner/redaction.d.cts.map +1 -0
- package/dist/partner/redaction.d.ts +158 -0
- package/dist/partner/redaction.d.ts.map +1 -0
- package/dist/partner/redaction.js +281 -0
- package/dist/partner/redaction.js.map +1 -0
- package/dist/raw/encoding.cjs +29 -10
- package/dist/raw/encoding.cjs.map +1 -1
- package/dist/raw/encoding.d.cts +3 -2
- package/dist/raw/encoding.d.cts.map +1 -1
- package/dist/raw/encoding.d.ts +3 -2
- package/dist/raw/encoding.d.ts.map +1 -1
- package/dist/raw/encoding.js +29 -10
- package/dist/raw/encoding.js.map +1 -1
- package/dist/raw/index.cjs +131 -44
- package/dist/raw/index.cjs.map +1 -1
- package/dist/raw/index.d.cts +21 -15
- package/dist/raw/index.d.cts.map +1 -1
- package/dist/raw/index.d.ts +21 -15
- package/dist/raw/index.d.ts.map +1 -1
- package/dist/raw/index.js +114 -45
- package/dist/raw/index.js.map +1 -1
- package/dist/raw/url.cjs +111 -0
- package/dist/raw/url.cjs.map +1 -0
- package/dist/raw/url.d.cts +41 -0
- package/dist/raw/url.d.cts.map +1 -0
- package/dist/raw/url.d.ts +41 -0
- package/dist/raw/url.d.ts.map +1 -0
- package/dist/raw/url.js +110 -0
- package/dist/raw/url.js.map +1 -0
- package/dist/s3/sigv4.cjs +15 -10
- package/dist/s3/sigv4.cjs.map +1 -1
- package/dist/s3/sigv4.js +15 -10
- package/dist/s3/sigv4.js.map +1 -1
- package/dist/simulator/index.cjs +1579 -257
- package/dist/simulator/index.cjs.map +1 -1
- package/dist/simulator/index.d.cts +124 -11
- package/dist/simulator/index.d.cts.map +1 -1
- package/dist/simulator/index.d.ts +124 -11
- package/dist/simulator/index.d.ts.map +1 -1
- package/dist/simulator/index.js +1568 -262
- package/dist/simulator/index.js.map +1 -1
- package/dist/simulator/partner-capabilities.cjs +77 -0
- package/dist/simulator/partner-capabilities.cjs.map +1 -0
- package/dist/simulator/partner-capabilities.d.cts +53 -0
- package/dist/simulator/partner-capabilities.d.cts.map +1 -0
- package/dist/simulator/partner-capabilities.d.ts +53 -0
- package/dist/simulator/partner-capabilities.d.ts.map +1 -0
- package/dist/simulator/partner-capabilities.js +73 -0
- package/dist/simulator/partner-capabilities.js.map +1 -0
- package/dist/simulator/partner.cjs +713 -0
- package/dist/simulator/partner.cjs.map +1 -0
- package/dist/simulator/partner.d.cts +186 -0
- package/dist/simulator/partner.d.cts.map +1 -0
- package/dist/simulator/partner.d.ts +186 -0
- package/dist/simulator/partner.d.ts.map +1 -0
- package/dist/simulator/partner.js +713 -0
- package/dist/simulator/partner.js.map +1 -0
- package/dist/simulator/validation.cjs +732 -25
- package/dist/simulator/validation.cjs.map +1 -1
- package/dist/simulator/validation.d.cts +145 -6
- package/dist/simulator/validation.d.cts.map +1 -1
- package/dist/simulator/validation.d.ts +145 -6
- package/dist/simulator/validation.d.ts.map +1 -1
- package/dist/simulator/validation.js +705 -26
- package/dist/simulator/validation.js.map +1 -1
- package/dist/streams/file-source.cjs +2 -2
- package/dist/streams/file-source.cjs.map +1 -1
- package/dist/streams/file-source.js +2 -2
- package/dist/streams/file-source.js.map +1 -1
- package/dist/streams/hash.cjs +246 -13
- package/dist/streams/hash.cjs.map +1 -1
- package/dist/streams/hash.d.cts +37 -12
- package/dist/streams/hash.d.cts.map +1 -1
- package/dist/streams/hash.d.ts +37 -12
- package/dist/streams/hash.d.ts.map +1 -1
- package/dist/streams/hash.js +246 -15
- package/dist/streams/hash.js.map +1 -1
- package/dist/streams/index.cjs +3 -1
- package/dist/streams/index.d.cts +1 -1
- package/dist/streams/index.d.cts.map +1 -1
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.d.ts.map +1 -1
- package/dist/streams/index.js +3 -3
- package/dist/streams/progress.cjs +63 -4
- package/dist/streams/progress.cjs.map +1 -1
- package/dist/streams/progress.d.cts +28 -2
- package/dist/streams/progress.d.cts.map +1 -1
- package/dist/streams/progress.d.ts +28 -2
- package/dist/streams/progress.d.ts.map +1 -1
- package/dist/streams/progress.js +63 -4
- package/dist/streams/progress.js.map +1 -1
- package/dist/streams/source.cjs +2 -1
- package/dist/streams/source.cjs.map +1 -1
- package/dist/streams/source.js +2 -1
- package/dist/streams/source.js.map +1 -1
- package/dist/sync/b2-sha1-reader.cjs +6 -2
- package/dist/sync/b2-sha1-reader.cjs.map +1 -1
- package/dist/sync/b2-sha1-reader.d.cts.map +1 -1
- package/dist/sync/b2-sha1-reader.d.ts.map +1 -1
- package/dist/sync/b2-sha1-reader.js +6 -2
- package/dist/sync/b2-sha1-reader.js.map +1 -1
- package/dist/sync/download-staging.cjs +156 -43
- package/dist/sync/download-staging.cjs.map +1 -1
- package/dist/sync/download-staging.d.cts +26 -2
- package/dist/sync/download-staging.d.cts.map +1 -1
- package/dist/sync/download-staging.d.ts +26 -2
- package/dist/sync/download-staging.d.ts.map +1 -1
- package/dist/sync/download-staging.js +155 -44
- package/dist/sync/download-staging.js.map +1 -1
- package/dist/sync/filters.cjs.map +1 -1
- package/dist/sync/filters.js.map +1 -1
- package/dist/sync/index.d.cts +1 -1
- package/dist/sync/index.d.cts.map +1 -1
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/local-file-io.cjs +15 -6
- package/dist/sync/local-file-io.cjs.map +1 -1
- package/dist/sync/local-file-io.d.cts +3 -0
- package/dist/sync/local-file-io.d.cts.map +1 -1
- package/dist/sync/local-file-io.d.ts +3 -0
- package/dist/sync/local-file-io.d.ts.map +1 -1
- package/dist/sync/local-file-io.js +15 -6
- package/dist/sync/local-file-io.js.map +1 -1
- package/dist/sync/local-sha1.cjs +6 -15
- package/dist/sync/local-sha1.cjs.map +1 -1
- package/dist/sync/local-sha1.d.cts +0 -8
- package/dist/sync/local-sha1.d.cts.map +1 -1
- package/dist/sync/local-sha1.d.ts +0 -8
- package/dist/sync/local-sha1.d.ts.map +1 -1
- package/dist/sync/local-sha1.js +7 -15
- package/dist/sync/local-sha1.js.map +1 -1
- package/dist/sync/pairing.cjs +1 -0
- package/dist/sync/pairing.cjs.map +1 -1
- package/dist/sync/pairing.js +1 -0
- package/dist/sync/pairing.js.map +1 -1
- package/dist/sync/policies/compare.cjs +5 -3
- package/dist/sync/policies/compare.cjs.map +1 -1
- package/dist/sync/policies/compare.d.cts.map +1 -1
- package/dist/sync/policies/compare.d.ts.map +1 -1
- package/dist/sync/policies/compare.js +6 -4
- package/dist/sync/policies/compare.js.map +1 -1
- package/dist/sync/policies/index.cjs +4 -10
- package/dist/sync/policies/index.cjs.map +1 -1
- package/dist/sync/policies/index.js +4 -10
- package/dist/sync/policies/index.js.map +1 -1
- package/dist/sync/scanners/b2.cjs +4 -2
- package/dist/sync/scanners/b2.cjs.map +1 -1
- package/dist/sync/scanners/b2.d.cts.map +1 -1
- package/dist/sync/scanners/b2.d.ts.map +1 -1
- package/dist/sync/scanners/b2.js +4 -2
- package/dist/sync/scanners/b2.js.map +1 -1
- package/dist/sync/scanners/local.cjs +150 -33
- package/dist/sync/scanners/local.cjs.map +1 -1
- package/dist/sync/scanners/local.d.cts +6 -0
- package/dist/sync/scanners/local.d.cts.map +1 -1
- package/dist/sync/scanners/local.d.ts +6 -0
- package/dist/sync/scanners/local.d.ts.map +1 -1
- package/dist/sync/scanners/local.js +150 -33
- package/dist/sync/scanners/local.js.map +1 -1
- package/dist/sync/synchronizer.cjs +79 -31
- package/dist/sync/synchronizer.cjs.map +1 -1
- package/dist/sync/synchronizer.d.cts +1 -0
- package/dist/sync/synchronizer.d.cts.map +1 -1
- package/dist/sync/synchronizer.d.ts +1 -0
- package/dist/sync/synchronizer.d.ts.map +1 -1
- package/dist/sync/synchronizer.js +79 -31
- package/dist/sync/synchronizer.js.map +1 -1
- package/dist/sync/types.d.cts +19 -3
- package/dist/sync/types.d.cts.map +1 -1
- package/dist/sync/types.d.ts +19 -3
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/types/auth.cjs +4 -0
- package/dist/types/auth.cjs.map +1 -1
- package/dist/types/auth.d.cts +4 -0
- package/dist/types/auth.d.cts.map +1 -1
- package/dist/types/auth.d.ts +4 -0
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/auth.js +4 -0
- package/dist/types/auth.js.map +1 -1
- package/dist/types/backup.d.cts +85 -0
- package/dist/types/backup.d.cts.map +1 -0
- package/dist/types/backup.d.ts +85 -0
- package/dist/types/backup.d.ts.map +1 -0
- package/dist/types/bucket.cjs +81 -11
- package/dist/types/bucket.cjs.map +1 -1
- package/dist/types/bucket.d.cts +194 -41
- package/dist/types/bucket.d.cts.map +1 -1
- package/dist/types/bucket.d.ts +194 -41
- package/dist/types/bucket.d.ts.map +1 -1
- package/dist/types/bucket.js +67 -12
- package/dist/types/bucket.js.map +1 -1
- package/dist/types/download.cjs +62 -0
- package/dist/types/download.cjs.map +1 -0
- package/dist/types/download.d.cts +100 -16
- package/dist/types/download.d.cts.map +1 -1
- package/dist/types/download.d.ts +100 -16
- package/dist/types/download.d.ts.map +1 -1
- package/dist/types/download.js +61 -0
- package/dist/types/download.js.map +1 -0
- package/dist/types/encryption.cjs +76 -229
- package/dist/types/encryption.cjs.map +1 -1
- package/dist/types/encryption.d.cts +48 -6
- package/dist/types/encryption.d.cts.map +1 -1
- package/dist/types/encryption.d.ts +48 -6
- package/dist/types/encryption.d.ts.map +1 -1
- package/dist/types/encryption.js +74 -229
- package/dist/types/encryption.js.map +1 -1
- package/dist/types/errors.cjs +9 -0
- package/dist/types/errors.cjs.map +1 -1
- package/dist/types/errors.d.cts +1 -1
- package/dist/types/errors.d.cts.map +1 -1
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +9 -0
- package/dist/types/errors.js.map +1 -1
- package/dist/types/file.cjs +3 -0
- package/dist/types/file.cjs.map +1 -1
- package/dist/types/file.d.cts +140 -18
- package/dist/types/file.d.cts.map +1 -1
- package/dist/types/file.d.ts +140 -18
- package/dist/types/file.d.ts.map +1 -1
- package/dist/types/file.js +3 -1
- package/dist/types/file.js.map +1 -1
- package/dist/types/ids.cjs +30 -0
- package/dist/types/ids.cjs.map +1 -1
- package/dist/types/ids.d.cts +32 -0
- package/dist/types/ids.d.cts.map +1 -1
- package/dist/types/ids.d.ts +32 -0
- package/dist/types/ids.d.ts.map +1 -1
- package/dist/types/ids.js +28 -1
- package/dist/types/ids.js.map +1 -1
- package/dist/types/index.d.cts +16 -12
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +16 -12
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/key.d.cts +4 -3
- package/dist/types/key.d.cts.map +1 -1
- package/dist/types/key.d.ts +4 -3
- package/dist/types/key.d.ts.map +1 -1
- package/dist/types/lock.cjs.map +1 -1
- package/dist/types/lock.d.cts +14 -0
- package/dist/types/lock.d.cts.map +1 -1
- package/dist/types/lock.d.ts +14 -0
- package/dist/types/lock.d.ts.map +1 -1
- package/dist/types/lock.js.map +1 -1
- package/dist/types/notifications.cjs +31 -1
- package/dist/types/notifications.cjs.map +1 -1
- package/dist/types/notifications.d.cts +31 -4
- package/dist/types/notifications.d.cts.map +1 -1
- package/dist/types/notifications.d.ts +31 -4
- package/dist/types/notifications.d.ts.map +1 -1
- package/dist/types/notifications.js +30 -2
- package/dist/types/notifications.js.map +1 -1
- package/dist/types/partner.cjs +32 -0
- package/dist/types/partner.cjs.map +1 -0
- package/dist/types/partner.d.cts +386 -0
- package/dist/types/partner.d.cts.map +1 -0
- package/dist/types/partner.d.ts +386 -0
- package/dist/types/partner.d.ts.map +1 -0
- package/dist/types/partner.js +29 -0
- package/dist/types/partner.js.map +1 -0
- package/dist/types/upload.d.cts +35 -18
- package/dist/types/upload.d.cts.map +1 -1
- package/dist/types/upload.d.ts +35 -18
- package/dist/types/upload.d.ts.map +1 -1
- package/dist/upload/abort-scope.cjs +0 -45
- package/dist/upload/abort-scope.cjs.map +1 -1
- package/dist/upload/abort-scope.d.cts +0 -22
- package/dist/upload/abort-scope.d.cts.map +1 -1
- package/dist/upload/abort-scope.d.ts +0 -22
- package/dist/upload/abort-scope.d.ts.map +1 -1
- package/dist/upload/abort-scope.js +1 -44
- package/dist/upload/abort-scope.js.map +1 -1
- package/dist/upload/finish.cjs +3 -8
- package/dist/upload/finish.cjs.map +1 -1
- package/dist/upload/finish.d.cts.map +1 -1
- package/dist/upload/finish.d.ts.map +1 -1
- package/dist/upload/finish.js +1 -6
- package/dist/upload/finish.js.map +1 -1
- package/dist/upload/large.cjs +15 -8
- package/dist/upload/large.cjs.map +1 -1
- package/dist/upload/large.d.cts +31 -8
- package/dist/upload/large.d.cts.map +1 -1
- package/dist/upload/large.d.ts +31 -8
- package/dist/upload/large.d.ts.map +1 -1
- package/dist/upload/large.js +15 -8
- package/dist/upload/large.js.map +1 -1
- package/dist/upload/options.cjs.map +1 -1
- package/dist/upload/options.d.cts +24 -0
- package/dist/upload/options.d.cts.map +1 -1
- package/dist/upload/options.d.ts +24 -0
- package/dist/upload/options.d.ts.map +1 -1
- package/dist/upload/options.js.map +1 -1
- package/dist/upload/resume.cjs +6 -4
- package/dist/upload/resume.cjs.map +1 -1
- package/dist/upload/resume.d.cts +9 -5
- package/dist/upload/resume.d.cts.map +1 -1
- package/dist/upload/resume.d.ts +9 -5
- package/dist/upload/resume.d.ts.map +1 -1
- package/dist/upload/resume.js +6 -4
- package/dist/upload/resume.js.map +1 -1
- package/dist/upload/retry.cjs +25 -13
- package/dist/upload/retry.cjs.map +1 -1
- package/dist/upload/retry.d.cts.map +1 -1
- package/dist/upload/retry.d.ts.map +1 -1
- package/dist/upload/retry.js +25 -13
- package/dist/upload/retry.js.map +1 -1
- package/dist/upload/single.cjs +35 -30
- package/dist/upload/single.cjs.map +1 -1
- package/dist/upload/single.d.cts +12 -0
- package/dist/upload/single.d.cts.map +1 -1
- package/dist/upload/single.d.ts +12 -0
- package/dist/upload/single.d.ts.map +1 -1
- package/dist/upload/single.js +35 -30
- package/dist/upload/single.js.map +1 -1
- package/dist/upload/stream.cjs +18 -5
- package/dist/upload/stream.cjs.map +1 -1
- package/dist/upload/stream.d.cts +12 -0
- package/dist/upload/stream.d.cts.map +1 -1
- package/dist/upload/stream.d.ts +12 -0
- package/dist/upload/stream.d.ts.map +1 -1
- package/dist/upload/stream.js +15 -2
- package/dist/upload/stream.js.map +1 -1
- package/dist/util/abort.cjs +114 -0
- package/dist/util/abort.cjs.map +1 -0
- package/dist/util/abort.d.cts +65 -0
- package/dist/util/abort.d.cts.map +1 -0
- package/dist/util/abort.d.ts +65 -0
- package/dist/util/abort.d.ts.map +1 -0
- package/dist/util/abort.js +109 -0
- package/dist/util/abort.js.map +1 -0
- package/dist/util/defaults.cjs +3 -0
- package/dist/util/defaults.cjs.map +1 -1
- package/dist/util/defaults.d.cts +2 -0
- package/dist/util/defaults.d.cts.map +1 -1
- package/dist/util/defaults.d.ts +2 -0
- package/dist/util/defaults.d.ts.map +1 -1
- package/dist/util/defaults.js +3 -1
- package/dist/util/defaults.js.map +1 -1
- package/dist/util/md5.cjs +211 -0
- package/dist/util/md5.cjs.map +1 -0
- package/dist/util/md5.d.cts +43 -0
- package/dist/util/md5.d.cts.map +1 -0
- package/dist/util/md5.d.ts +43 -0
- package/dist/util/md5.d.ts.map +1 -0
- package/dist/util/md5.js +209 -0
- package/dist/util/md5.js.map +1 -0
- package/dist/util/normalize.cjs +5 -5
- package/dist/util/normalize.cjs.map +1 -1
- package/dist/util/normalize.d.cts +7 -7
- package/dist/util/normalize.d.cts.map +1 -1
- package/dist/util/normalize.d.ts +7 -7
- package/dist/util/normalize.d.ts.map +1 -1
- package/dist/util/normalize.js +5 -5
- package/dist/util/normalize.js.map +1 -1
- package/dist/util/paginator.cjs +7 -1
- package/dist/util/paginator.cjs.map +1 -1
- package/dist/util/paginator.d.cts +3 -1
- package/dist/util/paginator.d.cts.map +1 -1
- package/dist/util/paginator.d.ts +3 -1
- package/dist/util/paginator.d.ts.map +1 -1
- package/dist/util/paginator.js +7 -1
- package/dist/util/paginator.js.map +1 -1
- package/dist/version.cjs +56 -4
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +53 -4
- package/dist/version.d.cts.map +1 -1
- package/dist/version.d.ts +53 -4
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +52 -5
- package/dist/version.js.map +1 -1
- package/package.json +47 -18
package/dist/http/retry.js
CHANGED
package/dist/http/retry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","names":[],"sources":["../../src/http/retry.ts"],"sourcesContent":["/** Configuration for retry behavior on transient failures. */\nexport interface RetryOptions {\n /** Maximum number of retry attempts before giving up. */\n readonly maxRetries: number\n /** Upper bound on retry delay in milliseconds, regardless of backoff calculation. */\n readonly maxRetryDelayMs: number\n /** Base delay in milliseconds for the first retry. Doubles on each subsequent attempt. */\n readonly initialRetryDelayMs: number\n /**\n * Optional timeout for each HTTP request attempt. Defaults to 15 minutes\n * when omitted. The timer covers request dispatch, upload bodies, and\n * non-streaming response body reads. For `response.body` streams it is an\n * idle timeout that resets after each received chunk. Set to 0 to disable\n * the SDK timeout and rely only on the caller's AbortSignal.\n */\n readonly requestTimeoutMs?: number\n}\n\n/** Default retry settings: 5 retries, 1s initial delay, 64s max delay, 15 minute timeout. */\nexport const DEFAULT_RETRY_OPTIONS = {\n maxRetries: 5,\n maxRetryDelayMs: 64_000,\n initialRetryDelayMs: 1_000,\n requestTimeoutMs: 15 * 60_000,\n} satisfies Required<RetryOptions>\n\n/**\n * Computes the delay before the next retry using exponential backoff with jitter.\n * If a `Retry-After` value is provided by the server, it takes precedence over\n * the calculated backoff (still capped at {@link RetryOptions.maxRetryDelayMs}).\n *\n * @param attempt - Zero-based retry attempt index.\n * @param options - Retry configuration with delay bounds.\n * @param retryAfter - Server-provided retry delay in seconds, if any.\n *\n * @returns The delay in milliseconds before the next retry attempt.\n */\nexport function computeBackoff(\n attempt: number,\n options: RetryOptions,\n retryAfter?: number,\n): number {\n if (retryAfter !== undefined && retryAfter > 0) {\n return Math.min(retryAfter * 1000, options.maxRetryDelayMs)\n }\n const base = options.initialRetryDelayMs * 2 ** attempt\n const jitter = Math.random() * base * 0.5\n return Math.min(base + jitter, options.maxRetryDelayMs)\n}\n\n/**\n * Returns a promise that resolves after the given delay. Supports cancellation\n * via an optional AbortSignal.\n *\n * @param ms - Delay in milliseconds.\n * @param signal - Optional abort signal to cancel the sleep early.\n *\n * @returns A promise that resolves when the delay elapses or rejects if aborted.\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new DOMException('Aborted', 'AbortError'))\n return\n }\n const timer = setTimeout(resolve, ms)\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer)\n reject(signal.reason ?? new DOMException('Aborted', 'AbortError'))\n },\n { once: true },\n )\n })\n}\n"],"mappings":";;AAmBA,IAAa,wBAAwB;CACnC,YAAY;CACZ,iBAAiB;CACjB,qBAAqB;CACrB,kBAAkB
|
|
1
|
+
{"version":3,"file":"retry.js","names":[],"sources":["../../src/http/retry.ts"],"sourcesContent":["/** Configuration for retry behavior on transient failures. */\nexport interface RetryOptions {\n /** Maximum number of retry attempts before giving up. */\n readonly maxRetries: number\n /** Upper bound on retry delay in milliseconds, regardless of backoff calculation. */\n readonly maxRetryDelayMs: number\n /** Base delay in milliseconds for the first retry. Doubles on each subsequent attempt. */\n readonly initialRetryDelayMs: number\n /**\n * Optional timeout for each HTTP request attempt. Defaults to 15 minutes\n * when omitted. The timer covers request dispatch, upload bodies, and\n * non-streaming response body reads. For `response.body` streams it is an\n * idle timeout that resets after each received chunk. Set to 0 to disable\n * the SDK timeout and rely only on the caller's AbortSignal.\n */\n readonly requestTimeoutMs?: number\n}\n\n/** Default retry settings: 5 retries, 1s initial delay, 64s max delay, 15 minute timeout. */\nexport const DEFAULT_RETRY_OPTIONS = {\n maxRetries: 5,\n maxRetryDelayMs: 64_000,\n initialRetryDelayMs: 1_000,\n requestTimeoutMs: 15 * 60_000,\n} satisfies Required<RetryOptions>\n\n/**\n * Computes the delay before the next retry using exponential backoff with jitter.\n * If a `Retry-After` value is provided by the server, it takes precedence over\n * the calculated backoff (still capped at {@link RetryOptions.maxRetryDelayMs}).\n *\n * @param attempt - Zero-based retry attempt index.\n * @param options - Retry configuration with delay bounds.\n * @param retryAfter - Server-provided retry delay in seconds, if any.\n *\n * @returns The delay in milliseconds before the next retry attempt.\n */\nexport function computeBackoff(\n attempt: number,\n options: RetryOptions,\n retryAfter?: number,\n): number {\n if (retryAfter !== undefined && retryAfter > 0) {\n return Math.min(retryAfter * 1000, options.maxRetryDelayMs)\n }\n const base = options.initialRetryDelayMs * 2 ** attempt\n const jitter = Math.random() * base * 0.5\n return Math.min(base + jitter, options.maxRetryDelayMs)\n}\n\n/**\n * Returns a promise that resolves after the given delay. Supports cancellation\n * via an optional AbortSignal.\n *\n * @param ms - Delay in milliseconds.\n * @param signal - Optional abort signal to cancel the sleep early.\n *\n * @returns A promise that resolves when the delay elapses or rejects if aborted.\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new DOMException('Aborted', 'AbortError'))\n return\n }\n const timer = setTimeout(resolve, ms)\n signal?.addEventListener(\n 'abort',\n () => {\n clearTimeout(timer)\n reject(signal.reason ?? new DOMException('Aborted', 'AbortError'))\n },\n { once: true },\n )\n })\n}\n"],"mappings":";;AAmBA,IAAa,wBAAwB;CACnC,YAAY;CACZ,iBAAiB;CACjB,qBAAqB;CACrB,kBAAkB;AACpB;;;;;;;;;;;;AAaA,SAAgB,eACd,SACA,SACA,YACQ;CACR,IAAI,eAAe,KAAA,KAAa,aAAa,GAC3C,OAAO,KAAK,IAAI,aAAa,KAAM,QAAQ,eAAe;CAE5D,MAAM,OAAO,QAAQ,sBAAsB,KAAK;CAChD,MAAM,SAAS,KAAK,OAAO,IAAI,OAAO;CACtC,OAAO,KAAK,IAAI,OAAO,QAAQ,QAAQ,eAAe;AACxD;;;;;;;;;;AAWA,SAAgB,MAAM,IAAY,QAAqC;CACrE,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAI,QAAQ,SAAS;GACnB,OAAO,OAAO,UAAU,IAAI,aAAa,WAAW,YAAY,CAAC;GACjE;EACF;EACA,MAAM,QAAQ,WAAW,SAAS,EAAE;EACpC,QAAQ,iBACN,eACM;GACJ,aAAa,KAAK;GAClB,OAAO,OAAO,UAAU,IAAI,aAAa,WAAW,YAAY,CAAC;EACnE,GACA,EAAE,MAAM,KAAK,CACf;CACF,CAAC;AACH"}
|
package/dist/http/transport.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const require_errors_index = require("../errors/index.cjs");
|
|
2
|
+
const require_abort = require("../util/abort.cjs");
|
|
2
3
|
const require_retry = require("./retry.cjs");
|
|
4
|
+
const require_non_idempotent_mutations = require("./non-idempotent-mutations.cjs");
|
|
3
5
|
const require_url_guard = require("./url-guard.cjs");
|
|
4
6
|
const require_user_agent = require("./user-agent.cjs");
|
|
5
7
|
//#region src/http/transport.ts
|
|
@@ -12,6 +14,18 @@ var REDIRECT_STATUSES = /* @__PURE__ */ new Set([
|
|
|
12
14
|
]);
|
|
13
15
|
var MAX_SAME_ORIGIN_REDIRECTS = 5;
|
|
14
16
|
/**
|
|
17
|
+
* Returns the URL guard exposed by `transport`, if it implements
|
|
18
|
+
* {@link UrlGuardedTransport}.
|
|
19
|
+
*
|
|
20
|
+
* @param transport - Transport to inspect.
|
|
21
|
+
*
|
|
22
|
+
* @returns The exposed URL guard, or undefined for unguarded transports.
|
|
23
|
+
*/
|
|
24
|
+
function getTransportUrlGuard(transport) {
|
|
25
|
+
const candidate = transport;
|
|
26
|
+
return candidate.urlGuard instanceof require_url_guard.UrlGuard ? candidate.urlGuard : void 0;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
15
29
|
* Default transport implementation using the global `fetch` API.
|
|
16
30
|
* Automatically sets the User-Agent header on each request and applies the
|
|
17
31
|
* SSRF {@link UrlGuard} (if configured) before opening the connection.
|
|
@@ -218,17 +232,16 @@ function createTimedResponseBody(body, timeoutScope) {
|
|
|
218
232
|
async function raceBodyReadWithAbort(timeoutScope, read, abortCleanup) {
|
|
219
233
|
const signal = timeoutScope.signal;
|
|
220
234
|
if (signal === void 0) return read;
|
|
221
|
-
const abortReason = () => signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
222
235
|
if (signal.aborted) {
|
|
223
236
|
read.catch(() => {});
|
|
224
|
-
const reason = abortReason();
|
|
237
|
+
const reason = require_abort.abortReason(signal);
|
|
225
238
|
await runAbortCleanup(abortCleanup, reason);
|
|
226
239
|
throw reason;
|
|
227
240
|
}
|
|
228
241
|
let removeAbortListener;
|
|
229
242
|
const abort = new Promise((_, reject) => {
|
|
230
243
|
const onAbort = () => {
|
|
231
|
-
const reason = abortReason();
|
|
244
|
+
const reason = require_abort.abortReason(signal);
|
|
232
245
|
read.catch(() => {});
|
|
233
246
|
reject(reason);
|
|
234
247
|
runAbortCleanup(abortCleanup, reason);
|
|
@@ -277,16 +290,38 @@ function isUploadEndpoint(url) {
|
|
|
277
290
|
function isFinishLargeFileEndpoint(url) {
|
|
278
291
|
return b2ApiEndpointName(url) === "b2_finish_large_file";
|
|
279
292
|
}
|
|
293
|
+
function isAuthorizeEndpoint(url) {
|
|
294
|
+
return b2ApiEndpointName(url) === "b2_authorize_account";
|
|
295
|
+
}
|
|
280
296
|
function isStartLargeFileEndpoint(url) {
|
|
281
297
|
return b2ApiEndpointName(url) === "b2_start_large_file";
|
|
282
298
|
}
|
|
299
|
+
function isKnownPartnerNonIdempotentMutationEndpoint(url) {
|
|
300
|
+
return require_non_idempotent_mutations.isPartnerNonIdempotentMutationEndpoint(b2ApiEndpointName(url));
|
|
301
|
+
}
|
|
302
|
+
function isKnownBackupNonIdempotentMutationEndpoint(url) {
|
|
303
|
+
return require_non_idempotent_mutations.isBackupNonIdempotentMutationEndpoint(backupApiEndpointName(url));
|
|
304
|
+
}
|
|
305
|
+
function isNonIdempotentMutationRequest(request) {
|
|
306
|
+
return request.idempotent === false || request.method === "POST" && (isKnownPartnerNonIdempotentMutationEndpoint(request.url) || isKnownBackupNonIdempotentMutationEndpoint(request.url));
|
|
307
|
+
}
|
|
283
308
|
function b2ApiEndpointName(url) {
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
return
|
|
309
|
+
const segments = new URL(url).pathname.split("/").filter((segment) => segment.length > 0);
|
|
310
|
+
const apiRootIndex = segments.lastIndexOf("b2api");
|
|
311
|
+
if (apiRootIndex === -1) return void 0;
|
|
312
|
+
return segments[apiRootIndex + 2];
|
|
287
313
|
}
|
|
288
|
-
function
|
|
289
|
-
|
|
314
|
+
function backupApiEndpointName(url) {
|
|
315
|
+
const segments = new URL(url).pathname.split("/").filter((segment) => segment.length > 0);
|
|
316
|
+
const apiRootIndex = segments.lastIndexOf("api");
|
|
317
|
+
if (apiRootIndex === -1 || segments[apiRootIndex + 1] !== "backup") return void 0;
|
|
318
|
+
if (!/^v\d+$/.test(segments[apiRootIndex + 2] ?? "")) return void 0;
|
|
319
|
+
return segments[apiRootIndex + 3];
|
|
320
|
+
}
|
|
321
|
+
function isReplayUnsafeRequest(request) {
|
|
322
|
+
if (request.idempotent === false) return true;
|
|
323
|
+
if (request.method !== "POST") return false;
|
|
324
|
+
return isUploadEndpoint(request.url) || isStartLargeFileEndpoint(request.url) || isFinishLargeFileEndpoint(request.url) || isNonIdempotentMutationRequest(request);
|
|
290
325
|
}
|
|
291
326
|
/**
|
|
292
327
|
* Decide whether a classified error should be retried in place for `url`.
|
|
@@ -295,15 +330,17 @@ function isReplayUnsafePostEndpoint(url) {
|
|
|
295
330
|
* upload URL only amplifies the rate limit.
|
|
296
331
|
*
|
|
297
332
|
* @param error - The classified, retryability-tagged error.
|
|
298
|
-
* @param
|
|
333
|
+
* @param request - The request being considered for in-place retry.
|
|
299
334
|
*
|
|
300
335
|
* @returns Whether to retry the request in place.
|
|
301
336
|
*/
|
|
302
|
-
function shouldRetryInPlace(error,
|
|
337
|
+
function shouldRetryInPlace(error, request) {
|
|
303
338
|
if (!error.retryable) return false;
|
|
304
|
-
if (
|
|
305
|
-
if (
|
|
306
|
-
if (
|
|
339
|
+
if (isAuthorizeEndpoint(request.url) && error instanceof require_errors_index.ExpiredAuthTokenError) return false;
|
|
340
|
+
if (isNonIdempotentMutationRequest(request)) return false;
|
|
341
|
+
if (isStartLargeFileEndpoint(request.url) || isFinishLargeFileEndpoint(request.url)) return false;
|
|
342
|
+
if (isUploadEndpoint(request.url) && error.status === 429) return true;
|
|
343
|
+
if (isUploadEndpoint(request.url)) return false;
|
|
307
344
|
return true;
|
|
308
345
|
}
|
|
309
346
|
function isRequestTimeoutError(err) {
|
|
@@ -324,6 +361,8 @@ function isTerminalTransportError(err) {
|
|
|
324
361
|
* retry so account-level throttling does not trigger extra upload URL fetches.
|
|
325
362
|
*/
|
|
326
363
|
var RetryTransport = class {
|
|
364
|
+
/** URL guard from the wrapped transport, when the transport exposes one. */
|
|
365
|
+
urlGuard;
|
|
327
366
|
/** The wrapped transport that performs actual HTTP requests. */
|
|
328
367
|
inner;
|
|
329
368
|
/** Resolved retry options (defaults merged with user overrides). */
|
|
@@ -338,6 +377,7 @@ var RetryTransport = class {
|
|
|
338
377
|
*/
|
|
339
378
|
constructor(opts) {
|
|
340
379
|
this.inner = opts.transport;
|
|
380
|
+
this.urlGuard = getTransportUrlGuard(opts.transport);
|
|
341
381
|
this.options = {
|
|
342
382
|
...require_retry.DEFAULT_RETRY_OPTIONS,
|
|
343
383
|
...opts.retry
|
|
@@ -364,7 +404,7 @@ var RetryTransport = class {
|
|
|
364
404
|
let didReauth = false;
|
|
365
405
|
let attempt = 0;
|
|
366
406
|
while (attempt <= retryOptions.maxRetries) {
|
|
367
|
-
throwIfSignalAborted(request.signal);
|
|
407
|
+
require_abort.throwIfSignalAborted(request.signal);
|
|
368
408
|
if (attempt > 0 && lastError) {
|
|
369
409
|
const retryAfter = lastError instanceof require_errors_index.NetworkError ? void 0 : lastError.retryAfter;
|
|
370
410
|
const delay = require_retry.computeBackoff(attempt - 1, retryOptions, retryAfter);
|
|
@@ -395,8 +435,9 @@ var RetryTransport = class {
|
|
|
395
435
|
...retryAfterSec !== void 0 ? { retryAfter: retryAfterSec } : {},
|
|
396
436
|
...requestId !== void 0 ? { requestId } : {}
|
|
397
437
|
});
|
|
398
|
-
if (error instanceof require_errors_index.ExpiredAuthTokenError && this.onReauth && !isUploadEndpoint(request.url) && !didReauth) {
|
|
399
|
-
const freshToken = await this.onReauth();
|
|
438
|
+
if (error instanceof require_errors_index.ExpiredAuthTokenError && this.onReauth && !isAuthorizeEndpoint(request.url) && !isUploadEndpoint(request.url) && !isNonIdempotentMutationRequest(request) && !didReauth) {
|
|
439
|
+
const freshToken = await require_abort.raceWithAbort(this.onReauth(request.signal), request.signal);
|
|
440
|
+
require_abort.throwIfSignalAborted(request.signal);
|
|
400
441
|
request = {
|
|
401
442
|
...request,
|
|
402
443
|
headers: {
|
|
@@ -408,14 +449,14 @@ var RetryTransport = class {
|
|
|
408
449
|
lastError = void 0;
|
|
409
450
|
continue;
|
|
410
451
|
}
|
|
411
|
-
if (!shouldRetryInPlace(error, request
|
|
452
|
+
if (!shouldRetryInPlace(error, request) || attempt === retryOptions.maxRetries) throw error;
|
|
412
453
|
lastError = error;
|
|
413
454
|
attempt += 1;
|
|
414
455
|
} catch (err) {
|
|
415
|
-
throwIfSignalAborted(request.signal);
|
|
456
|
+
require_abort.throwIfSignalAborted(request.signal);
|
|
416
457
|
if (isTerminalTransportError(err)) throw err;
|
|
417
458
|
const networkErr = new require_errors_index.NetworkError(err instanceof Error ? err.message : "Network error", err);
|
|
418
|
-
if (
|
|
459
|
+
if (isReplayUnsafeRequest(request) || attempt === retryOptions.maxRetries) throw networkErr;
|
|
419
460
|
lastError = networkErr;
|
|
420
461
|
attempt += 1;
|
|
421
462
|
}
|
|
@@ -423,12 +464,9 @@ var RetryTransport = class {
|
|
|
423
464
|
throw lastError ?? new require_errors_index.NetworkError("Max retries exceeded");
|
|
424
465
|
}
|
|
425
466
|
};
|
|
426
|
-
function throwIfSignalAborted(signal) {
|
|
427
|
-
if (signal?.aborted === true) throw signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
428
|
-
}
|
|
429
467
|
async function throwIfSignalAbortedAfterResponse(signal, response) {
|
|
430
468
|
if (signal?.aborted !== true) return;
|
|
431
|
-
const reason =
|
|
469
|
+
const reason = require_abort.abortReason(signal);
|
|
432
470
|
try {
|
|
433
471
|
await response.body?.cancel(reason);
|
|
434
472
|
} catch {}
|
|
@@ -437,5 +475,6 @@ async function throwIfSignalAbortedAfterResponse(signal, response) {
|
|
|
437
475
|
//#endregion
|
|
438
476
|
exports.FetchTransport = FetchTransport;
|
|
439
477
|
exports.RetryTransport = RetryTransport;
|
|
478
|
+
exports.getTransportUrlGuard = getTransportUrlGuard;
|
|
440
479
|
|
|
441
480
|
//# sourceMappingURL=transport.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.cjs","names":[],"sources":["../../src/http/transport.ts"],"sourcesContent":["import {\n B2Error,\n B2RedirectError,\n B2SsrfError,\n classifyError,\n ExpiredAuthTokenError,\n NetworkError,\n} from '../errors/index.ts'\nimport type { B2ErrorResponse } from '../types/errors.ts'\nimport { computeBackoff, DEFAULT_RETRY_OPTIONS, type RetryOptions, sleep } from './retry.ts'\nimport { UrlGuard } from './url-guard.ts'\nimport { getUserAgent } from './user-agent.ts'\n\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308])\nconst MAX_SAME_ORIGIN_REDIRECTS = 5\n\n/** Describes an outgoing HTTP request to the B2 API. */\nexport interface HttpRequest {\n /** Fully qualified URL to send the request to. */\n readonly url: string\n /** HTTP method. B2 uses GET for downloads (HEAD to fetch only headers) and POST for all other operations. */\n readonly method: 'GET' | 'HEAD' | 'POST'\n /** Request headers. Authorization and content-type are typically included. */\n readonly headers?: Record<string, string>\n /** Request body. Used for POST requests (JSON payloads or file uploads). */\n readonly body?: BodyInit | null\n /** Optional abort signal for request cancellation. */\n readonly signal?: AbortSignal\n /** Optional per-request retry override. */\n readonly retry?: Partial<RetryOptions>\n}\n\n/** Represents a parsed HTTP response from the B2 API. */\nexport interface HttpResponse {\n /** HTTP status code. */\n readonly status: number\n /** Response headers. */\n readonly headers: Headers\n /** Response body as a readable stream, or null for empty responses. */\n readonly body: ReadableStream<Uint8Array> | null\n /** Parses the response body as JSON. */\n json<T>(): Promise<T>\n /** Reads the response body as a UTF-8 string. */\n text(): Promise<string>\n /** Reads the response body as an ArrayBuffer. */\n arrayBuffer(): Promise<ArrayBuffer>\n}\n\n/**\n * Transport layer abstraction for sending HTTP requests.\n * Implementations handle the actual network I/O and can be composed\n * (e.g. wrapping a {@link FetchTransport} with a {@link RetryTransport}).\n */\nexport interface HttpTransport {\n /** Sends an HTTP request and returns the response. */\n send(request: HttpRequest): Promise<HttpResponse>\n}\n\n/**\n * Default transport implementation using the global `fetch` API.\n * Automatically sets the User-Agent header on each request and applies the\n * SSRF {@link UrlGuard} (if configured) before opening the connection.\n * Redirect following is disabled so redirected URLs cannot bypass the guard or\n * receive credential-bearing headers without an explicit checked request.\n */\nexport class FetchTransport implements HttpTransport {\n /** User-Agent string sent with every request. */\n private readonly userAgent: string\n /** Whether same-origin GET/HEAD redirects should be followed after guard checks. */\n private readonly followSameOriginRedirects: boolean\n /** SSRF allow-list applied to every outgoing URL. Mutable so `B2Client.authorize()` can lock it down post-auth. */\n readonly urlGuard: UrlGuard\n\n /**\n * Creates a new FetchTransport.\n * @param options - Optional configuration: custom User-Agent prefix and SSRF guard.\n */\n constructor(options?: {\n userAgent?: string\n urlGuard?: UrlGuard\n /**\n * Follow same-origin GET/HEAD redirects after checking the target with the\n * URL guard. POST redirects are still blocked to avoid replaying\n * credential-bearing payloads to an unexpected endpoint. Defaults to true.\n */\n followSameOriginRedirects?: boolean\n }) {\n this.userAgent = getUserAgent(options?.userAgent)\n this.followSameOriginRedirects = options?.followSameOriginRedirects ?? true\n this.urlGuard = options?.urlGuard ?? new UrlGuard()\n }\n\n /**\n * Sends the request using the global `fetch` function.\n * @param request - The HTTP request to execute.\n *\n * @returns The HTTP response.\n *\n * @throws B2SsrfError when the URL fails the configured SSRF guard.\n * @throws B2RedirectError when a response attempts to redirect.\n */\n async send(request: HttpRequest): Promise<HttpResponse> {\n let currentRequest = request\n let redirectCount = 0\n\n while (true) {\n this.urlGuard.check(currentRequest.url)\n\n const headers = new Headers(currentRequest.headers)\n if (!headers.has('User-Agent')) {\n headers.set('User-Agent', this.userAgent)\n }\n\n const timeoutScope = createRequestTimeoutScope(currentRequest)\n let response: Response\n try {\n response = await fetch(currentRequest.url, {\n method: currentRequest.method,\n headers,\n body: currentRequest.body ?? null,\n redirect: 'manual',\n ...(timeoutScope.signal !== undefined ? { signal: timeoutScope.signal } : {}),\n })\n } catch (err) {\n timeoutScope.dispose()\n if (timeoutScope.timedOut) {\n throw createRequestTimeoutError(timeoutScope)\n }\n throw err\n }\n\n if (isBlockedRedirect(response)) {\n const location = response.headers.get('Location')\n if (\n this.followSameOriginRedirects &&\n location !== null &&\n redirectCount < MAX_SAME_ORIGIN_REDIRECTS &&\n canFollowSameOriginRedirect(currentRequest, location)\n ) {\n const nextUrl = new URL(location, currentRequest.url).toString()\n await cancelResponseBody(response)\n timeoutScope.dispose()\n this.urlGuard.check(nextUrl)\n currentRequest = { ...currentRequest, url: nextUrl }\n redirectCount += 1\n continue\n }\n\n await cancelResponseBody(response)\n timeoutScope.dispose()\n throw new B2RedirectError(currentRequest.url, response.status, location)\n }\n\n return createTimedHttpResponse(response, timeoutScope)\n }\n }\n}\n\ninterface RequestTimeoutScope {\n readonly signal?: AbortSignal\n readonly timeoutMs: number\n readonly timedOut: boolean\n reset(): void\n dispose(): void\n}\n\nfunction createRequestTimeoutScope(request: HttpRequest): RequestTimeoutScope {\n const timeoutMs = request.retry?.requestTimeoutMs ?? DEFAULT_RETRY_OPTIONS.requestTimeoutMs\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n const scope: RequestTimeoutScope = {\n timeoutMs: 0,\n timedOut: false,\n reset() {},\n dispose() {},\n }\n if (request.signal !== undefined) return { ...scope, signal: request.signal }\n return scope\n }\n\n const controller = new AbortController()\n let timedOut = false\n let timer: ReturnType<typeof setTimeout>\n const abortFromUpstream = (): void => {\n clearTimeout(timer)\n controller.abort(request.signal?.reason ?? new DOMException('Aborted', 'AbortError'))\n }\n const armTimer = (): ReturnType<typeof setTimeout> => {\n const nextTimer = setTimeout(() => {\n timedOut = true\n controller.abort(new DOMException('HTTP request timed out', 'TimeoutError'))\n }, timeoutMs)\n unrefTimer(nextTimer)\n return nextTimer\n }\n timer = armTimer()\n\n const reset = (): void => {\n if (timedOut || controller.signal.aborted) return\n clearTimeout(timer)\n timer = armTimer()\n }\n\n if (request.signal?.aborted === true) {\n clearTimeout(timer)\n abortFromUpstream()\n } else {\n request.signal?.addEventListener('abort', abortFromUpstream, { once: true })\n }\n\n return {\n signal: controller.signal,\n timeoutMs,\n get timedOut() {\n return timedOut\n },\n reset,\n dispose() {\n clearTimeout(timer)\n request.signal?.removeEventListener('abort', abortFromUpstream)\n },\n }\n}\n\nfunction unrefTimer(timer: ReturnType<typeof setTimeout>): void {\n const maybeUnref = (timer as { unref?: () => void }).unref\n if (typeof maybeUnref === 'function') maybeUnref.call(timer)\n}\n\nfunction createRequestTimeoutError(scope: RequestTimeoutScope): DOMException {\n return new DOMException(`HTTP request timed out after ${scope.timeoutMs} ms`, 'TimeoutError')\n}\n\nfunction createTimedHttpResponse(\n response: Response,\n timeoutScope: RequestTimeoutScope,\n): HttpResponse {\n const body = response.body\n if (body === null) timeoutScope.dispose()\n let timedBody: ReadableStream<Uint8Array> | undefined\n\n return {\n status: response.status,\n headers: response.headers,\n get body() {\n if (body === null) return null\n timedBody ??= createTimedResponseBody(body, timeoutScope)\n return timedBody\n },\n json: <T>() =>\n readTimedResponseBody(timeoutScope, response, () => response.json() as Promise<T>),\n text: () => readTimedResponseBody(timeoutScope, response, () => response.text()),\n arrayBuffer: () => readTimedResponseBody(timeoutScope, response, () => response.arrayBuffer()),\n }\n}\n\nasync function readTimedResponseBody<T>(\n timeoutScope: RequestTimeoutScope,\n response: Response,\n read: () => Promise<T>,\n): Promise<T> {\n try {\n return await raceBodyReadWithAbort(timeoutScope, read(), (reason) =>\n cancelResponseBody(response, reason),\n )\n } catch (err) {\n if (timeoutScope.timedOut) {\n throw createRequestTimeoutError(timeoutScope)\n }\n throw err\n } finally {\n timeoutScope.dispose()\n }\n}\n\nfunction createTimedResponseBody(\n body: ReadableStream<Uint8Array>,\n timeoutScope: RequestTimeoutScope,\n): ReadableStream<Uint8Array> {\n let reader: ReadableStreamDefaultReader<Uint8Array> | undefined\n let disposed = false\n const dispose = (): void => {\n if (disposed) return\n disposed = true\n timeoutScope.dispose()\n }\n\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n reader ??= body.getReader()\n try {\n const result = await raceBodyReadWithAbort(timeoutScope, reader.read(), (reason) =>\n reader?.cancel(reason),\n )\n if (result.done) {\n dispose()\n controller.close()\n return\n }\n timeoutScope.reset()\n controller.enqueue(result.value)\n } catch (err) {\n dispose()\n if (timeoutScope.timedOut) {\n controller.error(createRequestTimeoutError(timeoutScope))\n return\n }\n controller.error(err)\n }\n },\n async cancel(reason) {\n dispose()\n try {\n if (reader !== undefined) {\n await reader.cancel(reason)\n return\n }\n await body.cancel(reason)\n } catch {\n // Best-effort cleanup when the caller cancels the wrapper body.\n }\n },\n })\n}\n\nasync function raceBodyReadWithAbort<T>(\n timeoutScope: RequestTimeoutScope,\n read: Promise<T>,\n abortCleanup?: ((reason: unknown) => Promise<void> | void) | undefined,\n): Promise<T> {\n const signal = timeoutScope.signal\n if (signal === undefined) return read\n const abortReason = (): unknown => signal.reason ?? new DOMException('Aborted', 'AbortError')\n if (signal.aborted) {\n void read.catch(() => {})\n const reason = abortReason()\n await runAbortCleanup(abortCleanup, reason)\n throw reason\n }\n\n let removeAbortListener: (() => void) | undefined\n const abort = new Promise<never>((_, reject) => {\n const onAbort = (): void => {\n const reason = abortReason()\n void read.catch(() => {})\n reject(reason)\n void runAbortCleanup(abortCleanup, reason)\n }\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n return await Promise.race([read, abort])\n } finally {\n removeAbortListener?.()\n }\n}\n\nasync function runAbortCleanup(\n abortCleanup: ((reason: unknown) => Promise<void> | void) | undefined,\n reason: unknown,\n): Promise<void> {\n try {\n await abortCleanup?.(reason)\n } catch {\n // Abort cleanup is best-effort and must not mask the abort reason.\n }\n}\n\nfunction isBlockedRedirect(response: Response): boolean {\n return response.type === 'opaqueredirect' || REDIRECT_STATUSES.has(response.status)\n}\n\nfunction canFollowSameOriginRedirect(request: HttpRequest, location: string): boolean {\n if (request.method !== 'GET' && request.method !== 'HEAD') return false\n try {\n return new URL(request.url).origin === new URL(location, request.url).origin\n } catch {\n return false\n }\n}\n\nasync function cancelResponseBody(response: Response, reason?: unknown): Promise<void> {\n try {\n await response.body?.cancel(reason)\n } catch {\n // Best-effort cleanup before throwing the primary error.\n }\n}\n\n/** Configuration for {@link RetryTransport}. */\nexport interface RetryTransportOptions {\n /** The underlying transport to delegate requests to. */\n readonly transport: HttpTransport\n /** Override default retry settings (max retries, delays). */\n readonly retry?: Partial<RetryOptions>\n /**\n * Callback invoked on expired auth token errors. Must refresh\n * credentials AND return the fresh auth token. The transport\n * substitutes the new token into `request.headers.Authorization`\n * before retrying — without this, the retried request would still\n * carry the expired token captured by the original caller and the\n * loop would never make progress.\n */\n readonly onReauth?: () => Promise<string>\n /**\n * Sleep implementation used between retry attempts. Defaults to the real\n * `sleep` from `./retry.js`. Test code can inject a no-op to avoid real\n * delays without relying on module mocking (which differs across runners).\n *\n * @internal\n */\n readonly sleepImpl?: (ms: number, signal?: AbortSignal) => Promise<void>\n}\n\n/**\n * Decide whether `url` points at a URL-pinned upload POST endpoint.\n *\n * @param url - Request URL to inspect.\n *\n * @returns Whether the request is a direct upload endpoint.\n */\nfunction isUploadEndpoint(url: string): boolean {\n const endpoint = b2ApiEndpointName(url)\n return endpoint === 'b2_upload_file' || endpoint === 'b2_upload_part'\n}\n\nfunction isFinishLargeFileEndpoint(url: string): boolean {\n return b2ApiEndpointName(url) === 'b2_finish_large_file'\n}\n\nfunction isStartLargeFileEndpoint(url: string): boolean {\n return b2ApiEndpointName(url) === 'b2_start_large_file'\n}\n\nfunction b2ApiEndpointName(url: string): string | undefined {\n const [, root, , endpoint] = new URL(url).pathname.split('/')\n if (root !== 'b2api') return undefined\n return endpoint\n}\n\nfunction isReplayUnsafePostEndpoint(url: string): boolean {\n return isUploadEndpoint(url) || isStartLargeFileEndpoint(url) || isFinishLargeFileEndpoint(url)\n}\n\n/**\n * Decide whether a classified error should be retried in place for `url`.\n * Transient errors normally retry; upload endpoints bubble to the upload layer\n * for fresh-URL retry except account-level 429 throttling, where fetching a new\n * upload URL only amplifies the rate limit.\n *\n * @param error - The classified, retryability-tagged error.\n * @param url - The request URL (used to detect upload endpoints).\n *\n * @returns Whether to retry the request in place.\n */\nfunction shouldRetryInPlace(error: B2Error, url: string): boolean {\n if (!error.retryable) return false\n if (isStartLargeFileEndpoint(url) || isFinishLargeFileEndpoint(url)) return false\n if (isUploadEndpoint(url) && error.status === 429) return true\n if (isUploadEndpoint(url)) return false\n return true\n}\n\nfunction isRequestTimeoutError(err: unknown): boolean {\n return err instanceof DOMException && err.name === 'TimeoutError'\n}\n\nfunction isTerminalTransportError(err: unknown): boolean {\n return (\n err instanceof B2Error ||\n err instanceof B2RedirectError ||\n err instanceof NetworkError ||\n err instanceof B2SsrfError ||\n (err instanceof DOMException && err.name === 'AbortError')\n )\n}\n\n/**\n * Transport wrapper that adds automatic retry with exponential backoff.\n * Handles transient errors (408, 429, and the transient 5xx set 500/502/503/504),\n * expired auth tokens, and network failures. Delegates to an inner\n * {@link HttpTransport}.\n *\n * Upload endpoints (`b2_upload_file` / `b2_upload_part`) are URL-pinned. Their\n * retryable pod failures bubble to the upload layer, which evicts the failed\n * URL, fetches a fresh one, and retries there. HTTP 429 remains an in-place\n * retry so account-level throttling does not trigger extra upload URL fetches.\n */\nexport class RetryTransport implements HttpTransport {\n /** The wrapped transport that performs actual HTTP requests. */\n private readonly inner: HttpTransport\n /** Resolved retry options (defaults merged with user overrides). */\n private readonly options: RetryOptions\n /** Optional callback to refresh auth credentials on 401 — returns the fresh token. */\n private readonly onReauth?: () => Promise<string>\n /** Sleep implementation used between retries; injectable for tests. */\n private readonly sleepImpl: (ms: number, signal?: AbortSignal) => Promise<void>\n\n /**\n * Creates a new RetryTransport.\n * @param opts - Retry transport configuration.\n */\n constructor(opts: RetryTransportOptions) {\n this.inner = opts.transport\n this.options = { ...DEFAULT_RETRY_OPTIONS, ...opts.retry }\n if (opts.onReauth !== undefined) this.onReauth = opts.onReauth\n this.sleepImpl = opts.sleepImpl ?? sleep\n }\n\n /**\n * Sends the request with automatic retry on transient failures.\n * On expired auth tokens, calls {@link RetryTransportOptions.onReauth} and retries.\n * @param originalRequest - The HTTP request to execute. The caller's\n * reference is not mutated; on reauth, a copy with a refreshed\n * Authorization header is sent.\n *\n * @returns The HTTP response.\n */\n async send(originalRequest: HttpRequest): Promise<HttpResponse> {\n // `request` is reassigned (not mutated) when reauth produces a\n // fresh Authorization header, so the caller's `originalRequest`\n // stays untouched.\n let request: HttpRequest = originalRequest\n const retryOptions = { ...this.options, ...originalRequest.retry }\n let lastError: B2Error | NetworkError | undefined\n let didReauth = false\n let attempt = 0\n\n while (attempt <= retryOptions.maxRetries) {\n throwIfSignalAborted(request.signal)\n\n if (attempt > 0 && lastError) {\n const retryAfter = lastError instanceof NetworkError ? undefined : lastError.retryAfter\n const delay = computeBackoff(attempt - 1, retryOptions, retryAfter)\n await this.sleepImpl(delay, request.signal)\n }\n\n try {\n const response = await this.inner.send({ ...request, retry: retryOptions })\n await throwIfSignalAbortedAfterResponse(request.signal, response)\n\n if (response.status >= 200 && response.status < 300) {\n return response\n }\n\n let errorBody: B2ErrorResponse\n try {\n errorBody = await response.json<B2ErrorResponse>()\n } catch (err) {\n if (isRequestTimeoutError(err)) throw err\n errorBody = {\n status: response.status,\n code: 'internal_error',\n message: `HTTP ${response.status}`,\n }\n }\n\n const retryAfterHeader = response.headers.get('Retry-After')\n const retryAfterSec = retryAfterHeader ? Number.parseInt(retryAfterHeader, 10) : undefined\n const requestId = response.headers.get('X-Bz-Request-Id') ?? undefined\n\n const error = classifyError(errorBody, {\n ...(retryAfterSec !== undefined ? { retryAfter: retryAfterSec } : {}),\n ...(requestId !== undefined ? { requestId } : {}),\n })\n\n if (\n error instanceof ExpiredAuthTokenError &&\n this.onReauth &&\n !isUploadEndpoint(request.url) &&\n !didReauth\n ) {\n // Reauth returns the FRESH token; build a new request with a\n // shallow-copied headers object so the Authorization swap\n // doesn't mutate the caller's original request (which they\n // may hold for retry / introspection). Without this swap the\n // retry would carry the expired token captured at\n // request-build time and bounce off the server again,\n // exhausting the retry budget.\n const freshToken = await this.onReauth()\n request = {\n ...request,\n headers: { ...(request.headers ?? {}), Authorization: freshToken },\n }\n didReauth = true\n lastError = undefined\n continue\n }\n\n if (!shouldRetryInPlace(error, request.url) || attempt === retryOptions.maxRetries) {\n throw error\n }\n\n lastError = error\n attempt += 1\n } catch (err) {\n throwIfSignalAborted(request.signal)\n if (isTerminalTransportError(err)) {\n throw err\n }\n\n const networkErr = new NetworkError(\n err instanceof Error ? err.message : 'Network error',\n err,\n )\n\n if (isReplayUnsafePostEndpoint(request.url) || attempt === retryOptions.maxRetries) {\n throw networkErr\n }\n\n lastError = networkErr\n attempt += 1\n }\n }\n\n throw lastError ?? new NetworkError('Max retries exceeded')\n }\n}\n\nfunction throwIfSignalAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted === true) {\n throw signal.reason ?? new DOMException('Aborted', 'AbortError')\n }\n}\n\nasync function throwIfSignalAbortedAfterResponse(\n signal: AbortSignal | undefined,\n response: HttpResponse,\n): Promise<void> {\n if (signal?.aborted !== true) return\n const reason = signal.reason ?? new DOMException('Aborted', 'AbortError')\n try {\n await response.body?.cancel(reason)\n } catch {\n // Best-effort cleanup before preserving the caller's abort reason.\n }\n throw reason\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transport.cjs","names":[],"sources":["../../src/http/transport.ts"],"sourcesContent":["import {\n B2Error,\n B2RedirectError,\n B2SsrfError,\n classifyError,\n ExpiredAuthTokenError,\n NetworkError,\n} from '../errors/index.ts'\nimport type { B2ErrorResponse } from '../types/errors.ts'\nimport { abortReason, raceWithAbort, throwIfSignalAborted } from '../util/abort.ts'\nimport {\n isBackupNonIdempotentMutationEndpoint,\n isPartnerNonIdempotentMutationEndpoint,\n} from './non-idempotent-mutations.ts'\nimport { computeBackoff, DEFAULT_RETRY_OPTIONS, type RetryOptions, sleep } from './retry.ts'\nimport { UrlGuard } from './url-guard.ts'\nimport { getUserAgent } from './user-agent.ts'\n\nconst REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308])\nconst MAX_SAME_ORIGIN_REDIRECTS = 5\n\n/** Describes an outgoing HTTP request to the B2 API. */\nexport interface HttpRequest {\n /** Fully qualified URL to send the request to. */\n readonly url: string\n /** HTTP method. B2 uses GET for downloads (HEAD to fetch only headers) and POST for all other operations. */\n readonly method: 'GET' | 'HEAD' | 'POST'\n /** Request headers. Authorization and content-type are typically included. */\n readonly headers?: Record<string, string>\n /** Request body. Used for POST requests (JSON payloads or file uploads). */\n readonly body?: BodyInit | null\n /** Optional abort signal for request cancellation. */\n readonly signal?: AbortSignal\n /** Optional per-request retry override. */\n readonly retry?: Partial<RetryOptions>\n /**\n * Set false to disable automatic retry and expired-token reauth replay.\n * This is not a general idempotency override.\n */\n readonly idempotent?: false\n}\n\n/** Represents a parsed HTTP response from the B2 API. */\nexport interface HttpResponse {\n /** HTTP status code. */\n readonly status: number\n /** Response headers. */\n readonly headers: Headers\n /** Response body as a readable stream, or null for empty responses. */\n readonly body: ReadableStream<Uint8Array> | null\n /** Parses the response body as JSON. */\n json<T>(): Promise<T>\n /** Reads the response body as a UTF-8 string. */\n text(): Promise<string>\n /** Reads the response body as an ArrayBuffer. */\n arrayBuffer(): Promise<ArrayBuffer>\n}\n\n/**\n * Transport layer abstraction for sending HTTP requests.\n * Implementations handle the actual network I/O and can be composed\n * (e.g. wrapping a {@link FetchTransport} with a {@link RetryTransport}).\n */\nexport interface HttpTransport {\n /** Sends an HTTP request and returns the response. */\n send(request: HttpRequest): Promise<HttpResponse>\n}\n\n/**\n * Transport capability for implementations that expose the SSRF URL guard\n * protecting credential-bearing requests. Wrappers that preserve this\n * capability should forward the same `urlGuard` property.\n */\nexport interface UrlGuardedTransport extends HttpTransport {\n /** SSRF allow-list applied to outgoing URLs. */\n readonly urlGuard: UrlGuard\n}\n\n/**\n * Returns the URL guard exposed by `transport`, if it implements\n * {@link UrlGuardedTransport}.\n *\n * @param transport - Transport to inspect.\n *\n * @returns The exposed URL guard, or undefined for unguarded transports.\n */\nexport function getTransportUrlGuard(transport: HttpTransport): UrlGuard | undefined {\n const candidate = transport as Partial<UrlGuardedTransport>\n return candidate.urlGuard instanceof UrlGuard ? candidate.urlGuard : undefined\n}\n\n/**\n * Default transport implementation using the global `fetch` API.\n * Automatically sets the User-Agent header on each request and applies the\n * SSRF {@link UrlGuard} (if configured) before opening the connection.\n * Redirect following is disabled so redirected URLs cannot bypass the guard or\n * receive credential-bearing headers without an explicit checked request.\n */\nexport class FetchTransport implements UrlGuardedTransport {\n /** User-Agent string sent with every request. */\n private readonly userAgent: string\n /** Whether same-origin GET/HEAD redirects should be followed after guard checks. */\n private readonly followSameOriginRedirects: boolean\n /** SSRF allow-list applied to every outgoing URL. Mutable so `B2Client.authorize()` can lock it down post-auth. */\n readonly urlGuard: UrlGuard\n\n /**\n * Creates a new FetchTransport.\n * @param options - Optional configuration: custom User-Agent prefix and SSRF guard.\n */\n constructor(options?: {\n userAgent?: string\n urlGuard?: UrlGuard\n /**\n * Follow same-origin GET/HEAD redirects after checking the target with the\n * URL guard. POST redirects are still blocked to avoid replaying\n * credential-bearing payloads to an unexpected endpoint. Defaults to true.\n */\n followSameOriginRedirects?: boolean\n }) {\n this.userAgent = getUserAgent(options?.userAgent)\n this.followSameOriginRedirects = options?.followSameOriginRedirects ?? true\n this.urlGuard = options?.urlGuard ?? new UrlGuard()\n }\n\n /**\n * Sends the request using the global `fetch` function.\n * @param request - The HTTP request to execute.\n *\n * @returns The HTTP response.\n *\n * @throws B2SsrfError when the URL fails the configured SSRF guard.\n * @throws B2RedirectError when a response attempts to redirect.\n */\n async send(request: HttpRequest): Promise<HttpResponse> {\n let currentRequest = request\n let redirectCount = 0\n\n while (true) {\n this.urlGuard.check(currentRequest.url)\n\n const headers = new Headers(currentRequest.headers)\n if (!headers.has('User-Agent')) {\n headers.set('User-Agent', this.userAgent)\n }\n\n const timeoutScope = createRequestTimeoutScope(currentRequest)\n let response: Response\n try {\n response = await fetch(currentRequest.url, {\n method: currentRequest.method,\n headers,\n body: currentRequest.body ?? null,\n redirect: 'manual',\n ...(timeoutScope.signal !== undefined ? { signal: timeoutScope.signal } : {}),\n })\n } catch (err) {\n timeoutScope.dispose()\n if (timeoutScope.timedOut) {\n throw createRequestTimeoutError(timeoutScope)\n }\n throw err\n }\n\n if (isBlockedRedirect(response)) {\n const location = response.headers.get('Location')\n if (\n this.followSameOriginRedirects &&\n location !== null &&\n redirectCount < MAX_SAME_ORIGIN_REDIRECTS &&\n canFollowSameOriginRedirect(currentRequest, location)\n ) {\n const nextUrl = new URL(location, currentRequest.url).toString()\n await cancelResponseBody(response)\n timeoutScope.dispose()\n this.urlGuard.check(nextUrl)\n currentRequest = { ...currentRequest, url: nextUrl }\n redirectCount += 1\n continue\n }\n\n await cancelResponseBody(response)\n timeoutScope.dispose()\n throw new B2RedirectError(currentRequest.url, response.status, location)\n }\n\n return createTimedHttpResponse(response, timeoutScope)\n }\n }\n}\n\ninterface RequestTimeoutScope {\n readonly signal?: AbortSignal\n readonly timeoutMs: number\n readonly timedOut: boolean\n reset(): void\n dispose(): void\n}\n\nfunction createRequestTimeoutScope(request: HttpRequest): RequestTimeoutScope {\n const timeoutMs = request.retry?.requestTimeoutMs ?? DEFAULT_RETRY_OPTIONS.requestTimeoutMs\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n const scope: RequestTimeoutScope = {\n timeoutMs: 0,\n timedOut: false,\n reset() {},\n dispose() {},\n }\n if (request.signal !== undefined) return { ...scope, signal: request.signal }\n return scope\n }\n\n const controller = new AbortController()\n let timedOut = false\n let timer: ReturnType<typeof setTimeout>\n const abortFromUpstream = (): void => {\n clearTimeout(timer)\n controller.abort(request.signal?.reason ?? new DOMException('Aborted', 'AbortError'))\n }\n const armTimer = (): ReturnType<typeof setTimeout> => {\n const nextTimer = setTimeout(() => {\n timedOut = true\n controller.abort(new DOMException('HTTP request timed out', 'TimeoutError'))\n }, timeoutMs)\n unrefTimer(nextTimer)\n return nextTimer\n }\n timer = armTimer()\n\n const reset = (): void => {\n if (timedOut || controller.signal.aborted) return\n clearTimeout(timer)\n timer = armTimer()\n }\n\n if (request.signal?.aborted === true) {\n clearTimeout(timer)\n abortFromUpstream()\n } else {\n request.signal?.addEventListener('abort', abortFromUpstream, { once: true })\n }\n\n return {\n signal: controller.signal,\n timeoutMs,\n get timedOut() {\n return timedOut\n },\n reset,\n dispose() {\n clearTimeout(timer)\n request.signal?.removeEventListener('abort', abortFromUpstream)\n },\n }\n}\n\nfunction unrefTimer(timer: ReturnType<typeof setTimeout>): void {\n const maybeUnref = (timer as { unref?: () => void }).unref\n if (typeof maybeUnref === 'function') maybeUnref.call(timer)\n}\n\nfunction createRequestTimeoutError(scope: RequestTimeoutScope): DOMException {\n return new DOMException(`HTTP request timed out after ${scope.timeoutMs} ms`, 'TimeoutError')\n}\n\nfunction createTimedHttpResponse(\n response: Response,\n timeoutScope: RequestTimeoutScope,\n): HttpResponse {\n const body = response.body\n if (body === null) timeoutScope.dispose()\n let timedBody: ReadableStream<Uint8Array> | undefined\n\n return {\n status: response.status,\n headers: response.headers,\n get body() {\n if (body === null) return null\n timedBody ??= createTimedResponseBody(body, timeoutScope)\n return timedBody\n },\n json: <T>() =>\n readTimedResponseBody(timeoutScope, response, () => response.json() as Promise<T>),\n text: () => readTimedResponseBody(timeoutScope, response, () => response.text()),\n arrayBuffer: () => readTimedResponseBody(timeoutScope, response, () => response.arrayBuffer()),\n }\n}\n\nasync function readTimedResponseBody<T>(\n timeoutScope: RequestTimeoutScope,\n response: Response,\n read: () => Promise<T>,\n): Promise<T> {\n try {\n return await raceBodyReadWithAbort(timeoutScope, read(), (reason) =>\n cancelResponseBody(response, reason),\n )\n } catch (err) {\n if (timeoutScope.timedOut) {\n throw createRequestTimeoutError(timeoutScope)\n }\n throw err\n } finally {\n timeoutScope.dispose()\n }\n}\n\nfunction createTimedResponseBody(\n body: ReadableStream<Uint8Array>,\n timeoutScope: RequestTimeoutScope,\n): ReadableStream<Uint8Array> {\n let reader: ReadableStreamDefaultReader<Uint8Array> | undefined\n let disposed = false\n const dispose = (): void => {\n if (disposed) return\n disposed = true\n timeoutScope.dispose()\n }\n\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n reader ??= body.getReader()\n try {\n const result = await raceBodyReadWithAbort(timeoutScope, reader.read(), (reason) =>\n reader?.cancel(reason),\n )\n if (result.done) {\n dispose()\n controller.close()\n return\n }\n timeoutScope.reset()\n controller.enqueue(result.value)\n } catch (err) {\n dispose()\n if (timeoutScope.timedOut) {\n controller.error(createRequestTimeoutError(timeoutScope))\n return\n }\n controller.error(err)\n }\n },\n async cancel(reason) {\n dispose()\n try {\n if (reader !== undefined) {\n await reader.cancel(reason)\n return\n }\n await body.cancel(reason)\n } catch {\n // Best-effort cleanup when the caller cancels the wrapper body.\n }\n },\n })\n}\n\nasync function raceBodyReadWithAbort<T>(\n timeoutScope: RequestTimeoutScope,\n read: Promise<T>,\n abortCleanup?: ((reason: unknown) => Promise<void> | void) | undefined,\n): Promise<T> {\n const signal = timeoutScope.signal\n if (signal === undefined) return read\n if (signal.aborted) {\n void read.catch(() => {})\n const reason = abortReason(signal)\n await runAbortCleanup(abortCleanup, reason)\n throw reason\n }\n\n let removeAbortListener: (() => void) | undefined\n const abort = new Promise<never>((_, reject) => {\n const onAbort = (): void => {\n const reason = abortReason(signal)\n void read.catch(() => {})\n reject(reason)\n void runAbortCleanup(abortCleanup, reason)\n }\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n return await Promise.race([read, abort])\n } finally {\n removeAbortListener?.()\n }\n}\n\nasync function runAbortCleanup(\n abortCleanup: ((reason: unknown) => Promise<void> | void) | undefined,\n reason: unknown,\n): Promise<void> {\n try {\n await abortCleanup?.(reason)\n } catch {\n // Abort cleanup is best-effort and must not mask the abort reason.\n }\n}\n\nfunction isBlockedRedirect(response: Response): boolean {\n return response.type === 'opaqueredirect' || REDIRECT_STATUSES.has(response.status)\n}\n\nfunction canFollowSameOriginRedirect(request: HttpRequest, location: string): boolean {\n if (request.method !== 'GET' && request.method !== 'HEAD') return false\n try {\n return new URL(request.url).origin === new URL(location, request.url).origin\n } catch {\n return false\n }\n}\n\nasync function cancelResponseBody(response: Response, reason?: unknown): Promise<void> {\n try {\n await response.body?.cancel(reason)\n } catch {\n // Best-effort cleanup before throwing the primary error.\n }\n}\n\n/** Configuration for {@link RetryTransport}. */\nexport interface RetryTransportOptions {\n /** The underlying transport to delegate requests to. */\n readonly transport: HttpTransport\n /** Override default retry settings (max retries, delays). */\n readonly retry?: Partial<RetryOptions>\n /**\n * Callback invoked on expired auth token errors. Must refresh\n * credentials AND return the fresh auth token. The original request's\n * abort signal is forwarded so reauthorization can be cancelled with the\n * operation that triggered it. The transport\n * substitutes the new token into `request.headers.Authorization`\n * before retrying — without this, the retried request would still\n * carry the expired token captured by the original caller and the\n * loop would never make progress.\n */\n readonly onReauth?: (signal?: AbortSignal) => Promise<string>\n /**\n * Sleep implementation used between retry attempts. Defaults to the real\n * `sleep` from `./retry.js`. Test code can inject a no-op to avoid real\n * delays without relying on module mocking (which differs across runners).\n *\n * @internal\n */\n readonly sleepImpl?: (ms: number, signal?: AbortSignal) => Promise<void>\n}\n\n/**\n * Decide whether `url` points at a URL-pinned upload POST endpoint.\n *\n * @param url - Request URL to inspect.\n *\n * @returns Whether the request is a direct upload endpoint.\n */\nfunction isUploadEndpoint(url: string): boolean {\n const endpoint = b2ApiEndpointName(url)\n return endpoint === 'b2_upload_file' || endpoint === 'b2_upload_part'\n}\n\nfunction isFinishLargeFileEndpoint(url: string): boolean {\n return b2ApiEndpointName(url) === 'b2_finish_large_file'\n}\n\nfunction isAuthorizeEndpoint(url: string): boolean {\n return b2ApiEndpointName(url) === 'b2_authorize_account'\n}\n\nfunction isStartLargeFileEndpoint(url: string): boolean {\n return b2ApiEndpointName(url) === 'b2_start_large_file'\n}\n\nfunction isKnownPartnerNonIdempotentMutationEndpoint(url: string): boolean {\n return isPartnerNonIdempotentMutationEndpoint(b2ApiEndpointName(url))\n}\n\nfunction isKnownBackupNonIdempotentMutationEndpoint(url: string): boolean {\n return isBackupNonIdempotentMutationEndpoint(backupApiEndpointName(url))\n}\n\nfunction isNonIdempotentMutationRequest(request: HttpRequest): boolean {\n // Defense in depth: known mutations must not replay if a wrapper drops\n // the raw client's explicit `idempotent: false` marker.\n return (\n request.idempotent === false ||\n (request.method === 'POST' &&\n (isKnownPartnerNonIdempotentMutationEndpoint(request.url) ||\n isKnownBackupNonIdempotentMutationEndpoint(request.url)))\n )\n}\n\nfunction b2ApiEndpointName(url: string): string | undefined {\n const segments = new URL(url).pathname.split('/').filter((segment) => segment.length > 0)\n // Partner endpoint base URLs can themselves contain a b2api-looking segment\n // before the SDK appends the real API route. Classify the terminal route.\n const apiRootIndex = segments.lastIndexOf('b2api')\n if (apiRootIndex === -1) return undefined\n return segments[apiRootIndex + 2]\n}\n\nfunction backupApiEndpointName(url: string): string | undefined {\n const segments = new URL(url).pathname.split('/').filter((segment) => segment.length > 0)\n const apiRootIndex = segments.lastIndexOf('api')\n if (apiRootIndex === -1 || segments[apiRootIndex + 1] !== 'backup') return undefined\n if (!/^v\\d+$/.test(segments[apiRootIndex + 2] ?? '')) return undefined\n return segments[apiRootIndex + 3]\n}\n\nfunction isReplayUnsafeRequest(request: HttpRequest): boolean {\n if (request.idempotent === false) return true\n if (request.method !== 'POST') return false\n return (\n isUploadEndpoint(request.url) ||\n isStartLargeFileEndpoint(request.url) ||\n isFinishLargeFileEndpoint(request.url) ||\n isNonIdempotentMutationRequest(request)\n )\n}\n\n/**\n * Decide whether a classified error should be retried in place for `url`.\n * Transient errors normally retry; upload endpoints bubble to the upload layer\n * for fresh-URL retry except account-level 429 throttling, where fetching a new\n * upload URL only amplifies the rate limit.\n *\n * @param error - The classified, retryability-tagged error.\n * @param request - The request being considered for in-place retry.\n *\n * @returns Whether to retry the request in place.\n */\nfunction shouldRetryInPlace(error: B2Error, request: HttpRequest): boolean {\n if (!error.retryable) return false\n if (isAuthorizeEndpoint(request.url) && error instanceof ExpiredAuthTokenError) return false\n if (isNonIdempotentMutationRequest(request)) return false\n if (isStartLargeFileEndpoint(request.url) || isFinishLargeFileEndpoint(request.url)) return false\n if (isUploadEndpoint(request.url) && error.status === 429) return true\n if (isUploadEndpoint(request.url)) return false\n return true\n}\n\nfunction isRequestTimeoutError(err: unknown): boolean {\n return err instanceof DOMException && err.name === 'TimeoutError'\n}\n\nfunction isTerminalTransportError(err: unknown): boolean {\n return (\n err instanceof B2Error ||\n err instanceof B2RedirectError ||\n err instanceof NetworkError ||\n err instanceof B2SsrfError ||\n (err instanceof DOMException && err.name === 'AbortError')\n )\n}\n\n/**\n * Transport wrapper that adds automatic retry with exponential backoff.\n * Handles transient errors (408, 429, and the transient 5xx set 500/502/503/504),\n * expired auth tokens, and network failures. Delegates to an inner\n * {@link HttpTransport}.\n *\n * Upload endpoints (`b2_upload_file` / `b2_upload_part`) are URL-pinned. Their\n * retryable pod failures bubble to the upload layer, which evicts the failed\n * URL, fetches a fresh one, and retries there. HTTP 429 remains an in-place\n * retry so account-level throttling does not trigger extra upload URL fetches.\n */\nexport class RetryTransport implements HttpTransport {\n /** URL guard from the wrapped transport, when the transport exposes one. */\n readonly urlGuard: UrlGuard | undefined\n /** The wrapped transport that performs actual HTTP requests. */\n private readonly inner: HttpTransport\n /** Resolved retry options (defaults merged with user overrides). */\n private readonly options: RetryOptions\n /** Optional callback to refresh auth credentials on 401 — returns the fresh token. */\n private readonly onReauth?: (signal?: AbortSignal) => Promise<string>\n /** Sleep implementation used between retries; injectable for tests. */\n private readonly sleepImpl: (ms: number, signal?: AbortSignal) => Promise<void>\n\n /**\n * Creates a new RetryTransport.\n * @param opts - Retry transport configuration.\n */\n constructor(opts: RetryTransportOptions) {\n this.inner = opts.transport\n this.urlGuard = getTransportUrlGuard(opts.transport)\n this.options = { ...DEFAULT_RETRY_OPTIONS, ...opts.retry }\n if (opts.onReauth !== undefined) this.onReauth = opts.onReauth\n this.sleepImpl = opts.sleepImpl ?? sleep\n }\n\n /**\n * Sends the request with automatic retry on transient failures.\n * On expired auth tokens, calls {@link RetryTransportOptions.onReauth} and retries.\n * @param originalRequest - The HTTP request to execute. The caller's\n * reference is not mutated; on reauth, a copy with a refreshed\n * Authorization header is sent.\n *\n * @returns The HTTP response.\n */\n async send(originalRequest: HttpRequest): Promise<HttpResponse> {\n // `request` is reassigned (not mutated) when reauth produces a\n // fresh Authorization header, so the caller's `originalRequest`\n // stays untouched.\n let request: HttpRequest = originalRequest\n const retryOptions = { ...this.options, ...originalRequest.retry }\n let lastError: B2Error | NetworkError | undefined\n let didReauth = false\n let attempt = 0\n\n while (attempt <= retryOptions.maxRetries) {\n throwIfSignalAborted(request.signal)\n\n if (attempt > 0 && lastError) {\n const retryAfter = lastError instanceof NetworkError ? undefined : lastError.retryAfter\n const delay = computeBackoff(attempt - 1, retryOptions, retryAfter)\n await this.sleepImpl(delay, request.signal)\n }\n\n try {\n const response = await this.inner.send({ ...request, retry: retryOptions })\n await throwIfSignalAbortedAfterResponse(request.signal, response)\n\n if (response.status >= 200 && response.status < 300) {\n return response\n }\n\n let errorBody: B2ErrorResponse\n try {\n errorBody = await response.json<B2ErrorResponse>()\n } catch (err) {\n if (isRequestTimeoutError(err)) throw err\n errorBody = {\n status: response.status,\n code: 'internal_error',\n message: `HTTP ${response.status}`,\n }\n }\n\n const retryAfterHeader = response.headers.get('Retry-After')\n const retryAfterSec = retryAfterHeader ? Number.parseInt(retryAfterHeader, 10) : undefined\n const requestId = response.headers.get('X-Bz-Request-Id') ?? undefined\n\n const error = classifyError(errorBody, {\n ...(retryAfterSec !== undefined ? { retryAfter: retryAfterSec } : {}),\n ...(requestId !== undefined ? { requestId } : {}),\n })\n\n if (\n error instanceof ExpiredAuthTokenError &&\n this.onReauth &&\n !isAuthorizeEndpoint(request.url) &&\n !isUploadEndpoint(request.url) &&\n !isNonIdempotentMutationRequest(request) &&\n !didReauth\n ) {\n // Reauth returns the FRESH token; build a new request with a\n // shallow-copied headers object so the Authorization swap\n // doesn't mutate the caller's original request (which they\n // may hold for retry / introspection). Without this swap the\n // retry would carry the expired token captured at\n // request-build time and bounce off the server again,\n // exhausting the retry budget.\n const freshToken = await raceWithAbort(this.onReauth(request.signal), request.signal)\n throwIfSignalAborted(request.signal)\n request = {\n ...request,\n headers: { ...(request.headers ?? {}), Authorization: freshToken },\n }\n didReauth = true\n lastError = undefined\n continue\n }\n\n if (!shouldRetryInPlace(error, request) || attempt === retryOptions.maxRetries) {\n throw error\n }\n\n lastError = error\n attempt += 1\n } catch (err) {\n throwIfSignalAborted(request.signal)\n if (isTerminalTransportError(err)) {\n throw err\n }\n\n const networkErr = new NetworkError(\n err instanceof Error ? err.message : 'Network error',\n err,\n )\n\n if (isReplayUnsafeRequest(request) || attempt === retryOptions.maxRetries) {\n throw networkErr\n }\n\n lastError = networkErr\n attempt += 1\n }\n }\n\n throw lastError ?? new NetworkError('Max retries exceeded')\n }\n}\n\nasync function throwIfSignalAbortedAfterResponse(\n signal: AbortSignal | undefined,\n response: HttpResponse,\n): Promise<void> {\n if (signal?.aborted !== true) return\n const reason = abortReason(signal)\n try {\n await response.body?.cancel(reason)\n } catch {\n // Best-effort cleanup before preserving the caller's abort reason.\n }\n throw reason\n}\n"],"mappings":"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"}
|
|
@@ -14,6 +14,11 @@ export interface HttpRequest {
|
|
|
14
14
|
readonly signal?: AbortSignal;
|
|
15
15
|
/** Optional per-request retry override. */
|
|
16
16
|
readonly retry?: Partial<RetryOptions>;
|
|
17
|
+
/**
|
|
18
|
+
* Set false to disable automatic retry and expired-token reauth replay.
|
|
19
|
+
* This is not a general idempotency override.
|
|
20
|
+
*/
|
|
21
|
+
readonly idempotent?: false;
|
|
17
22
|
}
|
|
18
23
|
/** Represents a parsed HTTP response from the B2 API. */
|
|
19
24
|
export interface HttpResponse {
|
|
@@ -39,6 +44,24 @@ export interface HttpTransport {
|
|
|
39
44
|
/** Sends an HTTP request and returns the response. */
|
|
40
45
|
send(request: HttpRequest): Promise<HttpResponse>;
|
|
41
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Transport capability for implementations that expose the SSRF URL guard
|
|
49
|
+
* protecting credential-bearing requests. Wrappers that preserve this
|
|
50
|
+
* capability should forward the same `urlGuard` property.
|
|
51
|
+
*/
|
|
52
|
+
export interface UrlGuardedTransport extends HttpTransport {
|
|
53
|
+
/** SSRF allow-list applied to outgoing URLs. */
|
|
54
|
+
readonly urlGuard: UrlGuard;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns the URL guard exposed by `transport`, if it implements
|
|
58
|
+
* {@link UrlGuardedTransport}.
|
|
59
|
+
*
|
|
60
|
+
* @param transport - Transport to inspect.
|
|
61
|
+
*
|
|
62
|
+
* @returns The exposed URL guard, or undefined for unguarded transports.
|
|
63
|
+
*/
|
|
64
|
+
export declare function getTransportUrlGuard(transport: HttpTransport): UrlGuard | undefined;
|
|
42
65
|
/**
|
|
43
66
|
* Default transport implementation using the global `fetch` API.
|
|
44
67
|
* Automatically sets the User-Agent header on each request and applies the
|
|
@@ -46,7 +69,7 @@ export interface HttpTransport {
|
|
|
46
69
|
* Redirect following is disabled so redirected URLs cannot bypass the guard or
|
|
47
70
|
* receive credential-bearing headers without an explicit checked request.
|
|
48
71
|
*/
|
|
49
|
-
export declare class FetchTransport implements
|
|
72
|
+
export declare class FetchTransport implements UrlGuardedTransport {
|
|
50
73
|
/** User-Agent string sent with every request. */
|
|
51
74
|
private readonly userAgent;
|
|
52
75
|
/** Whether same-origin GET/HEAD redirects should be followed after guard checks. */
|
|
@@ -86,13 +109,15 @@ export interface RetryTransportOptions {
|
|
|
86
109
|
readonly retry?: Partial<RetryOptions>;
|
|
87
110
|
/**
|
|
88
111
|
* Callback invoked on expired auth token errors. Must refresh
|
|
89
|
-
* credentials AND return the fresh auth token. The
|
|
112
|
+
* credentials AND return the fresh auth token. The original request's
|
|
113
|
+
* abort signal is forwarded so reauthorization can be cancelled with the
|
|
114
|
+
* operation that triggered it. The transport
|
|
90
115
|
* substitutes the new token into `request.headers.Authorization`
|
|
91
116
|
* before retrying — without this, the retried request would still
|
|
92
117
|
* carry the expired token captured by the original caller and the
|
|
93
118
|
* loop would never make progress.
|
|
94
119
|
*/
|
|
95
|
-
readonly onReauth?: () => Promise<string>;
|
|
120
|
+
readonly onReauth?: (signal?: AbortSignal) => Promise<string>;
|
|
96
121
|
/**
|
|
97
122
|
* Sleep implementation used between retry attempts. Defaults to the real
|
|
98
123
|
* `sleep` from `./retry.js`. Test code can inject a no-op to avoid real
|
|
@@ -114,6 +139,8 @@ export interface RetryTransportOptions {
|
|
|
114
139
|
* retry so account-level throttling does not trigger extra upload URL fetches.
|
|
115
140
|
*/
|
|
116
141
|
export declare class RetryTransport implements HttpTransport {
|
|
142
|
+
/** URL guard from the wrapped transport, when the transport exposes one. */
|
|
143
|
+
readonly urlGuard: UrlGuard | undefined;
|
|
117
144
|
/** The wrapped transport that performs actual HTTP requests. */
|
|
118
145
|
private readonly inner;
|
|
119
146
|
/** Resolved retry options (defaults merged with user overrides). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/http/transport.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/http/transport.js"],"names":[],"mappings":"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"}
|
package/dist/http/transport.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ export interface HttpRequest {
|
|
|
14
14
|
readonly signal?: AbortSignal;
|
|
15
15
|
/** Optional per-request retry override. */
|
|
16
16
|
readonly retry?: Partial<RetryOptions>;
|
|
17
|
+
/**
|
|
18
|
+
* Set false to disable automatic retry and expired-token reauth replay.
|
|
19
|
+
* This is not a general idempotency override.
|
|
20
|
+
*/
|
|
21
|
+
readonly idempotent?: false;
|
|
17
22
|
}
|
|
18
23
|
/** Represents a parsed HTTP response from the B2 API. */
|
|
19
24
|
export interface HttpResponse {
|
|
@@ -39,6 +44,24 @@ export interface HttpTransport {
|
|
|
39
44
|
/** Sends an HTTP request and returns the response. */
|
|
40
45
|
send(request: HttpRequest): Promise<HttpResponse>;
|
|
41
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Transport capability for implementations that expose the SSRF URL guard
|
|
49
|
+
* protecting credential-bearing requests. Wrappers that preserve this
|
|
50
|
+
* capability should forward the same `urlGuard` property.
|
|
51
|
+
*/
|
|
52
|
+
export interface UrlGuardedTransport extends HttpTransport {
|
|
53
|
+
/** SSRF allow-list applied to outgoing URLs. */
|
|
54
|
+
readonly urlGuard: UrlGuard;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns the URL guard exposed by `transport`, if it implements
|
|
58
|
+
* {@link UrlGuardedTransport}.
|
|
59
|
+
*
|
|
60
|
+
* @param transport - Transport to inspect.
|
|
61
|
+
*
|
|
62
|
+
* @returns The exposed URL guard, or undefined for unguarded transports.
|
|
63
|
+
*/
|
|
64
|
+
export declare function getTransportUrlGuard(transport: HttpTransport): UrlGuard | undefined;
|
|
42
65
|
/**
|
|
43
66
|
* Default transport implementation using the global `fetch` API.
|
|
44
67
|
* Automatically sets the User-Agent header on each request and applies the
|
|
@@ -46,7 +69,7 @@ export interface HttpTransport {
|
|
|
46
69
|
* Redirect following is disabled so redirected URLs cannot bypass the guard or
|
|
47
70
|
* receive credential-bearing headers without an explicit checked request.
|
|
48
71
|
*/
|
|
49
|
-
export declare class FetchTransport implements
|
|
72
|
+
export declare class FetchTransport implements UrlGuardedTransport {
|
|
50
73
|
/** User-Agent string sent with every request. */
|
|
51
74
|
private readonly userAgent;
|
|
52
75
|
/** Whether same-origin GET/HEAD redirects should be followed after guard checks. */
|
|
@@ -86,13 +109,15 @@ export interface RetryTransportOptions {
|
|
|
86
109
|
readonly retry?: Partial<RetryOptions>;
|
|
87
110
|
/**
|
|
88
111
|
* Callback invoked on expired auth token errors. Must refresh
|
|
89
|
-
* credentials AND return the fresh auth token. The
|
|
112
|
+
* credentials AND return the fresh auth token. The original request's
|
|
113
|
+
* abort signal is forwarded so reauthorization can be cancelled with the
|
|
114
|
+
* operation that triggered it. The transport
|
|
90
115
|
* substitutes the new token into `request.headers.Authorization`
|
|
91
116
|
* before retrying — without this, the retried request would still
|
|
92
117
|
* carry the expired token captured by the original caller and the
|
|
93
118
|
* loop would never make progress.
|
|
94
119
|
*/
|
|
95
|
-
readonly onReauth?: () => Promise<string>;
|
|
120
|
+
readonly onReauth?: (signal?: AbortSignal) => Promise<string>;
|
|
96
121
|
/**
|
|
97
122
|
* Sleep implementation used between retry attempts. Defaults to the real
|
|
98
123
|
* `sleep` from `./retry.js`. Test code can inject a no-op to avoid real
|
|
@@ -114,6 +139,8 @@ export interface RetryTransportOptions {
|
|
|
114
139
|
* retry so account-level throttling does not trigger extra upload URL fetches.
|
|
115
140
|
*/
|
|
116
141
|
export declare class RetryTransport implements HttpTransport {
|
|
142
|
+
/** URL guard from the wrapped transport, when the transport exposes one. */
|
|
143
|
+
readonly urlGuard: UrlGuard | undefined;
|
|
117
144
|
/** The wrapped transport that performs actual HTTP requests. */
|
|
118
145
|
private readonly inner;
|
|
119
146
|
/** Resolved retry options (defaults merged with user overrides). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/http/transport.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/http/transport.js"],"names":[],"mappings":"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"}
|