@backblaze-labs/b2-sdk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +110 -5
- package/README.md +144 -33
- package/dist/_virtual/_b2-sdk-version-json.cjs +4 -0
- package/dist/_virtual/_b2-sdk-version-json.js +4 -0
- package/dist/auth/account-info.d.cts +32 -0
- package/dist/auth/account-info.d.cts.map +1 -1
- package/dist/auth/account-info.d.ts +32 -0
- package/dist/auth/account-info.d.ts.map +1 -1
- package/dist/auth/file.cjs +408 -207
- package/dist/auth/file.cjs.map +1 -1
- package/dist/auth/file.d.cts +77 -3
- package/dist/auth/file.d.cts.map +1 -1
- package/dist/auth/file.d.ts +77 -3
- package/dist/auth/file.d.ts.map +1 -1
- package/dist/auth/file.js +407 -207
- package/dist/auth/file.js.map +1 -1
- package/dist/auth/in-memory.cjs +212 -183
- package/dist/auth/in-memory.cjs.map +1 -1
- package/dist/auth/in-memory.d.cts +8 -0
- package/dist/auth/in-memory.d.cts.map +1 -1
- package/dist/auth/in-memory.d.ts +8 -0
- package/dist/auth/in-memory.d.ts.map +1 -1
- package/dist/auth/in-memory.js +211 -182
- package/dist/auth/in-memory.js.map +1 -1
- package/dist/auth/index.cjs +7 -9
- package/dist/auth/index.d.cts +3 -2
- package/dist/auth/index.d.cts.map +1 -1
- package/dist/auth/index.d.ts +3 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +2 -8
- package/dist/auth/realms.cjs +80 -7
- package/dist/auth/realms.cjs.map +1 -1
- package/dist/auth/realms.d.cts +27 -4
- package/dist/auth/realms.d.cts.map +1 -1
- package/dist/auth/realms.d.ts +27 -4
- package/dist/auth/realms.d.ts.map +1 -1
- package/dist/auth/realms.js +80 -9
- package/dist/auth/realms.js.map +1 -1
- package/dist/auth/upload-url-pool.cjs +55 -51
- package/dist/auth/upload-url-pool.cjs.map +1 -1
- package/dist/auth/upload-url-pool.js +55 -51
- package/dist/auth/upload-url-pool.js.map +1 -1
- package/dist/bucket.cjs +785 -787
- package/dist/bucket.cjs.map +1 -1
- package/dist/bucket.d.cts +35 -47
- package/dist/bucket.d.cts.map +1 -1
- package/dist/bucket.d.ts +35 -47
- package/dist/bucket.d.ts.map +1 -1
- package/dist/bucket.js +780 -782
- package/dist/bucket.js.map +1 -1
- package/dist/client.cjs +246 -228
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +25 -17
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.ts +25 -17
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +243 -225
- package/dist/client.js.map +1 -1
- package/dist/copy/large.cjs +114 -71
- package/dist/copy/large.cjs.map +1 -1
- package/dist/copy/large.d.cts +6 -0
- package/dist/copy/large.d.cts.map +1 -1
- package/dist/copy/large.d.ts +6 -0
- package/dist/copy/large.d.ts.map +1 -1
- package/dist/copy/large.js +112 -69
- package/dist/copy/large.js.map +1 -1
- package/dist/download/checksum.cjs +89 -0
- package/dist/download/checksum.cjs.map +1 -0
- package/dist/download/checksum.d.cts +40 -0
- package/dist/download/checksum.d.cts.map +1 -0
- package/dist/download/checksum.d.ts +40 -0
- package/dist/download/checksum.d.ts.map +1 -0
- package/dist/download/checksum.js +87 -0
- package/dist/download/checksum.js.map +1 -0
- package/dist/download/parallel.cjs +214 -118
- package/dist/download/parallel.cjs.map +1 -1
- package/dist/download/parallel.d.cts +5 -1
- package/dist/download/parallel.d.cts.map +1 -1
- package/dist/download/parallel.d.ts +5 -1
- package/dist/download/parallel.d.ts.map +1 -1
- package/dist/download/parallel.js +212 -116
- package/dist/download/parallel.js.map +1 -1
- package/dist/download/single.cjs +188 -97
- package/dist/download/single.cjs.map +1 -1
- package/dist/download/single.d.cts +6 -1
- package/dist/download/single.d.cts.map +1 -1
- package/dist/download/single.d.ts +6 -1
- package/dist/download/single.d.ts.map +1 -1
- package/dist/download/single.js +186 -98
- package/dist/download/single.js.map +1 -1
- package/dist/errors/index.cjs +699 -243
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.cts +285 -82
- package/dist/errors/index.d.cts.map +1 -1
- package/dist/errors/index.d.ts +285 -82
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +678 -261
- package/dist/errors/index.js.map +1 -1
- package/dist/http/retry.cjs +45 -28
- package/dist/http/retry.cjs.map +1 -1
- package/dist/http/retry.d.cts +15 -2
- package/dist/http/retry.d.cts.map +1 -1
- package/dist/http/retry.d.ts +15 -2
- package/dist/http/retry.d.ts.map +1 -1
- package/dist/http/retry.js +46 -31
- package/dist/http/retry.js.map +1 -1
- package/dist/http/transport.cjs +438 -140
- package/dist/http/transport.cjs.map +1 -1
- package/dist/http/transport.d.cts +21 -2
- package/dist/http/transport.d.cts.map +1 -1
- package/dist/http/transport.d.ts +21 -2
- package/dist/http/transport.d.ts.map +1 -1
- package/dist/http/transport.js +437 -140
- package/dist/http/transport.js.map +1 -1
- package/dist/http/url-guard.cjs +154 -89
- package/dist/http/url-guard.cjs.map +1 -1
- package/dist/http/url-guard.d.cts +25 -3
- package/dist/http/url-guard.d.cts.map +1 -1
- package/dist/http/url-guard.d.ts +25 -3
- package/dist/http/url-guard.d.ts.map +1 -1
- package/dist/http/url-guard.js +152 -90
- package/dist/http/url-guard.js.map +1 -1
- package/dist/http/user-agent.cjs +84 -44
- package/dist/http/user-agent.cjs.map +1 -1
- package/dist/http/user-agent.js +84 -46
- package/dist/http/user-agent.js.map +1 -1
- package/dist/index.cjs +101 -77
- package/dist/index.d.cts +27 -21
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +27 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -71
- package/dist/internal/b2-naming.cjs +66 -0
- package/dist/internal/b2-naming.cjs.map +1 -0
- package/dist/internal/b2-naming.d.cts +43 -0
- package/dist/internal/b2-naming.d.cts.map +1 -0
- package/dist/internal/b2-naming.d.ts +43 -0
- package/dist/internal/b2-naming.d.ts.map +1 -0
- package/dist/internal/b2-naming.js +60 -0
- package/dist/internal/b2-naming.js.map +1 -0
- package/dist/internal/upload-retry-options.cjs +21 -0
- package/dist/internal/upload-retry-options.cjs.map +1 -0
- package/dist/internal/upload-retry-options.d.cts +12 -0
- package/dist/internal/upload-retry-options.d.cts.map +1 -0
- package/dist/internal/upload-retry-options.d.ts +12 -0
- package/dist/internal/upload-retry-options.d.ts.map +1 -0
- package/dist/internal/upload-retry-options.js +21 -0
- package/dist/internal/upload-retry-options.js.map +1 -0
- package/dist/internal/url-redaction.cjs +31 -0
- package/dist/internal/url-redaction.cjs.map +1 -0
- package/dist/internal/url-redaction.d.cts +17 -0
- package/dist/internal/url-redaction.d.cts.map +1 -0
- package/dist/internal/url-redaction.d.ts +17 -0
- package/dist/internal/url-redaction.d.ts.map +1 -0
- package/dist/internal/url-redaction.js +31 -0
- package/dist/internal/url-redaction.js.map +1 -0
- package/dist/notifications/index.cjs +4 -6
- package/dist/notifications/index.d.cts +1 -1
- package/dist/notifications/index.d.cts.map +1 -1
- package/dist/notifications/index.d.ts +1 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +1 -6
- package/dist/notifications/webhook.cjs +195 -85
- package/dist/notifications/webhook.cjs.map +1 -1
- package/dist/notifications/webhook.d.cts.map +1 -1
- package/dist/notifications/webhook.d.ts.map +1 -1
- package/dist/notifications/webhook.js +195 -87
- package/dist/notifications/webhook.js.map +1 -1
- package/dist/object.cjs +253 -210
- package/dist/object.cjs.map +1 -1
- package/dist/object.d.cts +9 -55
- package/dist/object.d.cts.map +1 -1
- package/dist/object.d.ts +9 -55
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +249 -206
- package/dist/object.js.map +1 -1
- package/dist/raw/encoding.cjs +74 -35
- package/dist/raw/encoding.cjs.map +1 -1
- package/dist/raw/encoding.js +74 -38
- package/dist/raw/encoding.js.map +1 -1
- package/dist/raw/index.cjs +678 -587
- package/dist/raw/index.cjs.map +1 -1
- package/dist/raw/index.d.cts +121 -18
- package/dist/raw/index.d.cts.map +1 -1
- package/dist/raw/index.d.ts +121 -18
- package/dist/raw/index.d.ts.map +1 -1
- package/dist/raw/index.js +674 -589
- package/dist/raw/index.js.map +1 -1
- package/dist/s3/index.cjs +355 -18
- package/dist/s3/index.cjs.map +1 -1
- package/dist/s3/index.d.cts +233 -5
- package/dist/s3/index.d.cts.map +1 -1
- package/dist/s3/index.d.ts +233 -5
- package/dist/s3/index.d.ts.map +1 -1
- package/dist/s3/index.js +351 -22
- package/dist/s3/index.js.map +1 -1
- package/dist/s3/sigv4.cjs +149 -0
- package/dist/s3/sigv4.cjs.map +1 -0
- package/dist/s3/sigv4.d.cts +43 -0
- package/dist/s3/sigv4.d.cts.map +1 -0
- package/dist/s3/sigv4.d.ts +43 -0
- package/dist/s3/sigv4.d.ts.map +1 -0
- package/dist/s3/sigv4.js +148 -0
- package/dist/s3/sigv4.js.map +1 -0
- package/dist/s3/validation.cjs +69 -0
- package/dist/s3/validation.cjs.map +1 -0
- package/dist/s3/validation.d.cts +43 -0
- package/dist/s3/validation.d.cts.map +1 -0
- package/dist/s3/validation.d.ts +43 -0
- package/dist/s3/validation.d.ts.map +1 -0
- package/dist/s3/validation.js +66 -0
- package/dist/s3/validation.js.map +1 -0
- package/dist/simulator/capabilities.cjs +63 -48
- package/dist/simulator/capabilities.cjs.map +1 -1
- package/dist/simulator/capabilities.js +63 -49
- package/dist/simulator/capabilities.js.map +1 -1
- package/dist/simulator/index.cjs +2124 -1548
- package/dist/simulator/index.cjs.map +1 -1
- package/dist/simulator/index.d.cts +79 -11
- package/dist/simulator/index.d.cts.map +1 -1
- package/dist/simulator/index.d.ts +79 -11
- package/dist/simulator/index.d.ts.map +1 -1
- package/dist/simulator/index.js +2112 -1546
- package/dist/simulator/index.js.map +1 -1
- package/dist/simulator/validation.cjs +191 -153
- package/dist/simulator/validation.cjs.map +1 -1
- package/dist/simulator/validation.d.cts +3 -21
- package/dist/simulator/validation.d.cts.map +1 -1
- package/dist/simulator/validation.d.ts +3 -21
- package/dist/simulator/validation.d.ts.map +1 -1
- package/dist/simulator/validation.js +188 -162
- package/dist/simulator/validation.js.map +1 -1
- package/dist/streams/collect.cjs +74 -24
- package/dist/streams/collect.cjs.map +1 -1
- package/dist/streams/collect.d.cts +14 -1
- package/dist/streams/collect.d.cts.map +1 -1
- package/dist/streams/collect.d.ts +14 -1
- package/dist/streams/collect.d.ts.map +1 -1
- package/dist/streams/collect.js +74 -25
- package/dist/streams/collect.js.map +1 -1
- package/dist/streams/file-source.cjs +287 -0
- package/dist/streams/file-source.cjs.map +1 -0
- package/dist/streams/file-source.d.cts +96 -0
- package/dist/streams/file-source.d.cts.map +1 -0
- package/dist/streams/file-source.d.ts +96 -0
- package/dist/streams/file-source.d.ts.map +1 -0
- package/dist/streams/file-source.js +286 -0
- package/dist/streams/file-source.js.map +1 -0
- package/dist/streams/hash.cjs +207 -115
- package/dist/streams/hash.cjs.map +1 -1
- package/dist/streams/hash.d.cts +5 -4
- package/dist/streams/hash.d.cts.map +1 -1
- package/dist/streams/hash.d.ts +5 -4
- package/dist/streams/hash.d.ts.map +1 -1
- package/dist/streams/hash.js +208 -95
- package/dist/streams/hash.js.map +1 -1
- package/dist/streams/index.cjs +12 -12
- package/dist/streams/index.d.cts +3 -3
- package/dist/streams/index.d.cts.map +1 -1
- package/dist/streams/index.d.ts +3 -3
- package/dist/streams/index.d.ts.map +1 -1
- package/dist/streams/index.js +2 -10
- package/dist/streams/progress.cjs +60 -46
- package/dist/streams/progress.cjs.map +1 -1
- package/dist/streams/progress.js +60 -46
- package/dist/streams/progress.js.map +1 -1
- package/dist/streams/source.cjs +316 -146
- package/dist/streams/source.cjs.map +1 -1
- package/dist/streams/source.d.cts +56 -18
- package/dist/streams/source.d.cts.map +1 -1
- package/dist/streams/source.d.ts +56 -18
- package/dist/streams/source.d.ts.map +1 -1
- package/dist/streams/source.js +312 -149
- package/dist/streams/source.js.map +1 -1
- package/dist/sync/actions/index.cjs +236 -184
- package/dist/sync/actions/index.cjs.map +1 -1
- package/dist/sync/actions/index.d.cts +29 -21
- package/dist/sync/actions/index.d.cts.map +1 -1
- package/dist/sync/actions/index.d.ts +29 -21
- package/dist/sync/actions/index.d.ts.map +1 -1
- package/dist/sync/actions/index.js +236 -190
- package/dist/sync/actions/index.js.map +1 -1
- package/dist/sync/b2-sha1-reader.cjs +148 -0
- package/dist/sync/b2-sha1-reader.cjs.map +1 -0
- package/dist/sync/b2-sha1-reader.d.cts +58 -0
- package/dist/sync/b2-sha1-reader.d.cts.map +1 -0
- package/dist/sync/b2-sha1-reader.d.ts +58 -0
- package/dist/sync/b2-sha1-reader.d.ts.map +1 -0
- package/dist/sync/b2-sha1-reader.js +145 -0
- package/dist/sync/b2-sha1-reader.js.map +1 -0
- package/dist/sync/download-staging.cjs +265 -0
- package/dist/sync/download-staging.cjs.map +1 -0
- package/dist/sync/download-staging.d.cts +54 -0
- package/dist/sync/download-staging.d.cts.map +1 -0
- package/dist/sync/download-staging.d.ts +54 -0
- package/dist/sync/download-staging.d.ts.map +1 -0
- package/dist/sync/download-staging.js +259 -0
- package/dist/sync/download-staging.js.map +1 -0
- package/dist/sync/filesystem-errors.cjs +32 -0
- package/dist/sync/filesystem-errors.cjs.map +1 -0
- package/dist/sync/filesystem-errors.d.cts +8 -0
- package/dist/sync/filesystem-errors.d.cts.map +1 -0
- package/dist/sync/filesystem-errors.d.ts +8 -0
- package/dist/sync/filesystem-errors.d.ts.map +1 -0
- package/dist/sync/filesystem-errors.js +32 -0
- package/dist/sync/filesystem-errors.js.map +1 -0
- package/dist/sync/filters.cjs +217 -0
- package/dist/sync/filters.cjs.map +1 -0
- package/dist/sync/filters.d.cts +51 -0
- package/dist/sync/filters.d.cts.map +1 -0
- package/dist/sync/filters.d.ts +51 -0
- package/dist/sync/filters.d.ts.map +1 -0
- package/dist/sync/filters.js +213 -0
- package/dist/sync/filters.js.map +1 -0
- package/dist/sync/index.cjs +39 -22
- package/dist/sync/index.d.cts +14 -9
- package/dist/sync/index.d.cts.map +1 -1
- package/dist/sync/index.d.ts +14 -9
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +9 -20
- package/dist/sync/local-file-identity.cjs +61 -0
- package/dist/sync/local-file-identity.cjs.map +1 -0
- package/dist/sync/local-file-identity.d.cts +37 -0
- package/dist/sync/local-file-identity.d.cts.map +1 -0
- package/dist/sync/local-file-identity.d.ts +37 -0
- package/dist/sync/local-file-identity.d.ts.map +1 -0
- package/dist/sync/local-file-identity.js +60 -0
- package/dist/sync/local-file-identity.js.map +1 -0
- package/dist/sync/local-file-io.cjs +364 -0
- package/dist/sync/local-file-io.cjs.map +1 -0
- package/dist/sync/local-file-io.d.cts +75 -0
- package/dist/sync/local-file-io.d.cts.map +1 -0
- package/dist/sync/local-file-io.d.ts +75 -0
- package/dist/sync/local-file-io.d.ts.map +1 -0
- package/dist/sync/local-file-io.js +360 -0
- package/dist/sync/local-file-io.js.map +1 -0
- package/dist/sync/local-filesystem-root.cjs +27 -0
- package/dist/sync/local-filesystem-root.cjs.map +1 -0
- package/dist/sync/local-filesystem-root.d.cts +18 -0
- package/dist/sync/local-filesystem-root.d.cts.map +1 -0
- package/dist/sync/local-filesystem-root.d.ts +18 -0
- package/dist/sync/local-filesystem-root.d.ts.map +1 -0
- package/dist/sync/local-filesystem-root.js +26 -0
- package/dist/sync/local-filesystem-root.js.map +1 -0
- package/dist/sync/local-sha1.cjs +119 -0
- package/dist/sync/local-sha1.cjs.map +1 -0
- package/dist/sync/local-sha1.d.cts +39 -0
- package/dist/sync/local-sha1.d.cts.map +1 -0
- package/dist/sync/local-sha1.d.ts +39 -0
- package/dist/sync/local-sha1.d.ts.map +1 -0
- package/dist/sync/local-sha1.js +117 -0
- package/dist/sync/local-sha1.js.map +1 -0
- package/dist/sync/pairing.cjs +118 -29
- package/dist/sync/pairing.cjs.map +1 -1
- package/dist/sync/pairing.d.cts +7 -2
- package/dist/sync/pairing.d.cts.map +1 -1
- package/dist/sync/pairing.d.ts +7 -2
- package/dist/sync/pairing.d.ts.map +1 -1
- package/dist/sync/pairing.js +120 -31
- package/dist/sync/pairing.js.map +1 -1
- package/dist/sync/path-order.cjs +30 -0
- package/dist/sync/path-order.cjs.map +1 -0
- package/dist/sync/path-order.d.cts +28 -0
- package/dist/sync/path-order.d.cts.map +1 -0
- package/dist/sync/path-order.d.ts +28 -0
- package/dist/sync/path-order.d.ts.map +1 -0
- package/dist/sync/path-order.js +29 -0
- package/dist/sync/path-order.js.map +1 -0
- package/dist/sync/path-safety.cjs +111 -0
- package/dist/sync/path-safety.cjs.map +1 -0
- package/dist/sync/path-safety.d.cts +78 -0
- package/dist/sync/path-safety.d.cts.map +1 -0
- package/dist/sync/path-safety.d.ts +78 -0
- package/dist/sync/path-safety.d.ts.map +1 -0
- package/dist/sync/path-safety.js +105 -0
- package/dist/sync/path-safety.js.map +1 -0
- package/dist/sync/paths.d.cts +19 -0
- package/dist/sync/paths.d.cts.map +1 -0
- package/dist/sync/paths.d.ts +19 -0
- package/dist/sync/paths.d.ts.map +1 -0
- package/dist/sync/policies/compare.cjs +389 -11
- package/dist/sync/policies/compare.cjs.map +1 -1
- package/dist/sync/policies/compare.d.cts +100 -2
- package/dist/sync/policies/compare.d.cts.map +1 -1
- package/dist/sync/policies/compare.d.ts +100 -2
- package/dist/sync/policies/compare.d.ts.map +1 -1
- package/dist/sync/policies/compare.js +387 -13
- package/dist/sync/policies/compare.js.map +1 -1
- package/dist/sync/policies/index.cjs +76 -65
- package/dist/sync/policies/index.cjs.map +1 -1
- package/dist/sync/policies/index.d.cts +35 -6
- package/dist/sync/policies/index.d.cts.map +1 -1
- package/dist/sync/policies/index.d.ts +35 -6
- package/dist/sync/policies/index.d.ts.map +1 -1
- package/dist/sync/policies/index.js +76 -65
- package/dist/sync/policies/index.js.map +1 -1
- package/dist/sync/prefix.cjs +96 -0
- package/dist/sync/prefix.cjs.map +1 -0
- package/dist/sync/prefix.d.cts +55 -0
- package/dist/sync/prefix.d.cts.map +1 -0
- package/dist/sync/prefix.d.ts +55 -0
- package/dist/sync/prefix.d.ts.map +1 -0
- package/dist/sync/prefix.js +92 -0
- package/dist/sync/prefix.js.map +1 -0
- package/dist/sync/regexp-safety.cjs +192 -0
- package/dist/sync/regexp-safety.cjs.map +1 -0
- package/dist/sync/regexp-safety.d.cts +29 -0
- package/dist/sync/regexp-safety.d.cts.map +1 -0
- package/dist/sync/regexp-safety.d.ts +29 -0
- package/dist/sync/regexp-safety.d.ts.map +1 -0
- package/dist/sync/regexp-safety.js +190 -0
- package/dist/sync/regexp-safety.js.map +1 -0
- package/dist/sync/scan-events.cjs +33 -0
- package/dist/sync/scan-events.cjs.map +1 -0
- package/dist/sync/scan-events.d.cts +17 -0
- package/dist/sync/scan-events.d.cts.map +1 -0
- package/dist/sync/scan-events.d.ts +17 -0
- package/dist/sync/scan-events.d.ts.map +1 -0
- package/dist/sync/scan-events.js +32 -0
- package/dist/sync/scan-events.js.map +1 -0
- package/dist/sync/scan-limit.cjs +33 -0
- package/dist/sync/scan-limit.cjs.map +1 -0
- package/dist/sync/scan-limit.d.cts +21 -0
- package/dist/sync/scan-limit.d.cts.map +1 -0
- package/dist/sync/scan-limit.d.ts +21 -0
- package/dist/sync/scan-limit.d.ts.map +1 -0
- package/dist/sync/scan-limit.js +31 -0
- package/dist/sync/scan-limit.js.map +1 -0
- package/dist/sync/scanners/b2.cjs +239 -55
- package/dist/sync/scanners/b2.cjs.map +1 -1
- package/dist/sync/scanners/b2.d.cts +26 -7
- package/dist/sync/scanners/b2.d.cts.map +1 -1
- package/dist/sync/scanners/b2.d.ts +26 -7
- package/dist/sync/scanners/b2.d.ts.map +1 -1
- package/dist/sync/scanners/b2.js +239 -55
- package/dist/sync/scanners/b2.js.map +1 -1
- package/dist/sync/scanners/local.cjs +215 -56
- package/dist/sync/scanners/local.cjs.map +1 -1
- package/dist/sync/scanners/local.d.cts +22 -7
- package/dist/sync/scanners/local.d.cts.map +1 -1
- package/dist/sync/scanners/local.d.ts +22 -7
- package/dist/sync/scanners/local.d.ts.map +1 -1
- package/dist/sync/scanners/local.js +216 -57
- package/dist/sync/scanners/local.js.map +1 -1
- package/dist/sync/sha1-metadata.cjs +94 -0
- package/dist/sync/sha1-metadata.cjs.map +1 -0
- package/dist/sync/sha1-metadata.d.cts +82 -0
- package/dist/sync/sha1-metadata.d.cts.map +1 -0
- package/dist/sync/sha1-metadata.d.ts +82 -0
- package/dist/sync/sha1-metadata.d.ts.map +1 -0
- package/dist/sync/sha1-metadata.js +89 -0
- package/dist/sync/sha1-metadata.js.map +1 -0
- package/dist/sync/sha1-options.cjs +23 -0
- package/dist/sync/sha1-options.cjs.map +1 -0
- package/dist/sync/sha1-options.d.cts +14 -0
- package/dist/sync/sha1-options.d.cts.map +1 -0
- package/dist/sync/sha1-options.d.ts +14 -0
- package/dist/sync/sha1-options.d.ts.map +1 -0
- package/dist/sync/sha1-options.js +21 -0
- package/dist/sync/sha1-options.js.map +1 -0
- package/dist/sync/synchronizer.cjs +782 -197
- package/dist/sync/synchronizer.cjs.map +1 -1
- package/dist/sync/synchronizer.d.cts +47 -1
- package/dist/sync/synchronizer.d.cts.map +1 -1
- package/dist/sync/synchronizer.d.ts +47 -1
- package/dist/sync/synchronizer.d.ts.map +1 -1
- package/dist/sync/synchronizer.js +779 -173
- package/dist/sync/synchronizer.js.map +1 -1
- package/dist/sync/types.d.cts +208 -16
- package/dist/sync/types.d.cts.map +1 -1
- package/dist/sync/types.d.ts +208 -16
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/types/auth.cjs +76 -56
- package/dist/types/auth.cjs.map +1 -1
- package/dist/types/auth.d.cts +67 -9
- package/dist/types/auth.d.cts.map +1 -1
- package/dist/types/auth.d.ts +67 -9
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/auth.js +77 -57
- package/dist/types/auth.js.map +1 -1
- package/dist/types/bucket.cjs +74 -38
- package/dist/types/bucket.cjs.map +1 -1
- package/dist/types/bucket.js +75 -41
- package/dist/types/bucket.js.map +1 -1
- package/dist/types/encryption.cjs +364 -327
- package/dist/types/encryption.cjs.map +1 -1
- package/dist/types/encryption.d.cts +16 -0
- package/dist/types/encryption.d.cts.map +1 -1
- package/dist/types/encryption.d.ts +16 -0
- package/dist/types/encryption.d.ts.map +1 -1
- package/dist/types/encryption.js +364 -310
- package/dist/types/encryption.js.map +1 -1
- package/dist/types/errors.cjs +47 -0
- package/dist/types/errors.cjs.map +1 -0
- package/dist/types/errors.d.cts +13 -4
- package/dist/types/errors.d.cts.map +1 -1
- package/dist/types/errors.d.ts +13 -4
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +47 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/file.cjs +36 -19
- package/dist/types/file.cjs.map +1 -1
- package/dist/types/file.d.cts +2 -2
- package/dist/types/file.d.cts.map +1 -1
- package/dist/types/file.d.ts +2 -2
- package/dist/types/file.d.ts.map +1 -1
- package/dist/types/file.js +37 -21
- package/dist/types/file.js.map +1 -1
- package/dist/types/ids.cjs +53 -9
- package/dist/types/ids.cjs.map +1 -1
- package/dist/types/ids.js +54 -15
- package/dist/types/ids.js.map +1 -1
- package/dist/types/index.d.cts +12 -11
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +12 -11
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/key.d.cts +44 -8
- package/dist/types/key.d.cts.map +1 -1
- package/dist/types/key.d.ts +44 -8
- package/dist/types/key.d.ts.map +1 -1
- package/dist/types/lock.cjs +33 -13
- package/dist/types/lock.cjs.map +1 -1
- package/dist/types/lock.js +34 -15
- package/dist/types/lock.js.map +1 -1
- package/dist/types/notifications.cjs +44 -22
- package/dist/types/notifications.cjs.map +1 -1
- package/dist/types/notifications.js +45 -23
- package/dist/types/notifications.js.map +1 -1
- package/dist/types/upload.d.cts +39 -5
- package/dist/types/upload.d.cts.map +1 -1
- package/dist/types/upload.d.ts +39 -5
- package/dist/types/upload.d.ts.map +1 -1
- package/dist/upload/abort-scope.cjs +91 -0
- package/dist/upload/abort-scope.cjs.map +1 -0
- package/dist/upload/abort-scope.d.cts +48 -0
- package/dist/upload/abort-scope.d.cts.map +1 -0
- package/dist/upload/abort-scope.d.ts +48 -0
- package/dist/upload/abort-scope.d.ts.map +1 -0
- package/dist/upload/abort-scope.js +88 -0
- package/dist/upload/abort-scope.js.map +1 -0
- package/dist/upload/cancel.cjs +183 -8
- package/dist/upload/cancel.cjs.map +1 -1
- package/dist/upload/cancel.d.cts +110 -2
- package/dist/upload/cancel.d.cts.map +1 -1
- package/dist/upload/cancel.d.ts +110 -2
- package/dist/upload/cancel.d.ts.map +1 -1
- package/dist/upload/cancel.js +178 -9
- package/dist/upload/cancel.js.map +1 -1
- package/dist/upload/concurrency.cjs +79 -52
- package/dist/upload/concurrency.cjs.map +1 -1
- package/dist/upload/concurrency.js +79 -53
- package/dist/upload/concurrency.js.map +1 -1
- package/dist/upload/finish.cjs +59 -0
- package/dist/upload/finish.cjs.map +1 -0
- package/dist/upload/finish.d.cts +26 -0
- package/dist/upload/finish.d.cts.map +1 -0
- package/dist/upload/finish.d.ts +26 -0
- package/dist/upload/finish.d.ts.map +1 -0
- package/dist/upload/finish.js +59 -0
- package/dist/upload/finish.js.map +1 -0
- package/dist/upload/large.cjs +301 -218
- package/dist/upload/large.cjs.map +1 -1
- package/dist/upload/large.d.cts +76 -9
- package/dist/upload/large.d.cts.map +1 -1
- package/dist/upload/large.d.ts +76 -9
- package/dist/upload/large.d.ts.map +1 -1
- package/dist/upload/large.js +301 -218
- package/dist/upload/large.js.map +1 -1
- package/dist/upload/options.cjs +28 -0
- package/dist/upload/options.cjs.map +1 -0
- package/dist/upload/options.d.cts +104 -0
- package/dist/upload/options.d.cts.map +1 -0
- package/dist/upload/options.d.ts +104 -0
- package/dist/upload/options.d.ts.map +1 -0
- package/dist/upload/options.js +27 -0
- package/dist/upload/options.js.map +1 -0
- package/dist/upload/resume.cjs +333 -33
- package/dist/upload/resume.cjs.map +1 -1
- package/dist/upload/resume.d.cts +82 -12
- package/dist/upload/resume.d.cts.map +1 -1
- package/dist/upload/resume.d.ts +82 -12
- package/dist/upload/resume.d.ts.map +1 -1
- package/dist/upload/resume.js +330 -33
- package/dist/upload/resume.js.map +1 -1
- package/dist/upload/retry.cjs +186 -0
- package/dist/upload/retry.cjs.map +1 -0
- package/dist/upload/retry.d.cts +127 -0
- package/dist/upload/retry.d.cts.map +1 -0
- package/dist/upload/retry.d.ts +127 -0
- package/dist/upload/retry.d.ts.map +1 -0
- package/dist/upload/retry.js +182 -0
- package/dist/upload/retry.js.map +1 -0
- package/dist/upload/single.cjs +68 -44
- package/dist/upload/single.cjs.map +1 -1
- package/dist/upload/single.d.cts +2 -1
- package/dist/upload/single.d.cts.map +1 -1
- package/dist/upload/single.d.ts +2 -1
- package/dist/upload/single.d.ts.map +1 -1
- package/dist/upload/single.js +68 -44
- package/dist/upload/single.js.map +1 -1
- package/dist/upload/stream.cjs +317 -193
- package/dist/upload/stream.cjs.map +1 -1
- package/dist/upload/stream.d.cts +3 -1
- package/dist/upload/stream.d.cts.map +1 -1
- package/dist/upload/stream.d.ts +3 -1
- package/dist/upload/stream.d.ts.map +1 -1
- package/dist/upload/stream.js +316 -192
- package/dist/upload/stream.js.map +1 -1
- package/dist/util/best-effort.cjs +42 -8
- package/dist/util/best-effort.cjs.map +1 -1
- package/dist/util/best-effort.d.cts +2 -1
- package/dist/util/best-effort.d.cts.map +1 -1
- package/dist/util/best-effort.d.ts +2 -1
- package/dist/util/best-effort.d.ts.map +1 -1
- package/dist/util/best-effort.js +43 -9
- package/dist/util/best-effort.js.map +1 -1
- package/dist/util/bytes.cjs +23 -0
- package/dist/util/bytes.cjs.map +1 -0
- package/dist/util/bytes.d.cts +15 -0
- package/dist/util/bytes.d.cts.map +1 -0
- package/dist/util/bytes.d.ts +15 -0
- package/dist/util/bytes.d.ts.map +1 -0
- package/dist/util/bytes.js +23 -0
- package/dist/util/bytes.js.map +1 -0
- package/dist/util/crypto.cjs +68 -0
- package/dist/util/crypto.cjs.map +1 -0
- package/dist/util/crypto.d.cts +26 -0
- package/dist/util/crypto.d.cts.map +1 -0
- package/dist/util/crypto.d.ts +26 -0
- package/dist/util/crypto.d.ts.map +1 -0
- package/dist/util/crypto.js +66 -0
- package/dist/util/crypto.js.map +1 -0
- package/dist/util/defaults.cjs +25 -9
- package/dist/util/defaults.cjs.map +1 -1
- package/dist/util/defaults.js +26 -11
- package/dist/util/defaults.js.map +1 -1
- package/dist/util/error-reason.cjs +41 -0
- package/dist/util/error-reason.cjs.map +1 -0
- package/dist/util/error-reason.d.cts +9 -0
- package/dist/util/error-reason.d.cts.map +1 -0
- package/dist/util/error-reason.d.ts +9 -0
- package/dist/util/error-reason.d.ts.map +1 -0
- package/dist/util/error-reason.js +41 -0
- package/dist/util/error-reason.js.map +1 -0
- package/dist/util/http.cjs +23 -0
- package/dist/util/http.cjs.map +1 -0
- package/dist/util/http.d.cts +13 -0
- package/dist/util/http.d.cts.map +1 -0
- package/dist/util/http.d.ts +13 -0
- package/dist/util/http.d.ts.map +1 -0
- package/dist/util/http.js +23 -0
- package/dist/util/http.js.map +1 -0
- package/dist/util/normalize.cjs +66 -7
- package/dist/util/normalize.cjs.map +1 -1
- package/dist/util/normalize.js +67 -10
- package/dist/util/normalize.js.map +1 -1
- package/dist/util/paginator.cjs +63 -14
- package/dist/util/paginator.cjs.map +1 -1
- package/dist/util/paginator.js +64 -16
- package/dist/util/paginator.js.map +1 -1
- package/dist/util/plan-ranges.cjs +47 -22
- package/dist/util/plan-ranges.cjs.map +1 -1
- package/dist/util/plan-ranges.js +48 -24
- package/dist/util/plan-ranges.js.map +1 -1
- package/dist/util/sha1.cjs +27 -0
- package/dist/util/sha1.cjs.map +1 -0
- package/dist/util/sha1.d.cts +17 -0
- package/dist/util/sha1.d.cts.map +1 -0
- package/dist/util/sha1.d.ts +17 -0
- package/dist/util/sha1.d.ts.map +1 -0
- package/dist/util/sha1.js +26 -0
- package/dist/util/sha1.js.map +1 -0
- package/dist/util/text-codec.cjs +29 -5
- package/dist/util/text-codec.cjs.map +1 -1
- package/dist/util/text-codec.js +30 -7
- package/dist/util/text-codec.js.map +1 -1
- package/dist/util/to-error.cjs +18 -4
- package/dist/util/to-error.cjs.map +1 -1
- package/dist/util/to-error.js +19 -5
- package/dist/util/to-error.js.map +1 -1
- package/dist/version.cjs +17 -5
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +3 -3
- package/dist/version.d.ts +3 -3
- package/dist/version.js +19 -6
- package/dist/version.js.map +1 -1
- package/package.json +19 -16
- package/dist/auth/index.cjs.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/notifications/index.cjs.map +0 -1
- package/dist/notifications/index.js.map +0 -1
- package/dist/package.json.cjs +0 -9
- package/dist/package.json.cjs.map +0 -1
- package/dist/package.json.js +0 -9
- package/dist/package.json.js.map +0 -1
- package/dist/streams/index.cjs.map +0 -1
- package/dist/streams/index.js.map +0 -1
- package/dist/sync/index.cjs.map +0 -1
- package/dist/sync/index.js.map +0 -1
package/dist/http/url-guard.js
CHANGED
|
@@ -1,97 +1,159 @@
|
|
|
1
1
|
import { B2SsrfError } from "../errors/index.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
2
|
+
//#region src/http/url-guard.ts
|
|
3
|
+
/**
|
|
4
|
+
* URL allow-list guard. Defends against SSRF / URL-substitution attacks where
|
|
5
|
+
* a compromised or hostile B2 endpoint returns an upload URL pointing at an
|
|
6
|
+
* internal service (e.g. cloud metadata at `169.254.169.254`).
|
|
7
|
+
*
|
|
8
|
+
* The guard is built once per `B2Client` and updated by `B2Client.authorize()`.
|
|
9
|
+
* Before authorization it is permissive (so the very first
|
|
10
|
+
* `b2_authorize_account` request, whose URL the user configured, can succeed).
|
|
11
|
+
* After authorization it is locked to host suffixes derived from the realm's
|
|
12
|
+
* apiUrl/downloadUrl/s3ApiUrl, plus the well-known B2 upload-pod parent
|
|
13
|
+
* domain `backblaze.com`.
|
|
14
|
+
*
|
|
15
|
+
* The guard runs in `FetchTransport` before any outgoing request. It rejects:
|
|
16
|
+
*
|
|
17
|
+
* 1. Literal IPv4/IPv6 addresses (defense in depth, covers attempts to
|
|
18
|
+
* bypass DNS-based checks with raw IPs).
|
|
19
|
+
* 2. Well-known internal hostnames (`localhost`, `metadata`,
|
|
20
|
+
* `metadata.google.internal`, `.internal`, `.local`).
|
|
21
|
+
* 3. Hosts not matching any allowed suffix once the SDK is locked.
|
|
22
|
+
*
|
|
23
|
+
* Users supplying a custom `transport` to `B2Client` bypass the guard. That
|
|
24
|
+
* is their responsibility to document for their threat model.
|
|
25
|
+
*
|
|
26
|
+
* Threat-model note: the guard checks the URL's hostname before the
|
|
27
|
+
* `fetch()` call. It does NOT pin the resolved IP. A DNS rebinding attack
|
|
28
|
+
* could in principle resolve a permitted hostname to an internal IP between
|
|
29
|
+
* the guard's check and `fetch()`'s own resolution. This is theoretical
|
|
30
|
+
* against B2 because the allow-list is locked to a small set of stable
|
|
31
|
+
* Backblaze hostnames (the realm's apiUrl/downloadUrl/s3ApiUrl plus the
|
|
32
|
+
* `backblaze.com` parent), and DNS rebinding requires a hostname under
|
|
33
|
+
* attacker control. Defense in depth — pinning the IP from the first
|
|
34
|
+
* resolution and rejecting subsequent mismatches — would break legitimate
|
|
35
|
+
* CDN failovers and is not justified at this surface area. If your
|
|
36
|
+
* threat model requires it, supply a custom transport that does.
|
|
37
|
+
*/
|
|
38
|
+
/** A URL allow-list that can be reconfigured after construction. */
|
|
39
|
+
var UrlGuard = class {
|
|
40
|
+
allowedSuffixes = [];
|
|
41
|
+
/**
|
|
42
|
+
* Lock the guard to the given host suffixes. A suffix matches a host
|
|
43
|
+
* either exactly or as a `*.suffix` subdomain. For example,
|
|
44
|
+
* `backblazeb2.com` allows `api.backblazeb2.com` and
|
|
45
|
+
* `s3.us-west-004.backblazeb2.com`.
|
|
46
|
+
*
|
|
47
|
+
* Passing an empty array disables the guard (used by the simulator and
|
|
48
|
+
* other test setups). Production code should always lock the guard after
|
|
49
|
+
* a successful `b2_authorize_account`.
|
|
50
|
+
*
|
|
51
|
+
* @param suffixes - Allowed host suffixes.
|
|
52
|
+
*/
|
|
53
|
+
setAllowedSuffixes(suffixes) {
|
|
54
|
+
this.allowedSuffixes = suffixes;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns the current allowed-suffix list (for tests and diagnostics).
|
|
58
|
+
*
|
|
59
|
+
* @returns The currently-configured list of allowed host suffixes.
|
|
60
|
+
*/
|
|
61
|
+
getAllowedSuffixes() {
|
|
62
|
+
return this.allowedSuffixes;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validate `rawUrl` against the allow-list. Throws {@link B2SsrfError} if
|
|
66
|
+
* the URL points at a literal IP, a known-internal hostname, or a host
|
|
67
|
+
* outside the allowed suffixes. Permissive (no-op) when no suffixes have
|
|
68
|
+
* been configured yet.
|
|
69
|
+
*
|
|
70
|
+
* @param rawUrl - The URL the caller is about to fetch.
|
|
71
|
+
*
|
|
72
|
+
* @throws A `B2SsrfError` when the URL is rejected.
|
|
73
|
+
*/
|
|
74
|
+
check(rawUrl) {
|
|
75
|
+
if (this.allowedSuffixes.length === 0) return;
|
|
76
|
+
let parsed;
|
|
77
|
+
try {
|
|
78
|
+
parsed = new URL(rawUrl);
|
|
79
|
+
} catch {
|
|
80
|
+
throw new B2SsrfError(`malformed URL rejected by SSRF guard: ${rawUrl}`, rawUrl);
|
|
81
|
+
}
|
|
82
|
+
const host = parsed.hostname.toLowerCase();
|
|
83
|
+
if (isLiteralIp(host)) throw new B2SsrfError(`literal IP host not allowed by SSRF guard (use a hostname): ${host}`, rawUrl);
|
|
84
|
+
if (isInternalHostname(host)) throw new B2SsrfError(`internal hostname not allowed by SSRF guard: ${host}`, rawUrl);
|
|
85
|
+
if (hostMatchesAnyAllowedSuffix(host, this.allowedSuffixes)) return;
|
|
86
|
+
throw new B2SsrfError(`host outside allowed B2 realm: ${host} (allowed suffixes: ${this.allowedSuffixes.join(", ")})`, rawUrl);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Extract host suffixes to allow from a B2 authorize-account response.
|
|
91
|
+
*
|
|
92
|
+
* Known B2 realm hosts under `backblazeb2.com` are collapsed to that parent.
|
|
93
|
+
* Unknown or custom realm hosts are used as scoped suffixes: the returned
|
|
94
|
+
* hostname and its subdomains are allowed, but sibling hosts and parent
|
|
95
|
+
* domains are not. This avoids accidentally trusting broad public suffixes
|
|
96
|
+
* such as `co.uk`.
|
|
97
|
+
*
|
|
98
|
+
* Always includes `backblaze.com` because upload-pod URLs returned by
|
|
99
|
+
* `b2_get_upload_url` use that parent domain (`pod-NNN-NNNN-NN.backblaze.com`)
|
|
100
|
+
* rather than `backblazeb2.com`.
|
|
101
|
+
*
|
|
102
|
+
* @param storageApi - The `apiInfo.storageApi` portion of the authorize response.
|
|
103
|
+
*
|
|
104
|
+
* @returns Sorted list of unique host suffixes to allow.
|
|
105
|
+
*/
|
|
65
106
|
function deriveAllowedSuffixes(storageApi) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
107
|
+
const suffixes = /* @__PURE__ */ new Set(["backblaze.com"]);
|
|
108
|
+
for (const url of [
|
|
109
|
+
storageApi.apiUrl,
|
|
110
|
+
storageApi.downloadUrl,
|
|
111
|
+
storageApi.s3ApiUrl
|
|
112
|
+
]) try {
|
|
113
|
+
const host = new URL(url).hostname;
|
|
114
|
+
suffixes.add(host === "backblazeb2.com" || host.endsWith(".backblazeb2.com") ? "backblazeb2.com" : host);
|
|
115
|
+
} catch {}
|
|
116
|
+
return Array.from(suffixes).sort();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Checks a hostname against one allowed suffix using the SDK's exact-or-subdomain rule.
|
|
120
|
+
*
|
|
121
|
+
* @param hostname - URL hostname to check.
|
|
122
|
+
* @param suffix - Domain suffix that may match exactly or as a parent domain.
|
|
123
|
+
*
|
|
124
|
+
* @returns Whether the hostname is exactly the suffix or a subdomain of it.
|
|
125
|
+
*/
|
|
126
|
+
function hostMatchesAllowedSuffix(hostname, suffix) {
|
|
127
|
+
const host = hostname.toLowerCase();
|
|
128
|
+
const lowered = suffix.toLowerCase();
|
|
129
|
+
return host === lowered || host.endsWith(`.${lowered}`);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Checks a hostname against an allowed-suffix list.
|
|
133
|
+
*
|
|
134
|
+
* @param hostname - URL hostname to check.
|
|
135
|
+
* @param suffixes - Domain suffixes to test with the SDK's suffix-matching rule.
|
|
136
|
+
*
|
|
137
|
+
* @returns Whether any suffix matches the hostname.
|
|
138
|
+
*/
|
|
139
|
+
function hostMatchesAnyAllowedSuffix(hostname, suffixes) {
|
|
140
|
+
return suffixes.some((suffix) => hostMatchesAllowedSuffix(hostname, suffix));
|
|
78
141
|
}
|
|
79
142
|
function isLiteralIp(host) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
143
|
+
if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host)) return true;
|
|
144
|
+
if (host.includes(":")) return true;
|
|
145
|
+
return false;
|
|
83
146
|
}
|
|
84
147
|
function isInternalHostname(host) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
148
|
+
if (host === "localhost") return true;
|
|
149
|
+
if (host.endsWith(".localhost")) return true;
|
|
150
|
+
if (host === "metadata") return true;
|
|
151
|
+
if (host === "metadata.google.internal") return true;
|
|
152
|
+
if (host.endsWith(".internal")) return true;
|
|
153
|
+
if (host.endsWith(".local")) return true;
|
|
154
|
+
return false;
|
|
92
155
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
//# sourceMappingURL=url-guard.js.map
|
|
156
|
+
//#endregion
|
|
157
|
+
export { UrlGuard, deriveAllowedSuffixes, hostMatchesAllowedSuffix, hostMatchesAnyAllowedSuffix };
|
|
158
|
+
|
|
159
|
+
//# sourceMappingURL=url-guard.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-guard.js","sources":["../../src/http/url-guard.ts"],"sourcesContent":["/**\n * URL allow-list guard. Defends against SSRF / URL-substitution attacks where\n * a compromised or hostile B2 endpoint returns an upload URL pointing at an\n * internal service (e.g. cloud metadata at `169.254.169.254`).\n *\n * The guard is built once per `B2Client` and updated by `B2Client.authorize()`.\n * Before authorization it is permissive (so the very first\n * `b2_authorize_account` request, whose URL the user configured, can succeed).\n * After authorization it is locked to host suffixes derived from the realm's\n * apiUrl/downloadUrl/s3ApiUrl, plus the well-known B2 upload-pod parent\n * domain `backblaze.com`.\n *\n * The guard runs in `FetchTransport` before any outgoing request. It rejects:\n *\n * 1. Literal IPv4/IPv6 addresses (defense in depth, covers attempts to\n * bypass DNS-based checks with raw IPs).\n * 2. Well-known internal hostnames (`localhost`, `metadata`,\n * `metadata.google.internal`, `.internal`, `.local`).\n * 3. Hosts not matching any allowed suffix once the SDK is locked.\n *\n * Users supplying a custom `transport` to `B2Client` bypass the guard. That\n * is their responsibility to document for their threat model.\n *\n * Threat-model note: the guard checks the URL's hostname before the\n * `fetch()` call. It does NOT pin the resolved IP. A DNS rebinding attack\n * could in principle resolve a permitted hostname to an internal IP between\n * the guard's check and `fetch()`'s own resolution. This is theoretical\n * against B2 because the allow-list is locked to a small set of stable\n * Backblaze hostnames (the realm's apiUrl/downloadUrl/s3ApiUrl plus the\n * `backblaze.com` parent), and DNS rebinding requires a hostname under\n * attacker control. Defense in depth — pinning the IP from the first\n * resolution and rejecting subsequent mismatches — would break legitimate\n * CDN failovers and is not justified at this surface area. If your\n * threat model requires it, supply a custom transport that does.\n */\n\nimport { B2SsrfError } from '../errors/index.ts'\n\n/** A URL allow-list that can be reconfigured after construction. */\nexport class UrlGuard {\n private allowedSuffixes: readonly string[] = []\n\n /**\n * Lock the guard to the given host suffixes. A suffix matches a host\n * either exactly or as a `*.suffix` subdomain. For example,\n * `backblazeb2.com` allows `api.backblazeb2.com` and\n * `s3.us-west-004.backblazeb2.com`.\n *\n * Passing an empty array disables the guard (used by the simulator and\n * other test setups). Production code should always lock the guard after\n * a successful `b2_authorize_account`.\n *\n * @param suffixes - Allowed host suffixes.\n */\n setAllowedSuffixes(suffixes: readonly string[]): void {\n this.allowedSuffixes = suffixes\n }\n\n /**\n * Returns the current allowed-suffix list (for tests and diagnostics).\n *\n * @returns The currently-configured list of allowed host suffixes.\n */\n getAllowedSuffixes(): readonly string[] {\n return this.allowedSuffixes\n }\n\n /**\n * Validate `rawUrl` against the allow-list. Throws {@link B2SsrfError} if\n * the URL points at a literal IP, a known-internal hostname, or a host\n * outside the allowed suffixes. Permissive (no-op) when no suffixes have\n * been configured yet.\n *\n * @param rawUrl - The URL the caller is about to fetch.\n *\n * @throws A `B2SsrfError` when the URL is rejected.\n */\n check(rawUrl: string): void {\n if (this.allowedSuffixes.length === 0) return\n\n let parsed: URL\n try {\n parsed = new URL(rawUrl)\n } catch {\n throw new B2SsrfError(`malformed URL rejected by SSRF guard: ${rawUrl}`, rawUrl)\n }\n\n const host = parsed.hostname.toLowerCase()\n\n if (isLiteralIp(host)) {\n throw new B2SsrfError(\n `literal IP host not allowed by SSRF guard (use a hostname): ${host}`,\n rawUrl,\n )\n }\n\n if (isInternalHostname(host)) {\n throw new B2SsrfError(`internal hostname not allowed by SSRF guard: ${host}`, rawUrl)\n }\n\n
|
|
1
|
+
{"version":3,"file":"url-guard.js","names":[],"sources":["../../src/http/url-guard.ts"],"sourcesContent":["/**\n * URL allow-list guard. Defends against SSRF / URL-substitution attacks where\n * a compromised or hostile B2 endpoint returns an upload URL pointing at an\n * internal service (e.g. cloud metadata at `169.254.169.254`).\n *\n * The guard is built once per `B2Client` and updated by `B2Client.authorize()`.\n * Before authorization it is permissive (so the very first\n * `b2_authorize_account` request, whose URL the user configured, can succeed).\n * After authorization it is locked to host suffixes derived from the realm's\n * apiUrl/downloadUrl/s3ApiUrl, plus the well-known B2 upload-pod parent\n * domain `backblaze.com`.\n *\n * The guard runs in `FetchTransport` before any outgoing request. It rejects:\n *\n * 1. Literal IPv4/IPv6 addresses (defense in depth, covers attempts to\n * bypass DNS-based checks with raw IPs).\n * 2. Well-known internal hostnames (`localhost`, `metadata`,\n * `metadata.google.internal`, `.internal`, `.local`).\n * 3. Hosts not matching any allowed suffix once the SDK is locked.\n *\n * Users supplying a custom `transport` to `B2Client` bypass the guard. That\n * is their responsibility to document for their threat model.\n *\n * Threat-model note: the guard checks the URL's hostname before the\n * `fetch()` call. It does NOT pin the resolved IP. A DNS rebinding attack\n * could in principle resolve a permitted hostname to an internal IP between\n * the guard's check and `fetch()`'s own resolution. This is theoretical\n * against B2 because the allow-list is locked to a small set of stable\n * Backblaze hostnames (the realm's apiUrl/downloadUrl/s3ApiUrl plus the\n * `backblaze.com` parent), and DNS rebinding requires a hostname under\n * attacker control. Defense in depth — pinning the IP from the first\n * resolution and rejecting subsequent mismatches — would break legitimate\n * CDN failovers and is not justified at this surface area. If your\n * threat model requires it, supply a custom transport that does.\n */\n\nimport { B2SsrfError } from '../errors/index.ts'\n\n/** A URL allow-list that can be reconfigured after construction. */\nexport class UrlGuard {\n private allowedSuffixes: readonly string[] = []\n\n /**\n * Lock the guard to the given host suffixes. A suffix matches a host\n * either exactly or as a `*.suffix` subdomain. For example,\n * `backblazeb2.com` allows `api.backblazeb2.com` and\n * `s3.us-west-004.backblazeb2.com`.\n *\n * Passing an empty array disables the guard (used by the simulator and\n * other test setups). Production code should always lock the guard after\n * a successful `b2_authorize_account`.\n *\n * @param suffixes - Allowed host suffixes.\n */\n setAllowedSuffixes(suffixes: readonly string[]): void {\n this.allowedSuffixes = suffixes\n }\n\n /**\n * Returns the current allowed-suffix list (for tests and diagnostics).\n *\n * @returns The currently-configured list of allowed host suffixes.\n */\n getAllowedSuffixes(): readonly string[] {\n return this.allowedSuffixes\n }\n\n /**\n * Validate `rawUrl` against the allow-list. Throws {@link B2SsrfError} if\n * the URL points at a literal IP, a known-internal hostname, or a host\n * outside the allowed suffixes. Permissive (no-op) when no suffixes have\n * been configured yet.\n *\n * @param rawUrl - The URL the caller is about to fetch.\n *\n * @throws A `B2SsrfError` when the URL is rejected.\n */\n check(rawUrl: string): void {\n if (this.allowedSuffixes.length === 0) return\n\n let parsed: URL\n try {\n parsed = new URL(rawUrl)\n } catch {\n throw new B2SsrfError(`malformed URL rejected by SSRF guard: ${rawUrl}`, rawUrl)\n }\n\n const host = parsed.hostname.toLowerCase()\n\n if (isLiteralIp(host)) {\n throw new B2SsrfError(\n `literal IP host not allowed by SSRF guard (use a hostname): ${host}`,\n rawUrl,\n )\n }\n\n if (isInternalHostname(host)) {\n throw new B2SsrfError(`internal hostname not allowed by SSRF guard: ${host}`, rawUrl)\n }\n\n if (hostMatchesAnyAllowedSuffix(host, this.allowedSuffixes)) return\n\n throw new B2SsrfError(\n `host outside allowed B2 realm: ${host} (allowed suffixes: ${this.allowedSuffixes.join(', ')})`,\n rawUrl,\n )\n }\n}\n\n/**\n * Extract host suffixes to allow from a B2 authorize-account response.\n *\n * Known B2 realm hosts under `backblazeb2.com` are collapsed to that parent.\n * Unknown or custom realm hosts are used as scoped suffixes: the returned\n * hostname and its subdomains are allowed, but sibling hosts and parent\n * domains are not. This avoids accidentally trusting broad public suffixes\n * such as `co.uk`.\n *\n * Always includes `backblaze.com` because upload-pod URLs returned by\n * `b2_get_upload_url` use that parent domain (`pod-NNN-NNNN-NN.backblaze.com`)\n * rather than `backblazeb2.com`.\n *\n * @param storageApi - The `apiInfo.storageApi` portion of the authorize response.\n *\n * @returns Sorted list of unique host suffixes to allow.\n */\nexport function deriveAllowedSuffixes(storageApi: {\n apiUrl: string\n downloadUrl: string\n s3ApiUrl: string\n}): readonly string[] {\n const suffixes = new Set<string>(['backblaze.com'])\n for (const url of [storageApi.apiUrl, storageApi.downloadUrl, storageApi.s3ApiUrl]) {\n try {\n const host = new URL(url).hostname\n suffixes.add(\n host === 'backblazeb2.com' || host.endsWith('.backblazeb2.com') ? 'backblazeb2.com' : host,\n )\n } catch {\n // Skip malformed URLs. The auth response is from B2 itself; malformed\n // entries would already have caused other failures upstream.\n }\n }\n return Array.from(suffixes).sort()\n}\n\n/**\n * Checks a hostname against one allowed suffix using the SDK's exact-or-subdomain rule.\n *\n * @param hostname - URL hostname to check.\n * @param suffix - Domain suffix that may match exactly or as a parent domain.\n *\n * @returns Whether the hostname is exactly the suffix or a subdomain of it.\n */\nexport function hostMatchesAllowedSuffix(hostname: string, suffix: string): boolean {\n const host = hostname.toLowerCase()\n const lowered = suffix.toLowerCase()\n return host === lowered || host.endsWith(`.${lowered}`)\n}\n\n/**\n * Checks a hostname against an allowed-suffix list.\n *\n * @param hostname - URL hostname to check.\n * @param suffixes - Domain suffixes to test with the SDK's suffix-matching rule.\n *\n * @returns Whether any suffix matches the hostname.\n */\nexport function hostMatchesAnyAllowedSuffix(\n hostname: string,\n suffixes: readonly string[],\n): boolean {\n return suffixes.some((suffix) => hostMatchesAllowedSuffix(hostname, suffix))\n}\n\nfunction isLiteralIp(host: string): boolean {\n // IPv4 dotted quad: e.g. 169.254.169.254\n if (/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/.test(host)) return true\n // IPv6: URL.hostname strips the brackets but keeps colons. Any colon in a\n // hostname is an IPv6 literal.\n if (host.includes(':')) return true\n return false\n}\n\nfunction isInternalHostname(host: string): boolean {\n if (host === 'localhost') return true\n if (host.endsWith('.localhost')) return true\n if (host === 'metadata') return true\n if (host === 'metadata.google.internal') return true\n if (host.endsWith('.internal')) return true\n if (host.endsWith('.local')) return true\n return false\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,IAAa,WAAb,MAAsB;CACpB,kBAA6C,CAAC;;;;;;;;;;;;;CAc9C,mBAAmB,UAAmC;EACpD,KAAK,kBAAkB;CACzB;;;;;;CAOA,qBAAwC;EACtC,OAAO,KAAK;CACd;;;;;;;;;;;CAYA,MAAM,QAAsB;EAC1B,IAAI,KAAK,gBAAgB,WAAW,GAAG;EAEvC,IAAI;EACJ,IAAI;GACF,SAAS,IAAI,IAAI,MAAM;EACzB,QAAQ;GACN,MAAM,IAAI,YAAY,yCAAyC,UAAU,MAAM;EACjF;EAEA,MAAM,OAAO,OAAO,SAAS,YAAY;EAEzC,IAAI,YAAY,IAAI,GAClB,MAAM,IAAI,YACR,+DAA+D,QAC/D,MACF;EAGF,IAAI,mBAAmB,IAAI,GACzB,MAAM,IAAI,YAAY,gDAAgD,QAAQ,MAAM;EAGtF,IAAI,4BAA4B,MAAM,KAAK,eAAe,GAAG;EAE7D,MAAM,IAAI,YACR,kCAAkC,KAAK,sBAAsB,KAAK,gBAAgB,KAAK,IAAI,EAAE,IAC7F,MACF;CACF;AACF;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,sBAAsB,YAIhB;CACpB,MAAM,2BAAW,IAAI,IAAY,CAAC,eAAe,CAAC;CAClD,KAAK,MAAM,OAAO;EAAC,WAAW;EAAQ,WAAW;EAAa,WAAW;CAAQ,GAC/E,IAAI;EACF,MAAM,OAAO,IAAI,IAAI,GAAG,CAAC,CAAC;EAC1B,SAAS,IACP,SAAS,qBAAqB,KAAK,SAAS,kBAAkB,IAAI,oBAAoB,IACxF;CACF,QAAQ,CAGR;CAEF,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,KAAK;AACnC;;;;;;;;;AAUA,SAAgB,yBAAyB,UAAkB,QAAyB;CAClF,MAAM,OAAO,SAAS,YAAY;CAClC,MAAM,UAAU,OAAO,YAAY;CACnC,OAAO,SAAS,WAAW,KAAK,SAAS,IAAI,SAAS;AACxD;;;;;;;;;AAUA,SAAgB,4BACd,UACA,UACS;CACT,OAAO,SAAS,MAAM,WAAW,yBAAyB,UAAU,MAAM,CAAC;AAC7E;AAEA,SAAS,YAAY,MAAuB;CAE1C,IAAI,uCAAuC,KAAK,IAAI,GAAG,OAAO;CAG9D,IAAI,KAAK,SAAS,GAAG,GAAG,OAAO;CAC/B,OAAO;AACT;AAEA,SAAS,mBAAmB,MAAuB;CACjD,IAAI,SAAS,aAAa,OAAO;CACjC,IAAI,KAAK,SAAS,YAAY,GAAG,OAAO;CACxC,IAAI,SAAS,YAAY,OAAO;CAChC,IAAI,SAAS,4BAA4B,OAAO;CAChD,IAAI,KAAK,SAAS,WAAW,GAAG,OAAO;CACvC,IAAI,KAAK,SAAS,QAAQ,GAAG,OAAO;CACpC,OAAO;AACT"}
|
package/dist/http/user-agent.cjs
CHANGED
|
@@ -1,51 +1,91 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
const require_version = require("../version.cjs");
|
|
2
|
+
//#region src/http/user-agent.ts
|
|
3
|
+
/**
|
|
4
|
+
* Stable identifier Backblaze can grep server logs for to find every request
|
|
5
|
+
* issued by this SDK regardless of how the User-Agent comment evolves.
|
|
6
|
+
* Treat as part of the public contract: do NOT rename without coordinating.
|
|
7
|
+
*/
|
|
8
|
+
var SDK_PRODUCT = "b2-sdk-typescript";
|
|
9
|
+
/**
|
|
10
|
+
* The npm package name. Embedded in the User-Agent comment alongside
|
|
11
|
+
* {@link SDK_PRODUCT} so log queries that grep on either token work.
|
|
12
|
+
*/
|
|
13
|
+
var SDK_PACKAGE = "@backblaze-labs/b2-sdk";
|
|
14
|
+
/**
|
|
15
|
+
* Best-effort detection of the JS runtime and host OS. Used to populate the
|
|
16
|
+
* User-Agent comment so server-side logs can spot Bun/Deno adoption and
|
|
17
|
+
* triage OS-specific issues without asking for a repro environment.
|
|
18
|
+
*
|
|
19
|
+
* @returns The detected runtime, OS, and architecture tokens.
|
|
20
|
+
*/
|
|
6
21
|
function detectPlatform() {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
22
|
+
const g = globalThis;
|
|
23
|
+
if (typeof g["Deno"] !== "undefined") {
|
|
24
|
+
const deno = g["Deno"];
|
|
25
|
+
return {
|
|
26
|
+
runtime: deno.version?.deno ? `deno/${deno.version.deno}` : "deno",
|
|
27
|
+
os: deno.build?.os,
|
|
28
|
+
arch: deno.build?.arch
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (typeof g["Bun"] !== "undefined") {
|
|
32
|
+
const bun = g["Bun"];
|
|
33
|
+
const proc = g["process"];
|
|
34
|
+
return {
|
|
35
|
+
runtime: bun.version ? `bun/${bun.version}` : "bun",
|
|
36
|
+
os: proc?.platform,
|
|
37
|
+
arch: proc?.arch
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (typeof g["process"] !== "undefined") {
|
|
41
|
+
const proc = g["process"];
|
|
42
|
+
if (proc.versions?.node) return {
|
|
43
|
+
runtime: `node/${proc.versions.node}`,
|
|
44
|
+
os: proc.platform,
|
|
45
|
+
arch: proc.arch
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (typeof g["navigator"] !== "undefined") return {
|
|
49
|
+
runtime: "browser",
|
|
50
|
+
os: void 0,
|
|
51
|
+
arch: void 0
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
runtime: "unknown",
|
|
55
|
+
os: void 0,
|
|
56
|
+
arch: void 0
|
|
57
|
+
};
|
|
39
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Build the User-Agent header value the SDK sends on every B2 request.
|
|
61
|
+
*
|
|
62
|
+
* The product token, npm package name, language label, runtime, OS, and
|
|
63
|
+
* architecture are emitted in that order, separated by semicolons inside a
|
|
64
|
+
* single parenthesised comment block. OS and architecture are omitted on
|
|
65
|
+
* runtimes that don't expose them (notably browsers). A custom prefix passed
|
|
66
|
+
* via `B2ClientOptions.userAgent` is prepended verbatim so app-level
|
|
67
|
+
* identifiers come first. See the README "Identifying your traffic" section
|
|
68
|
+
* for examples.
|
|
69
|
+
*
|
|
70
|
+
* @param custom - Optional prefix prepended to the default User-Agent.
|
|
71
|
+
*
|
|
72
|
+
* @returns The formatted User-Agent header string.
|
|
73
|
+
*/
|
|
40
74
|
function getUserAgent(custom) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
75
|
+
const { runtime, os, arch } = detectPlatform();
|
|
76
|
+
const parts = [
|
|
77
|
+
"typescript",
|
|
78
|
+
SDK_PACKAGE,
|
|
79
|
+
runtime
|
|
80
|
+
];
|
|
81
|
+
if (os !== void 0) parts.push(os);
|
|
82
|
+
if (arch !== void 0) parts.push(arch);
|
|
83
|
+
const base = `${SDK_PRODUCT}/${require_version.VERSION} (${parts.join("; ")})`;
|
|
84
|
+
return custom ? `${custom} ${base}` : base;
|
|
47
85
|
}
|
|
86
|
+
//#endregion
|
|
48
87
|
exports.SDK_PACKAGE = SDK_PACKAGE;
|
|
49
88
|
exports.SDK_PRODUCT = SDK_PRODUCT;
|
|
50
89
|
exports.getUserAgent = getUserAgent;
|
|
51
|
-
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=user-agent.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"user-agent.cjs","sources":["../../src/http/user-agent.ts"],"sourcesContent":["import { VERSION } from '../version.ts'\n\n/**\n * Stable identifier Backblaze can grep server logs for to find every request\n * issued by this SDK regardless of how the User-Agent comment evolves.\n * Treat as part of the public contract: do NOT rename without coordinating.\n */\nexport const SDK_PRODUCT = 'b2-sdk-typescript'\n\n/**\n * The npm package name. Embedded in the User-Agent comment alongside\n * {@link SDK_PRODUCT} so log queries that grep on either token work.\n */\nexport const SDK_PACKAGE = '@backblaze-labs/b2-sdk'\n\n/** Detected runtime + OS information for the User-Agent comment. */\ninterface Platform {\n /** Runtime identifier: `node/<x.y.z>`, `bun/<x.y.z>`, `deno/<x.y.z>`, `browser`, or `unknown`. */\n readonly runtime: string\n /** OS identifier (`linux`, `darwin`, `win32`, etc.) when available, or `undefined`. */\n readonly os: string | undefined\n /** CPU architecture (`x64`, `arm64`, etc.) when available, or `undefined`. */\n readonly arch: string | undefined\n}\n\n/**\n * Best-effort detection of the JS runtime and host OS. Used to populate the\n * User-Agent comment so server-side logs can spot Bun/Deno adoption and\n * triage OS-specific issues without asking for a repro environment.\n *\n * @returns The detected runtime, OS, and architecture tokens.\n */\nfunction detectPlatform(): Platform {\n const g = globalThis as Record<string, unknown>\n\n // Deno: Deno.version.deno, Deno.build.{os,arch}.\n if (typeof g['Deno'] !== 'undefined') {\n const deno = g['Deno'] as {\n version?: { deno?: string }\n build?: { os?: string; arch?: string }\n }\n return {\n runtime: deno.version?.deno ? `deno/${deno.version.deno}` : 'deno',\n os: deno.build?.os,\n arch: deno.build?.arch,\n }\n }\n\n // Bun: globalThis.Bun.version, process.platform/arch (Bun is Node-compat).\n if (typeof g['Bun'] !== 'undefined') {\n const bun = g['Bun'] as { version?: string }\n const proc = g['process'] as { platform?: string; arch?: string } | undefined\n return {\n runtime: bun.version ? `bun/${bun.version}` : 'bun',\n os: proc?.platform,\n arch: proc?.arch,\n }\n }\n\n // Node: process.versions.node, process.platform, process.arch.\n if (typeof g['process'] !== 'undefined') {\n const proc = g['process'] as {\n versions?: { node?: string }\n platform?: string\n arch?: string\n }\n if (proc.versions?.node) {\n return {\n runtime: `node/${proc.versions.node}`,\n os: proc.platform,\n arch: proc.arch,\n }\n }\n }\n\n // Browsers (and other navigator-only runtimes like Cloudflare Workers,\n // Vercel Edge, etc.). We deliberately do NOT parse the existing navigator\n // UA — that's noisy, often spoofed, and the request layer already adds the\n // browser's own UA on top.\n if (typeof g['navigator'] !== 'undefined') {\n return { runtime: 'browser', os: undefined, arch: undefined }\n }\n\n return { runtime: 'unknown', os: undefined, arch: undefined }\n}\n\n/**\n * Build the User-Agent header value the SDK sends on every B2 request.\n *\n * The product token, npm package name, language label, runtime, OS, and\n * architecture are emitted in that order, separated by semicolons inside a\n * single parenthesised comment block. OS and architecture are omitted on\n * runtimes that don't expose them (notably browsers). A custom prefix passed\n * via `B2ClientOptions.userAgent` is prepended verbatim so app-level\n * identifiers come first. See the README \"Identifying your traffic\" section\n * for examples.\n *\n * @param custom - Optional prefix prepended to the default User-Agent.\n *\n * @returns The formatted User-Agent header string.\n */\nexport function getUserAgent(custom?: string): string {\n const { runtime, os, arch } = detectPlatform()\n const parts = ['typescript', SDK_PACKAGE, runtime]\n if (os !== undefined) parts.push(os)\n if (arch !== undefined) parts.push(arch)\n const base = `${SDK_PRODUCT}/${VERSION} (${parts.join('; ')})`\n return custom ? `${custom} ${base}` : base\n}\n"],"
|
|
1
|
+
{"version":3,"file":"user-agent.cjs","names":[],"sources":["../../src/http/user-agent.ts"],"sourcesContent":["import { VERSION } from '../version.ts'\n\n/**\n * Stable identifier Backblaze can grep server logs for to find every request\n * issued by this SDK regardless of how the User-Agent comment evolves.\n * Treat as part of the public contract: do NOT rename without coordinating.\n */\nexport const SDK_PRODUCT = 'b2-sdk-typescript'\n\n/**\n * The npm package name. Embedded in the User-Agent comment alongside\n * {@link SDK_PRODUCT} so log queries that grep on either token work.\n */\nexport const SDK_PACKAGE = '@backblaze-labs/b2-sdk'\n\n/** Detected runtime + OS information for the User-Agent comment. */\ninterface Platform {\n /** Runtime identifier: `node/<x.y.z>`, `bun/<x.y.z>`, `deno/<x.y.z>`, `browser`, or `unknown`. */\n readonly runtime: string\n /** OS identifier (`linux`, `darwin`, `win32`, etc.) when available, or `undefined`. */\n readonly os: string | undefined\n /** CPU architecture (`x64`, `arm64`, etc.) when available, or `undefined`. */\n readonly arch: string | undefined\n}\n\n/**\n * Best-effort detection of the JS runtime and host OS. Used to populate the\n * User-Agent comment so server-side logs can spot Bun/Deno adoption and\n * triage OS-specific issues without asking for a repro environment.\n *\n * @returns The detected runtime, OS, and architecture tokens.\n */\nfunction detectPlatform(): Platform {\n const g = globalThis as Record<string, unknown>\n\n // Deno: Deno.version.deno, Deno.build.{os,arch}.\n if (typeof g['Deno'] !== 'undefined') {\n const deno = g['Deno'] as {\n version?: { deno?: string }\n build?: { os?: string; arch?: string }\n }\n return {\n runtime: deno.version?.deno ? `deno/${deno.version.deno}` : 'deno',\n os: deno.build?.os,\n arch: deno.build?.arch,\n }\n }\n\n // Bun: globalThis.Bun.version, process.platform/arch (Bun is Node-compat).\n if (typeof g['Bun'] !== 'undefined') {\n const bun = g['Bun'] as { version?: string }\n const proc = g['process'] as { platform?: string; arch?: string } | undefined\n return {\n runtime: bun.version ? `bun/${bun.version}` : 'bun',\n os: proc?.platform,\n arch: proc?.arch,\n }\n }\n\n // Node: process.versions.node, process.platform, process.arch.\n if (typeof g['process'] !== 'undefined') {\n const proc = g['process'] as {\n versions?: { node?: string }\n platform?: string\n arch?: string\n }\n if (proc.versions?.node) {\n return {\n runtime: `node/${proc.versions.node}`,\n os: proc.platform,\n arch: proc.arch,\n }\n }\n }\n\n // Browsers (and other navigator-only runtimes like Cloudflare Workers,\n // Vercel Edge, etc.). We deliberately do NOT parse the existing navigator\n // UA — that's noisy, often spoofed, and the request layer already adds the\n // browser's own UA on top.\n if (typeof g['navigator'] !== 'undefined') {\n return { runtime: 'browser', os: undefined, arch: undefined }\n }\n\n return { runtime: 'unknown', os: undefined, arch: undefined }\n}\n\n/**\n * Build the User-Agent header value the SDK sends on every B2 request.\n *\n * The product token, npm package name, language label, runtime, OS, and\n * architecture are emitted in that order, separated by semicolons inside a\n * single parenthesised comment block. OS and architecture are omitted on\n * runtimes that don't expose them (notably browsers). A custom prefix passed\n * via `B2ClientOptions.userAgent` is prepended verbatim so app-level\n * identifiers come first. See the README \"Identifying your traffic\" section\n * for examples.\n *\n * @param custom - Optional prefix prepended to the default User-Agent.\n *\n * @returns The formatted User-Agent header string.\n */\nexport function getUserAgent(custom?: string): string {\n const { runtime, os, arch } = detectPlatform()\n const parts = ['typescript', SDK_PACKAGE, runtime]\n if (os !== undefined) parts.push(os)\n if (arch !== undefined) parts.push(arch)\n const base = `${SDK_PRODUCT}/${VERSION} (${parts.join('; ')})`\n return custom ? `${custom} ${base}` : base\n}\n"],"mappings":";;;;;;;AAOA,IAAa,cAAc;;;;;AAM3B,IAAa,cAAc;;;;;;;;AAmB3B,SAAS,iBAA2B;CAClC,MAAM,IAAI;CAGV,IAAI,OAAO,EAAE,YAAY,aAAa;EACpC,MAAM,OAAO,EAAE;EAIf,OAAO;GACL,SAAS,KAAK,SAAS,OAAO,QAAQ,KAAK,QAAQ,SAAS;GAC5D,IAAI,KAAK,OAAO;GAChB,MAAM,KAAK,OAAO;EACpB;CACF;CAGA,IAAI,OAAO,EAAE,WAAW,aAAa;EACnC,MAAM,MAAM,EAAE;EACd,MAAM,OAAO,EAAE;EACf,OAAO;GACL,SAAS,IAAI,UAAU,OAAO,IAAI,YAAY;GAC9C,IAAI,MAAM;GACV,MAAM,MAAM;EACd;CACF;CAGA,IAAI,OAAO,EAAE,eAAe,aAAa;EACvC,MAAM,OAAO,EAAE;EAKf,IAAI,KAAK,UAAU,MACjB,OAAO;GACL,SAAS,QAAQ,KAAK,SAAS;GAC/B,IAAI,KAAK;GACT,MAAM,KAAK;EACb;CAEJ;CAMA,IAAI,OAAO,EAAE,iBAAiB,aAC5B,OAAO;EAAE,SAAS;EAAW,IAAI,KAAA;EAAW,MAAM,KAAA;CAAU;CAG9D,OAAO;EAAE,SAAS;EAAW,IAAI,KAAA;EAAW,MAAM,KAAA;CAAU;AAC9D;;;;;;;;;;;;;;;;AAiBA,SAAgB,aAAa,QAAyB;CACpD,MAAM,EAAE,SAAS,IAAI,SAAS,eAAe;CAC7C,MAAM,QAAQ;EAAC;EAAc;EAAa;CAAO;CACjD,IAAI,OAAO,KAAA,GAAW,MAAM,KAAK,EAAE;CACnC,IAAI,SAAS,KAAA,GAAW,MAAM,KAAK,IAAI;CACvC,MAAM,OAAO,GAAG,YAAY,GAAG,gBAAA,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE;CAC5D,OAAO,SAAS,GAAG,OAAO,GAAG,SAAS;AACxC"}
|
package/dist/http/user-agent.js
CHANGED
|
@@ -1,51 +1,89 @@
|
|
|
1
1
|
import { VERSION } from "../version.js";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
//#region src/http/user-agent.ts
|
|
3
|
+
/**
|
|
4
|
+
* Stable identifier Backblaze can grep server logs for to find every request
|
|
5
|
+
* issued by this SDK regardless of how the User-Agent comment evolves.
|
|
6
|
+
* Treat as part of the public contract: do NOT rename without coordinating.
|
|
7
|
+
*/
|
|
8
|
+
var SDK_PRODUCT = "b2-sdk-typescript";
|
|
9
|
+
/**
|
|
10
|
+
* The npm package name. Embedded in the User-Agent comment alongside
|
|
11
|
+
* {@link SDK_PRODUCT} so log queries that grep on either token work.
|
|
12
|
+
*/
|
|
13
|
+
var SDK_PACKAGE = "@backblaze-labs/b2-sdk";
|
|
14
|
+
/**
|
|
15
|
+
* Best-effort detection of the JS runtime and host OS. Used to populate the
|
|
16
|
+
* User-Agent comment so server-side logs can spot Bun/Deno adoption and
|
|
17
|
+
* triage OS-specific issues without asking for a repro environment.
|
|
18
|
+
*
|
|
19
|
+
* @returns The detected runtime, OS, and architecture tokens.
|
|
20
|
+
*/
|
|
4
21
|
function detectPlatform() {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
22
|
+
const g = globalThis;
|
|
23
|
+
if (typeof g["Deno"] !== "undefined") {
|
|
24
|
+
const deno = g["Deno"];
|
|
25
|
+
return {
|
|
26
|
+
runtime: deno.version?.deno ? `deno/${deno.version.deno}` : "deno",
|
|
27
|
+
os: deno.build?.os,
|
|
28
|
+
arch: deno.build?.arch
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (typeof g["Bun"] !== "undefined") {
|
|
32
|
+
const bun = g["Bun"];
|
|
33
|
+
const proc = g["process"];
|
|
34
|
+
return {
|
|
35
|
+
runtime: bun.version ? `bun/${bun.version}` : "bun",
|
|
36
|
+
os: proc?.platform,
|
|
37
|
+
arch: proc?.arch
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (typeof g["process"] !== "undefined") {
|
|
41
|
+
const proc = g["process"];
|
|
42
|
+
if (proc.versions?.node) return {
|
|
43
|
+
runtime: `node/${proc.versions.node}`,
|
|
44
|
+
os: proc.platform,
|
|
45
|
+
arch: proc.arch
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (typeof g["navigator"] !== "undefined") return {
|
|
49
|
+
runtime: "browser",
|
|
50
|
+
os: void 0,
|
|
51
|
+
arch: void 0
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
runtime: "unknown",
|
|
55
|
+
os: void 0,
|
|
56
|
+
arch: void 0
|
|
57
|
+
};
|
|
37
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Build the User-Agent header value the SDK sends on every B2 request.
|
|
61
|
+
*
|
|
62
|
+
* The product token, npm package name, language label, runtime, OS, and
|
|
63
|
+
* architecture are emitted in that order, separated by semicolons inside a
|
|
64
|
+
* single parenthesised comment block. OS and architecture are omitted on
|
|
65
|
+
* runtimes that don't expose them (notably browsers). A custom prefix passed
|
|
66
|
+
* via `B2ClientOptions.userAgent` is prepended verbatim so app-level
|
|
67
|
+
* identifiers come first. See the README "Identifying your traffic" section
|
|
68
|
+
* for examples.
|
|
69
|
+
*
|
|
70
|
+
* @param custom - Optional prefix prepended to the default User-Agent.
|
|
71
|
+
*
|
|
72
|
+
* @returns The formatted User-Agent header string.
|
|
73
|
+
*/
|
|
38
74
|
function getUserAgent(custom) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
75
|
+
const { runtime, os, arch } = detectPlatform();
|
|
76
|
+
const parts = [
|
|
77
|
+
"typescript",
|
|
78
|
+
SDK_PACKAGE,
|
|
79
|
+
runtime
|
|
80
|
+
];
|
|
81
|
+
if (os !== void 0) parts.push(os);
|
|
82
|
+
if (arch !== void 0) parts.push(arch);
|
|
83
|
+
const base = `${SDK_PRODUCT}/${VERSION} (${parts.join("; ")})`;
|
|
84
|
+
return custom ? `${custom} ${base}` : base;
|
|
45
85
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
};
|
|
51
|
-
//# sourceMappingURL=user-agent.js.map
|
|
86
|
+
//#endregion
|
|
87
|
+
export { SDK_PACKAGE, SDK_PRODUCT, getUserAgent };
|
|
88
|
+
|
|
89
|
+
//# sourceMappingURL=user-agent.js.map
|