@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/upload/resume.cjs
CHANGED
|
@@ -1,34 +1,334 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
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
|
-
|
|
1
|
+
const require_ids = require("../types/ids.cjs");
|
|
2
|
+
const require_errors_index = require("../errors/index.cjs");
|
|
3
|
+
const require_bucket = require("../types/bucket.cjs");
|
|
4
|
+
const require_encryption = require("../types/encryption.cjs");
|
|
5
|
+
//#region src/upload/resume.ts
|
|
6
|
+
/** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */
|
|
7
|
+
var RESUME_SOURCE_SIZE_INFO_KEY = "b2_sdk_resume_source_size";
|
|
8
|
+
/** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */
|
|
9
|
+
var RESUME_PART_SIZE_INFO_KEY = "b2_sdk_resume_part_size";
|
|
10
|
+
var DEFAULT_MAX_RESUME_LIST_PAGES = 10;
|
|
11
|
+
var DEFAULT_MAX_RESUME_PART_CANDIDATES = 25;
|
|
12
|
+
var DEFAULT_MAX_RESUME_PART_PAGES = 10;
|
|
13
|
+
var LIST_PARTS_PAGE_SIZE = 100;
|
|
14
|
+
/**
|
|
15
|
+
* Finds an unfinished large file matching the given bucket and file name.
|
|
16
|
+
* Returns `null` when no compatible candidate exists.
|
|
17
|
+
*
|
|
18
|
+
* With criteria, the newest compatible candidate is selected; incompatible
|
|
19
|
+
* same-name uploads are ignored and optionally reported via
|
|
20
|
+
* `onCandidateRejected`.
|
|
21
|
+
*
|
|
22
|
+
* @param raw - Low-level B2 API client.
|
|
23
|
+
* @param accountInfo - Authorized account state.
|
|
24
|
+
* @param bucketId - Target bucket of the upload.
|
|
25
|
+
* @param fileName - Destination file name of the upload.
|
|
26
|
+
* @param criteria - Upload identity and option checks.
|
|
27
|
+
*
|
|
28
|
+
* @returns A {@link ResumeCandidate} describing the candidate and its uploaded parts, or `null`.
|
|
29
|
+
*/
|
|
30
|
+
async function findResumeCandidate(raw, accountInfo, bucketId, fileName, criteria) {
|
|
31
|
+
const discoverySignal = createResumeDiscoverySignal(criteria);
|
|
32
|
+
try {
|
|
33
|
+
return await findResumeCandidateWithSignal(raw, accountInfo, bucketId, fileName, criteria, discoverySignal.signal);
|
|
34
|
+
} finally {
|
|
35
|
+
discoverySignal.dispose();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function findResumeCandidateWithSignal(raw, accountInfo, bucketId, fileName, criteria, signal) {
|
|
39
|
+
const matches = [];
|
|
40
|
+
const maxListPages = criteria.maxListPages ?? DEFAULT_MAX_RESUME_LIST_PAGES;
|
|
41
|
+
const maxPartCandidates = criteria.maxPartCandidates ?? DEFAULT_MAX_RESUME_PART_CANDIDATES;
|
|
42
|
+
let sequence = 0;
|
|
43
|
+
let pageCount = 0;
|
|
44
|
+
const explicitResumeFileId = criteria.resumeFileId;
|
|
45
|
+
let startFileId = explicitResumeFileId;
|
|
46
|
+
let truncated = false;
|
|
47
|
+
while (pageCount < maxListPages) {
|
|
48
|
+
signal?.throwIfAborted();
|
|
49
|
+
const unfinished = await abortableRequest(raw.listUnfinishedLargeFiles(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
|
|
50
|
+
bucketId,
|
|
51
|
+
maxFileCount: explicitResumeFileId !== void 0 ? 1 : 100,
|
|
52
|
+
namePrefix: fileName,
|
|
53
|
+
...startFileId !== void 0 ? { startFileId } : {}
|
|
54
|
+
}, signal !== void 0 ? { signal } : void 0), signal);
|
|
55
|
+
pageCount++;
|
|
56
|
+
for (const file of unfinished.files) {
|
|
57
|
+
if (explicitResumeFileId !== void 0 ? file.fileId === explicitResumeFileId : file.fileName === fileName) matches.push({
|
|
58
|
+
file,
|
|
59
|
+
sequence
|
|
60
|
+
});
|
|
61
|
+
sequence++;
|
|
62
|
+
}
|
|
63
|
+
if (explicitResumeFileId !== void 0) break;
|
|
64
|
+
if (unfinished.nextFileId === null) break;
|
|
65
|
+
startFileId = unfinished.nextFileId;
|
|
66
|
+
truncated = pageCount >= maxListPages;
|
|
67
|
+
}
|
|
68
|
+
if (truncated) emitCandidateRejected(criteria, {
|
|
69
|
+
requestedFileName: fileName,
|
|
70
|
+
reason: "search-truncated"
|
|
71
|
+
});
|
|
72
|
+
matches.sort(compareNewestFirst);
|
|
73
|
+
let partCandidatesInspected = 0;
|
|
74
|
+
for (const match of matches) {
|
|
75
|
+
signal?.throwIfAborted();
|
|
76
|
+
const rejection = candidateMetadataRejectReason(match.file, fileName, criteria);
|
|
77
|
+
if (rejection !== null) {
|
|
78
|
+
notifyCandidateRejected(criteria, match.file, fileName, rejection);
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (partCandidatesInspected >= maxPartCandidates) {
|
|
82
|
+
notifyCandidateRejected(criteria, match.file, fileName, "candidate-limit");
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
partCandidatesInspected++;
|
|
86
|
+
const fileId = require_ids.largeFileId(match.file.fileId);
|
|
87
|
+
const uploadedPartsResult = await collectResumePartInfo(raw, accountInfo, fileId, {
|
|
88
|
+
maxPages: criteria.maxPartPages ?? DEFAULT_MAX_RESUME_PART_PAGES,
|
|
89
|
+
maxParts: criteria.parts.length,
|
|
90
|
+
...signal !== void 0 ? { signal } : {}
|
|
91
|
+
});
|
|
92
|
+
const uploadedParts = uploadedPartsResult.parts;
|
|
93
|
+
if (uploadedPartsResult.truncated || !uploadedPartsMatchPlan(uploadedParts, criteria.parts)) {
|
|
94
|
+
notifyCandidateRejected(criteria, match.file, fileName, "part-length-mismatch");
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
fileId,
|
|
99
|
+
uploadedPartSha1s: partInfoToSha1s(uploadedParts)
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
async function collectResumePartInfo(raw, accountInfo, fileId, options) {
|
|
105
|
+
const parts = /* @__PURE__ */ new Map();
|
|
106
|
+
const maxPages = options.maxPages ?? Number.POSITIVE_INFINITY;
|
|
107
|
+
const maxParts = options.maxParts ?? Number.POSITIVE_INFINITY;
|
|
108
|
+
let startPartNumber;
|
|
109
|
+
let pageCount = 0;
|
|
110
|
+
while (pageCount < maxPages) {
|
|
111
|
+
options.signal?.throwIfAborted();
|
|
112
|
+
const remainingParts = maxParts === Number.POSITIVE_INFINITY ? void 0 : Math.max(1, Math.min(LIST_PARTS_PAGE_SIZE, maxParts - parts.size + 1));
|
|
113
|
+
const page = await abortableRequest(raw.listParts(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {
|
|
114
|
+
fileId,
|
|
115
|
+
...startPartNumber !== void 0 ? { startPartNumber } : {},
|
|
116
|
+
...remainingParts !== void 0 ? { maxPartCount: remainingParts } : {}
|
|
117
|
+
}, options.signal !== void 0 ? { signal: options.signal } : void 0), options.signal);
|
|
118
|
+
pageCount++;
|
|
119
|
+
for (const part of page.parts) {
|
|
120
|
+
parts.set(part.partNumber, {
|
|
121
|
+
contentSha1: part.contentSha1,
|
|
122
|
+
contentLength: part.contentLength
|
|
123
|
+
});
|
|
124
|
+
if (parts.size > maxParts) return {
|
|
125
|
+
parts,
|
|
126
|
+
truncated: true
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (page.nextPartNumber === null) return {
|
|
130
|
+
parts,
|
|
131
|
+
truncated: false
|
|
132
|
+
};
|
|
133
|
+
assertAdvancingPartCursor(fileId, startPartNumber, page.nextPartNumber);
|
|
134
|
+
startPartNumber = page.nextPartNumber;
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
parts,
|
|
138
|
+
truncated: true
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function compareNewestFirst(a, b) {
|
|
142
|
+
const aTime = a.file.uploadTimestamp ?? Number.NEGATIVE_INFINITY;
|
|
143
|
+
const bTime = b.file.uploadTimestamp ?? Number.NEGATIVE_INFINITY;
|
|
144
|
+
if (aTime !== bTime) return bTime - aTime;
|
|
145
|
+
return b.sequence - a.sequence;
|
|
146
|
+
}
|
|
147
|
+
function candidateMetadataRejectReason(candidate, fileName, criteria) {
|
|
148
|
+
if (candidate.fileName !== fileName) return "file-name-mismatch";
|
|
149
|
+
if (criteria.contentType === "b2/x-auto" && criteria.resumeFileId === void 0 && candidate.contentType !== "b2/x-auto") return "content-type-mismatch";
|
|
150
|
+
if (criteria.contentType !== "b2/x-auto" && candidate.contentType !== criteria.contentType) return "content-type-mismatch";
|
|
151
|
+
const candidateInfo = splitResumeFileInfo(candidate.fileInfo ?? {});
|
|
152
|
+
if (!recordEquals(candidateInfo.fileInfo, criteria.fileInfo)) return "file-info-mismatch";
|
|
153
|
+
if (candidateInfo.sourceSize !== void 0 && candidateInfo.sourceSize !== String(criteria.sourceSize)) return "source-size-mismatch";
|
|
154
|
+
if (candidateInfo.partSize !== void 0 && candidateInfo.partSize !== String(criteria.partSize)) return "part-size-mismatch";
|
|
155
|
+
const encryptionRejectReason = serverSideEncryptionRejectReason(candidate.serverSideEncryption, criteria.serverSideEncryption);
|
|
156
|
+
if (encryptionRejectReason !== null) return encryptionRejectReason;
|
|
157
|
+
if (!fileRetentionMatches(candidate.fileRetention, criteria.fileRetention, criteria.defaultFileRetention, criteria.defaultFileRetentionUnreadable === true, candidate.uploadTimestamp)) return "retention-mismatch";
|
|
158
|
+
if (!legalHoldMatches(candidate.legalHold, criteria.legalHold)) return "legal-hold-mismatch";
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
function notifyCandidateRejected(criteria, candidate, requestedFileName, reason) {
|
|
162
|
+
emitCandidateRejected(criteria, {
|
|
163
|
+
fileId: require_ids.largeFileId(candidate.fileId),
|
|
164
|
+
requestedFileName,
|
|
165
|
+
candidateFileName: candidate.fileName,
|
|
166
|
+
reason
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function emitCandidateRejected(criteria, event) {
|
|
170
|
+
try {
|
|
171
|
+
criteria.onCandidateRejected?.(event);
|
|
172
|
+
} catch {}
|
|
173
|
+
}
|
|
174
|
+
function uploadedPartsMatchPlan(uploadedParts, plans) {
|
|
175
|
+
for (const [partNumber, part] of uploadedParts) {
|
|
176
|
+
const planned = plans[partNumber - 1];
|
|
177
|
+
if (planned === void 0) return false;
|
|
178
|
+
if (planned.partNumber !== partNumber) return false;
|
|
179
|
+
if (planned.length !== part.contentLength) return false;
|
|
180
|
+
}
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
function partInfoToSha1s(parts) {
|
|
184
|
+
const sha1s = /* @__PURE__ */ new Map();
|
|
185
|
+
for (const [partNumber, part] of parts) sha1s.set(partNumber, part.contentSha1);
|
|
186
|
+
return sha1s;
|
|
187
|
+
}
|
|
188
|
+
function recordEquals(a, b) {
|
|
189
|
+
const aKeys = Object.keys(a);
|
|
190
|
+
const bKeys = Object.keys(b);
|
|
191
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
192
|
+
for (const key of aKeys) if (a[key] !== b[key]) return false;
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
function splitResumeFileInfo(fileInfo) {
|
|
196
|
+
const userFileInfo = Object.create(null);
|
|
197
|
+
let sourceSize;
|
|
198
|
+
let partSize;
|
|
199
|
+
for (const [key, value] of Object.entries(fileInfo)) if (key === "b2_sdk_resume_source_size") sourceSize = value;
|
|
200
|
+
else if (key === "b2_sdk_resume_part_size") partSize = value;
|
|
201
|
+
else userFileInfo[key] = value;
|
|
202
|
+
return {
|
|
203
|
+
fileInfo: userFileInfo,
|
|
204
|
+
...sourceSize !== void 0 ? { sourceSize } : {},
|
|
205
|
+
...partSize !== void 0 ? { partSize } : {}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function fileRetentionMatches(candidate, expected, defaultExpected, defaultUnreadable, uploadTimestamp) {
|
|
209
|
+
if (expected === void 0 && defaultUnreadable) return false;
|
|
210
|
+
if (expected === void 0 && defaultExpected !== void 0) {
|
|
211
|
+
if (defaultExpected.mode === require_bucket.BucketRetentionMode.None) {
|
|
212
|
+
if (candidate === void 0) return true;
|
|
213
|
+
if (!candidate.isClientAuthorizedToRead) return false;
|
|
214
|
+
return fileRetentionValueEquals(candidate.value, null);
|
|
215
|
+
}
|
|
216
|
+
if (candidate === void 0 || !candidate.isClientAuthorizedToRead) return false;
|
|
217
|
+
return fileRetentionValueMatchesBucketDefault(candidate.value, defaultExpected, uploadTimestamp);
|
|
218
|
+
}
|
|
219
|
+
if (expected === void 0) {
|
|
220
|
+
if (candidate === void 0) return true;
|
|
221
|
+
if (!candidate.isClientAuthorizedToRead) return false;
|
|
222
|
+
return fileRetentionValueEquals(candidate.value, null);
|
|
223
|
+
}
|
|
224
|
+
if (candidate === void 0 || !candidate.isClientAuthorizedToRead) return false;
|
|
225
|
+
return fileRetentionValueEquals(candidate.value, expected);
|
|
226
|
+
}
|
|
227
|
+
function fileRetentionValueMatchesBucketDefault(candidate, expected, uploadTimestamp) {
|
|
228
|
+
if (expected.period === null) return false;
|
|
229
|
+
if (candidate?.mode !== expected.mode || candidate.retainUntilTimestamp === null) return false;
|
|
230
|
+
if (uploadTimestamp === void 0) return false;
|
|
231
|
+
return candidate.retainUntilTimestamp === uploadTimestamp + retentionPeriodMillis(expected.period);
|
|
232
|
+
}
|
|
233
|
+
function retentionPeriodMillis(period) {
|
|
234
|
+
if (period === null) return 0;
|
|
235
|
+
return (period.unit === "days" ? period.duration : period.duration * 365) * 24 * 60 * 60 * 1e3;
|
|
236
|
+
}
|
|
237
|
+
function fileRetentionValueEquals(a, b) {
|
|
238
|
+
return (a?.mode ?? null) === (b?.mode ?? null) && (a?.retainUntilTimestamp ?? null) === (b?.retainUntilTimestamp ?? null);
|
|
239
|
+
}
|
|
240
|
+
function legalHoldMatches(candidate, expected) {
|
|
241
|
+
if (expected === void 0) {
|
|
242
|
+
if (candidate === void 0) return true;
|
|
243
|
+
if (!candidate.isClientAuthorizedToRead) return false;
|
|
244
|
+
return candidate.value === null || candidate.value === "off";
|
|
245
|
+
}
|
|
246
|
+
if (candidate === void 0 || !candidate.isClientAuthorizedToRead) return false;
|
|
247
|
+
return candidate.value === expected;
|
|
248
|
+
}
|
|
249
|
+
function createResumeDiscoverySignal(criteria) {
|
|
250
|
+
if (criteria.signal !== void 0) return {
|
|
251
|
+
signal: criteria.signal,
|
|
252
|
+
dispose() {}
|
|
253
|
+
};
|
|
254
|
+
if (criteria.discoveryTimeoutMs === void 0) return { dispose() {} };
|
|
255
|
+
const timeoutMs = criteria.discoveryTimeoutMs;
|
|
256
|
+
if (timeoutMs === Number.POSITIVE_INFINITY) return { dispose() {} };
|
|
257
|
+
const controller = new AbortController();
|
|
258
|
+
const timeout = setTimeout(() => {
|
|
259
|
+
controller.abort(resumeDiscoveryTimeoutReason(timeoutMs));
|
|
260
|
+
}, Math.max(0, timeoutMs));
|
|
261
|
+
return {
|
|
262
|
+
signal: controller.signal,
|
|
263
|
+
dispose() {
|
|
264
|
+
clearTimeout(timeout);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
async function abortableRequest(request, signal) {
|
|
269
|
+
if (signal === void 0) return request;
|
|
270
|
+
if (signal.aborted) throw resumeAbortReason(signal);
|
|
271
|
+
let removeAbortListener;
|
|
272
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
273
|
+
const onAbort = () => reject(resumeAbortReason(signal));
|
|
274
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
275
|
+
removeAbortListener = () => signal.removeEventListener("abort", onAbort);
|
|
276
|
+
});
|
|
277
|
+
try {
|
|
278
|
+
return await Promise.race([request, aborted]);
|
|
279
|
+
} finally {
|
|
280
|
+
removeAbortListener?.();
|
|
281
|
+
request.catch(() => {});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
function resumeAbortReason(signal) {
|
|
285
|
+
return signal.reason ?? resumeAbortFallbackReason();
|
|
286
|
+
}
|
|
287
|
+
function resumeAbortFallbackReason() {
|
|
288
|
+
if (typeof DOMException === "function") return new DOMException("Resume discovery aborted", "AbortError");
|
|
289
|
+
const error = /* @__PURE__ */ new Error("Resume discovery aborted");
|
|
290
|
+
error.name = "AbortError";
|
|
291
|
+
return error;
|
|
292
|
+
}
|
|
293
|
+
function resumeDiscoveryTimeoutReason(timeoutMs) {
|
|
294
|
+
if (typeof DOMException === "function") return new DOMException(`Resume discovery timed out after ${timeoutMs} ms`, "TimeoutError");
|
|
295
|
+
const error = /* @__PURE__ */ new Error(`Resume discovery timed out after ${timeoutMs} ms`);
|
|
296
|
+
error.name = "TimeoutError";
|
|
297
|
+
return error;
|
|
298
|
+
}
|
|
299
|
+
function serverSideEncryptionRejectReason(candidate, expected) {
|
|
300
|
+
if (expected?.mode === require_encryption.EncryptionMode.SseC) return "sse-c-unsupported";
|
|
301
|
+
const actual = normalizeEncryption(candidate);
|
|
302
|
+
if (expected === void 0) {
|
|
303
|
+
if (candidate === void 0) return null;
|
|
304
|
+
if (actual === void 0) return "encryption-mismatch";
|
|
305
|
+
if (actual.mode === require_encryption.EncryptionMode.None) return null;
|
|
306
|
+
if (actual.mode === require_encryption.EncryptionMode.SseB2) return null;
|
|
307
|
+
return actual.mode === require_encryption.EncryptionMode.SseC ? "sse-c-unsupported" : "encryption-mismatch";
|
|
308
|
+
}
|
|
309
|
+
const normalizedExpected = normalizeEncryption(expected);
|
|
310
|
+
if (normalizedExpected?.mode === require_encryption.EncryptionMode.None && candidate === void 0) return null;
|
|
311
|
+
if (actual === void 0 || normalizedExpected === void 0) return "encryption-mismatch";
|
|
312
|
+
if (actual.mode !== normalizedExpected.mode) return "encryption-mismatch";
|
|
313
|
+
if (actual.mode === require_encryption.EncryptionMode.None) return null;
|
|
314
|
+
return actual.algorithm === normalizedExpected.algorithm ? null : "encryption-mismatch";
|
|
315
|
+
}
|
|
316
|
+
function normalizeEncryption(encryption) {
|
|
317
|
+
if (encryption === void 0) return void 0;
|
|
318
|
+
if (encryption.mode === null || encryption.mode === require_encryption.EncryptionMode.None) return { mode: require_encryption.EncryptionMode.None };
|
|
319
|
+
if (encryption.mode !== require_encryption.EncryptionMode.SseB2 && encryption.mode !== require_encryption.EncryptionMode.SseC) return;
|
|
320
|
+
return {
|
|
321
|
+
mode: encryption.mode,
|
|
322
|
+
algorithm: encryption.algorithm
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
function assertAdvancingPartCursor(fileId, previous, next) {
|
|
326
|
+
if (!Number.isInteger(next) || next < 1 || previous !== void 0 && next <= previous) throw new Error(`uploadLargeFile: listParts returned a non-advancing nextPartNumber for ${fileId}; aborting resume.`);
|
|
327
|
+
}
|
|
328
|
+
//#endregion
|
|
329
|
+
exports.RESUME_PART_SIZE_INFO_KEY = RESUME_PART_SIZE_INFO_KEY;
|
|
330
|
+
exports.RESUME_SOURCE_SIZE_INFO_KEY = RESUME_SOURCE_SIZE_INFO_KEY;
|
|
331
|
+
exports.ResumeFileIdMismatchError = require_errors_index.ResumeFileIdMismatchError;
|
|
33
332
|
exports.findResumeCandidate = findResumeCandidate;
|
|
34
|
-
|
|
333
|
+
|
|
334
|
+
//# sourceMappingURL=resume.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resume.cjs","sources":["../../src/upload/resume.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport type { BucketId, LargeFileId } from '../types/ids.ts'\nimport { largeFileId as largeFileIdOf } from '../types/ids.ts'\n\n/** Information about an unfinished large file eligible for resume. */\nexport interface ResumeCandidate {\n /** ID of the unfinished large file. */\n readonly fileId: LargeFileId\n /** SHA-1 of each part already uploaded, indexed by 1-based part number. */\n readonly uploadedPartSha1s: ReadonlyMap<number, string>\n}\n\n/**\n * Finds an unfinished large file matching the given bucket and file name.\n * Returns `null` when no matching candidate exists.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state.\n * @param bucketId - Target bucket of the upload.\n * @param fileName - Destination file name of the upload.\n *\n * @returns A {@link ResumeCandidate} describing the candidate and its uploaded parts, or `null`.\n */\nexport async function findResumeCandidate(\n raw: RawClient,\n accountInfo: AccountInfo,\n bucketId: BucketId,\n fileName: string,\n): Promise<ResumeCandidate | null> {\n const unfinished = await raw.listUnfinishedLargeFiles(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n { bucketId },\n )\n\n const match = unfinished.files.find((f) => f.fileName === fileName)\n if (!match) return null\n\n const fileId = largeFileIdOf(match.fileId)\n const uploadedPartSha1s = await collectPartSha1s(raw, accountInfo, fileId)\n\n return { fileId, uploadedPartSha1s }\n}\n\n/**\n * Lists all uploaded parts for a large file, paginating until exhausted.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state.\n * @param fileId - ID of the large file to inspect.\n *\n * @returns A map from 1-based part number to its server-stored SHA-1.\n */\nexport async function collectPartSha1s(\n raw: RawClient,\n accountInfo: AccountInfo,\n fileId: LargeFileId,\n): Promise<Map<number, string>> {\n const sha1s = new Map<number, string>()\n let startPartNumber: number | undefined\n\n while (true) {\n const page = await raw.listParts(accountInfo.getApiUrl(), accountInfo.getAuthToken(), {\n fileId,\n ...(startPartNumber !== undefined ? { startPartNumber } : {}),\n })\n for (const part of page.parts) {\n sha1s.set(part.partNumber, part.contentSha1)\n }\n if (page.nextPartNumber === null) break\n startPartNumber = page.nextPartNumber\n }\n\n return sha1s\n}\n"],"names":["largeFileIdOf"],"mappings":";;;AAwBA,eAAsB,oBACpB,KACA,aACA,UACA,UACiC;AACjC,QAAM,aAAa,MAAM,IAAI;AAAA,IAC3B,YAAY,UAAA;AAAA,IACZ,YAAY,aAAA;AAAA,IACZ,EAAE,SAAA;AAAA,EAAS;AAGb,QAAM,QAAQ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,QAAQ;AAClE,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,SAASA,IAAAA,YAAc,MAAM,MAAM;AACzC,QAAM,oBAAoB,MAAM,iBAAiB,KAAK,aAAa,MAAM;AAEzE,SAAO,EAAE,QAAQ,kBAAA;AACnB;AAWA,eAAsB,iBACpB,KACA,aACA,QAC8B;AAC9B,QAAM,4BAAY,IAAA;AAClB,MAAI;AAEJ,SAAO,MAAM;AACX,UAAM,OAAO,MAAM,IAAI,UAAU,YAAY,UAAA,GAAa,YAAY,gBAAgB;AAAA,MACpF;AAAA,MACA,GAAI,oBAAoB,SAAY,EAAE,oBAAoB,CAAA;AAAA,IAAC,CAC5D;AACD,eAAW,QAAQ,KAAK,OAAO;AAC7B,YAAM,IAAI,KAAK,YAAY,KAAK,WAAW;AAAA,IAC7C;AACA,QAAI,KAAK,mBAAmB,KAAM;AAClC,sBAAkB,KAAK;AAAA,EACzB;AAEA,SAAO;AACT;;;"}
|
|
1
|
+
{"version":3,"file":"resume.cjs","names":[],"sources":["../../src/upload/resume.ts"],"sourcesContent":["import type { AccountInfo } from '../auth/account-info.ts'\nimport { ResumeFileIdMismatchError } from '../errors/index.ts'\nimport type { RawClient } from '../raw/index.ts'\nimport { BucketRetentionMode, type BucketRetentionPolicy } from '../types/bucket.ts'\nimport {\n EncryptionMode,\n type EncryptionSetting,\n type PublicEncryptionSetting,\n} from '../types/encryption.ts'\nimport type { BucketId, LargeFileId } from '../types/ids.ts'\nimport { largeFileId as largeFileIdOf } from '../types/ids.ts'\nimport type { FileRetentionValue, LegalHoldValue } from '../types/lock.ts'\nimport type {\n ReadableFileRetention,\n ReadableLegalHold,\n UnfinishedLargeFile,\n} from '../types/upload.ts'\n\nexport { ResumeFileIdMismatchError }\n\n/** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */\nexport const RESUME_SOURCE_SIZE_INFO_KEY = 'b2_sdk_resume_source_size'\n\n/** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */\nexport const RESUME_PART_SIZE_INFO_KEY = 'b2_sdk_resume_part_size'\n\nconst DEFAULT_MAX_RESUME_LIST_PAGES = 10\nconst DEFAULT_MAX_RESUME_PART_CANDIDATES = 25\nconst DEFAULT_MAX_RESUME_PART_PAGES = 10\n\n/** One planned part from the local upload source. */\nexport interface ResumePartPlan {\n /** 1-based B2 part number. */\n readonly partNumber: number\n /** Expected byte length for this part. */\n readonly length: number\n}\n\n/** Reason an unfinished same-name large file was not reused for resume. */\nexport type ResumeCandidateRejectedReason =\n | 'search-truncated'\n | 'candidate-limit'\n | 'file-name-mismatch'\n | 'content-type-mismatch'\n | 'file-info-mismatch'\n | 'source-size-mismatch'\n | 'part-size-mismatch'\n | 'encryption-mismatch'\n | 'sse-c-unsupported'\n | 'retention-mismatch'\n | 'legal-hold-mismatch'\n | 'part-length-mismatch'\n\n/** Diagnostic event emitted when resume discovery declines a candidate. */\nexport interface ResumeCandidateRejectedEvent {\n /** ID of the unfinished large file, when the event is candidate-specific. */\n readonly fileId?: LargeFileId\n /** Requested destination file name. */\n readonly requestedFileName: string\n /** Actual candidate file name, when the event is candidate-specific. */\n readonly candidateFileName?: string\n /** Machine-readable rejection reason. */\n readonly reason: ResumeCandidateRejectedReason\n}\n\n/** Diagnostic callback for declined resume candidates. */\nexport type ResumeCandidateRejectedListener = (event: ResumeCandidateRejectedEvent) => void\n\n/** Compatibility requirements an unfinished large file must satisfy before reuse. */\nexport interface ResumeCandidateCriteria {\n /** Effective MIME type for the upload, including SDK defaults. */\n readonly contentType: string\n /** Caller-owned file info. Legacy SDK resume keys on candidates are ignored separately. */\n readonly fileInfo: Record<string, string>\n /** Source size in bytes, checked against legacy SDK metadata when a candidate carries it. */\n readonly sourceSize: number\n /** Effective multipart part size, checked against legacy SDK metadata when present. */\n readonly partSize: number\n /** Planned local parts used to verify already-uploaded server part lengths. */\n readonly parts: readonly ResumePartPlan[]\n /** Explicit server-side encryption option, if configured by the caller. */\n readonly serverSideEncryption?: EncryptionSetting\n /** Explicit Object Lock retention option, if configured by the caller. */\n readonly fileRetention?: FileRetentionValue\n /** Effective readable bucket default retention when the caller omits fileRetention. */\n readonly defaultFileRetention?: BucketRetentionPolicy\n /** Whether bucket default retention exists but cannot be read by the caller. */\n readonly defaultFileRetentionUnreadable?: boolean\n /** Explicit legal hold option, if configured by the caller. */\n readonly legalHold?: LegalHoldValue\n /** Explicit unfinished large-file ID to verify before reuse. */\n readonly resumeFileId?: LargeFileId\n /** Abort signal used for B2 list requests and checked between pages. */\n readonly signal?: AbortSignal\n /** Optional diagnostic callback for candidates that are found but not reused. */\n readonly onCandidateRejected?: ResumeCandidateRejectedListener\n /** Maximum `b2_list_unfinished_large_files` pages to inspect. */\n readonly maxListPages?: number\n /** Maximum metadata-compatible candidates whose parts may be listed. */\n readonly maxPartCandidates?: number\n /** Maximum `b2_list_parts` pages to inspect for each metadata-compatible candidate. */\n readonly maxPartPages?: number\n /** Caller-supplied aggregate resume discovery timeout. */\n readonly discoveryTimeoutMs?: number\n}\n\n/** Uploaded part metadata used by the resume planner. */\nexport interface ResumePartInfo {\n /** SHA-1 stored by B2 for this uploaded part. */\n readonly contentSha1: string\n /** Byte length stored by B2 for this uploaded part. */\n readonly contentLength: number\n}\n\nconst LIST_PARTS_PAGE_SIZE = 100\n\n/** Information about an unfinished large file eligible for resume. */\nexport interface ResumeCandidate {\n /** ID of the unfinished large file. */\n readonly fileId: LargeFileId\n /** SHA-1 of each part already uploaded, indexed by 1-based part number. */\n readonly uploadedPartSha1s: ReadonlyMap<number, string>\n}\n\n/**\n * Finds an unfinished large file matching the given bucket and file name.\n * Returns `null` when no compatible candidate exists.\n *\n * With criteria, the newest compatible candidate is selected; incompatible\n * same-name uploads are ignored and optionally reported via\n * `onCandidateRejected`.\n *\n * @param raw - Low-level B2 API client.\n * @param accountInfo - Authorized account state.\n * @param bucketId - Target bucket of the upload.\n * @param fileName - Destination file name of the upload.\n * @param criteria - Upload identity and option checks.\n *\n * @returns A {@link ResumeCandidate} describing the candidate and its uploaded parts, or `null`.\n */\nexport async function findResumeCandidate(\n raw: RawClient,\n accountInfo: AccountInfo,\n bucketId: BucketId,\n fileName: string,\n criteria: ResumeCandidateCriteria,\n): Promise<ResumeCandidate | null> {\n const discoverySignal = createResumeDiscoverySignal(criteria)\n try {\n return await findResumeCandidateWithSignal(\n raw,\n accountInfo,\n bucketId,\n fileName,\n criteria,\n discoverySignal.signal,\n )\n } finally {\n discoverySignal.dispose()\n }\n}\n\nasync function findResumeCandidateWithSignal(\n raw: RawClient,\n accountInfo: AccountInfo,\n bucketId: BucketId,\n fileName: string,\n criteria: ResumeCandidateCriteria,\n signal: AbortSignal | undefined,\n): Promise<ResumeCandidate | null> {\n const matches: Array<{ file: UnfinishedLargeFile; sequence: number }> = []\n const maxListPages = criteria.maxListPages ?? DEFAULT_MAX_RESUME_LIST_PAGES\n const maxPartCandidates = criteria.maxPartCandidates ?? DEFAULT_MAX_RESUME_PART_CANDIDATES\n let sequence = 0\n let pageCount = 0\n const explicitResumeFileId = criteria.resumeFileId\n let startFileId: LargeFileId | undefined = explicitResumeFileId\n let truncated = false\n\n while (pageCount < maxListPages) {\n signal?.throwIfAborted()\n const unfinished = await abortableRequest(\n raw.listUnfinishedLargeFiles(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n {\n bucketId,\n maxFileCount: explicitResumeFileId !== undefined ? 1 : 100,\n namePrefix: fileName,\n ...(startFileId !== undefined ? { startFileId } : {}),\n },\n signal !== undefined ? { signal } : undefined,\n ),\n signal,\n )\n pageCount++\n\n for (const file of unfinished.files) {\n const isMatch =\n explicitResumeFileId !== undefined\n ? file.fileId === explicitResumeFileId\n : file.fileName === fileName\n if (isMatch) {\n matches.push({ file, sequence })\n }\n sequence++\n }\n\n if (explicitResumeFileId !== undefined) break\n if (unfinished.nextFileId === null) break\n startFileId = unfinished.nextFileId\n truncated = pageCount >= maxListPages\n }\n\n if (truncated) {\n emitCandidateRejected(criteria, {\n requestedFileName: fileName,\n reason: 'search-truncated',\n })\n }\n\n matches.sort(compareNewestFirst)\n\n let partCandidatesInspected = 0\n for (const match of matches) {\n signal?.throwIfAborted()\n const rejection = candidateMetadataRejectReason(match.file, fileName, criteria)\n if (rejection !== null) {\n notifyCandidateRejected(criteria, match.file, fileName, rejection)\n continue\n }\n\n if (partCandidatesInspected >= maxPartCandidates) {\n notifyCandidateRejected(criteria, match.file, fileName, 'candidate-limit')\n break\n }\n\n partCandidatesInspected++\n const fileId = largeFileIdOf(match.file.fileId)\n const uploadedPartsResult = await collectResumePartInfo(raw, accountInfo, fileId, {\n maxPages: criteria.maxPartPages ?? DEFAULT_MAX_RESUME_PART_PAGES,\n maxParts: criteria.parts.length,\n ...(signal !== undefined ? { signal } : {}),\n })\n const uploadedParts = uploadedPartsResult.parts\n if (uploadedPartsResult.truncated || !uploadedPartsMatchPlan(uploadedParts, criteria.parts)) {\n notifyCandidateRejected(criteria, match.file, fileName, 'part-length-mismatch')\n continue\n }\n\n return { fileId, uploadedPartSha1s: partInfoToSha1s(uploadedParts) }\n }\n\n return null\n}\n\ninterface CollectResumePartInfoOptions {\n readonly signal?: AbortSignal\n readonly maxPages?: number\n readonly maxParts?: number\n}\n\nasync function collectResumePartInfo(\n raw: RawClient,\n accountInfo: AccountInfo,\n fileId: LargeFileId,\n options: CollectResumePartInfoOptions,\n): Promise<{ readonly parts: Map<number, ResumePartInfo>; readonly truncated: boolean }> {\n const parts = new Map<number, ResumePartInfo>()\n const maxPages = options.maxPages ?? Number.POSITIVE_INFINITY\n const maxParts = options.maxParts ?? Number.POSITIVE_INFINITY\n let startPartNumber: number | undefined\n let pageCount = 0\n\n while (pageCount < maxPages) {\n options.signal?.throwIfAborted()\n // Fetch one part beyond the local plan so a candidate with extra uploaded\n // parts is detected and rejected instead of silently reused.\n const remainingParts =\n maxParts === Number.POSITIVE_INFINITY\n ? undefined\n : Math.max(1, Math.min(LIST_PARTS_PAGE_SIZE, maxParts - parts.size + 1))\n const page = await abortableRequest(\n raw.listParts(\n accountInfo.getApiUrl(),\n accountInfo.getAuthToken(),\n {\n fileId,\n ...(startPartNumber !== undefined ? { startPartNumber } : {}),\n ...(remainingParts !== undefined ? { maxPartCount: remainingParts } : {}),\n },\n options.signal !== undefined ? { signal: options.signal } : undefined,\n ),\n options.signal,\n )\n pageCount++\n for (const part of page.parts) {\n parts.set(part.partNumber, {\n contentSha1: part.contentSha1,\n contentLength: part.contentLength,\n })\n if (parts.size > maxParts) return { parts, truncated: true }\n }\n if (page.nextPartNumber === null) return { parts, truncated: false }\n assertAdvancingPartCursor(fileId, startPartNumber, page.nextPartNumber)\n startPartNumber = page.nextPartNumber\n }\n\n return { parts, truncated: true }\n}\n\nfunction compareNewestFirst(\n a: { file: UnfinishedLargeFile; sequence: number },\n b: { file: UnfinishedLargeFile; sequence: number },\n): number {\n const aTime = a.file.uploadTimestamp ?? Number.NEGATIVE_INFINITY\n const bTime = b.file.uploadTimestamp ?? Number.NEGATIVE_INFINITY\n if (aTime !== bTime) return bTime - aTime\n return b.sequence - a.sequence\n}\n\nfunction candidateMetadataRejectReason(\n candidate: UnfinishedLargeFile,\n fileName: string,\n criteria: ResumeCandidateCriteria,\n): ResumeCandidateRejectedReason | null {\n if (candidate.fileName !== fileName) return 'file-name-mismatch'\n if (\n criteria.contentType === 'b2/x-auto' &&\n criteria.resumeFileId === undefined &&\n candidate.contentType !== 'b2/x-auto'\n ) {\n return 'content-type-mismatch'\n }\n if (criteria.contentType !== 'b2/x-auto' && candidate.contentType !== criteria.contentType) {\n return 'content-type-mismatch'\n }\n\n const candidateInfo = splitResumeFileInfo(candidate.fileInfo ?? {})\n if (!recordEquals(candidateInfo.fileInfo, criteria.fileInfo)) return 'file-info-mismatch'\n if (\n candidateInfo.sourceSize !== undefined &&\n candidateInfo.sourceSize !== String(criteria.sourceSize)\n ) {\n return 'source-size-mismatch'\n }\n if (\n candidateInfo.partSize !== undefined &&\n candidateInfo.partSize !== String(criteria.partSize)\n ) {\n return 'part-size-mismatch'\n }\n\n const encryptionRejectReason = serverSideEncryptionRejectReason(\n candidate.serverSideEncryption,\n criteria.serverSideEncryption,\n )\n if (encryptionRejectReason !== null) return encryptionRejectReason\n if (\n !fileRetentionMatches(\n candidate.fileRetention,\n criteria.fileRetention,\n criteria.defaultFileRetention,\n criteria.defaultFileRetentionUnreadable === true,\n candidate.uploadTimestamp,\n )\n ) {\n return 'retention-mismatch'\n }\n if (!legalHoldMatches(candidate.legalHold, criteria.legalHold)) {\n return 'legal-hold-mismatch'\n }\n\n return null\n}\n\nfunction notifyCandidateRejected(\n criteria: ResumeCandidateCriteria,\n candidate: UnfinishedLargeFile,\n requestedFileName: string,\n reason: ResumeCandidateRejectedReason,\n): void {\n emitCandidateRejected(criteria, {\n fileId: largeFileIdOf(candidate.fileId),\n requestedFileName,\n candidateFileName: candidate.fileName,\n reason,\n })\n}\n\nfunction emitCandidateRejected(\n criteria: ResumeCandidateCriteria,\n event: ResumeCandidateRejectedEvent,\n): void {\n try {\n criteria.onCandidateRejected?.(event)\n } catch {\n // Diagnostic listeners should not make an otherwise valid upload fail.\n }\n}\n\nfunction uploadedPartsMatchPlan(\n uploadedParts: ReadonlyMap<number, ResumePartInfo>,\n plans: readonly ResumePartPlan[],\n): boolean {\n for (const [partNumber, part] of uploadedParts) {\n const planned = plans[partNumber - 1]\n if (planned === undefined) return false\n if (planned.partNumber !== partNumber) return false\n if (planned.length !== part.contentLength) return false\n }\n return true\n}\n\nfunction partInfoToSha1s(parts: ReadonlyMap<number, ResumePartInfo>): Map<number, string> {\n const sha1s = new Map<number, string>()\n for (const [partNumber, part] of parts) {\n sha1s.set(partNumber, part.contentSha1)\n }\n return sha1s\n}\n\nfunction recordEquals(a: Record<string, string>, b: Record<string, string>): boolean {\n const aKeys = Object.keys(a)\n const bKeys = Object.keys(b)\n if (aKeys.length !== bKeys.length) return false\n for (const key of aKeys) {\n if (a[key] !== b[key]) return false\n }\n return true\n}\n\ninterface SplitResumeFileInfo {\n readonly fileInfo: Record<string, string>\n readonly sourceSize?: string\n readonly partSize?: string\n}\n\nfunction splitResumeFileInfo(fileInfo: Record<string, string>): SplitResumeFileInfo {\n const userFileInfo: Record<string, string> = Object.create(null) as Record<string, string>\n let sourceSize: string | undefined\n let partSize: string | undefined\n for (const [key, value] of Object.entries(fileInfo)) {\n if (key === RESUME_SOURCE_SIZE_INFO_KEY) {\n sourceSize = value\n } else if (key === RESUME_PART_SIZE_INFO_KEY) {\n partSize = value\n } else {\n userFileInfo[key] = value\n }\n }\n return {\n fileInfo: userFileInfo,\n ...(sourceSize !== undefined ? { sourceSize } : {}),\n ...(partSize !== undefined ? { partSize } : {}),\n }\n}\n\nfunction fileRetentionMatches(\n candidate: ReadableFileRetention | undefined,\n expected: FileRetentionValue | undefined,\n defaultExpected: BucketRetentionPolicy | undefined,\n defaultUnreadable: boolean,\n uploadTimestamp: number | undefined,\n): boolean {\n if (expected === undefined && defaultUnreadable) return false\n if (expected === undefined && defaultExpected !== undefined) {\n if (defaultExpected.mode === BucketRetentionMode.None) {\n if (candidate === undefined) return true\n if (!candidate.isClientAuthorizedToRead) return false\n return fileRetentionValueEquals(candidate.value, null)\n }\n if (candidate === undefined || !candidate.isClientAuthorizedToRead) return false\n return fileRetentionValueMatchesBucketDefault(candidate.value, defaultExpected, uploadTimestamp)\n }\n if (expected === undefined) {\n if (candidate === undefined) return true\n if (!candidate.isClientAuthorizedToRead) return false\n return fileRetentionValueEquals(candidate.value, null)\n }\n if (candidate === undefined || !candidate.isClientAuthorizedToRead) return false\n return fileRetentionValueEquals(candidate.value, expected)\n}\n\nfunction fileRetentionValueMatchesBucketDefault(\n candidate: FileRetentionValue | null,\n expected: BucketRetentionPolicy,\n uploadTimestamp: number | undefined,\n): boolean {\n if (expected.period === null) return false\n if (candidate?.mode !== expected.mode || candidate.retainUntilTimestamp === null) return false\n if (uploadTimestamp === undefined) return false\n return candidate.retainUntilTimestamp === uploadTimestamp + retentionPeriodMillis(expected.period)\n}\n\nfunction retentionPeriodMillis(period: BucketRetentionPolicy['period']): number {\n if (period === null) return 0\n const days = period.unit === 'days' ? period.duration : period.duration * 365\n return days * 24 * 60 * 60 * 1000\n}\n\nfunction fileRetentionValueEquals(\n a: FileRetentionValue | null,\n b: FileRetentionValue | null,\n): boolean {\n return (\n (a?.mode ?? null) === (b?.mode ?? null) &&\n (a?.retainUntilTimestamp ?? null) === (b?.retainUntilTimestamp ?? null)\n )\n}\n\nfunction legalHoldMatches(\n candidate: ReadableLegalHold | undefined,\n expected: LegalHoldValue | undefined,\n): boolean {\n if (expected === undefined) {\n if (candidate === undefined) return true\n if (!candidate.isClientAuthorizedToRead) return false\n return candidate.value === null || candidate.value === 'off'\n }\n if (candidate === undefined || !candidate.isClientAuthorizedToRead) return false\n return candidate.value === expected\n}\n\ninterface ResumeDiscoverySignal {\n readonly signal?: AbortSignal\n dispose(): void\n}\n\nfunction createResumeDiscoverySignal(criteria: ResumeCandidateCriteria): ResumeDiscoverySignal {\n if (criteria.signal !== undefined) {\n return {\n signal: criteria.signal,\n dispose() {},\n }\n }\n\n if (criteria.discoveryTimeoutMs === undefined) {\n return {\n dispose() {},\n }\n }\n\n const timeoutMs = criteria.discoveryTimeoutMs\n if (timeoutMs === Number.POSITIVE_INFINITY) {\n return {\n dispose() {},\n }\n }\n\n const controller = new AbortController()\n const timeout = setTimeout(\n () => {\n controller.abort(resumeDiscoveryTimeoutReason(timeoutMs))\n },\n Math.max(0, timeoutMs),\n )\n\n return {\n signal: controller.signal,\n dispose() {\n clearTimeout(timeout)\n },\n }\n}\n\nasync function abortableRequest<T>(\n request: Promise<T>,\n signal: AbortSignal | undefined,\n): Promise<T> {\n if (signal === undefined) return request\n if (signal.aborted) throw resumeAbortReason(signal)\n\n let removeAbortListener: (() => void) | undefined\n const aborted = new Promise<never>((_resolve, reject) => {\n const onAbort = () => reject(resumeAbortReason(signal))\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n return await Promise.race([request, aborted])\n } finally {\n removeAbortListener?.()\n void request.catch(() => {})\n }\n}\n\nfunction resumeAbortReason(signal: AbortSignal): unknown {\n return signal.reason ?? resumeAbortFallbackReason()\n}\n\nfunction resumeAbortFallbackReason(): Error {\n if (typeof DOMException === 'function') {\n return new DOMException('Resume discovery aborted', 'AbortError')\n }\n const error = new Error('Resume discovery aborted')\n error.name = 'AbortError'\n return error\n}\n\nfunction resumeDiscoveryTimeoutReason(timeoutMs: number): Error {\n if (typeof DOMException === 'function') {\n return new DOMException(`Resume discovery timed out after ${timeoutMs} ms`, 'TimeoutError')\n }\n const error = new Error(`Resume discovery timed out after ${timeoutMs} ms`)\n error.name = 'TimeoutError'\n return error\n}\n\ntype ListedEncryption = PublicEncryptionSetting | undefined\n\nfunction serverSideEncryptionRejectReason(\n candidate: ListedEncryption,\n expected: EncryptionSetting | undefined,\n): 'encryption-mismatch' | 'sse-c-unsupported' | null {\n if (expected?.mode === EncryptionMode.SseC) return 'sse-c-unsupported'\n\n const actual = normalizeEncryption(candidate)\n if (expected === undefined) {\n if (candidate === undefined) return null\n if (actual === undefined) return 'encryption-mismatch'\n if (actual.mode === EncryptionMode.None) return null\n if (actual.mode === EncryptionMode.SseB2) return null\n return actual.mode === EncryptionMode.SseC ? 'sse-c-unsupported' : 'encryption-mismatch'\n }\n\n const normalizedExpected = normalizeEncryption(expected)\n if (normalizedExpected?.mode === EncryptionMode.None && candidate === undefined) return null\n if (actual === undefined || normalizedExpected === undefined) return 'encryption-mismatch'\n if (actual.mode !== normalizedExpected.mode) return 'encryption-mismatch'\n if (actual.mode === EncryptionMode.None) return null\n return actual.algorithm === normalizedExpected.algorithm ? null : 'encryption-mismatch'\n}\n\ninterface NormalizedEncryption {\n readonly mode: EncryptionMode\n readonly algorithm?: string\n}\n\nfunction normalizeEncryption(\n encryption: EncryptionSetting | ListedEncryption,\n): NormalizedEncryption | undefined {\n if (encryption === undefined) return undefined\n // Real B2 responses may spell no encryption as `{ mode: null, algorithm: null }`.\n if (encryption.mode === null || encryption.mode === EncryptionMode.None) {\n return { mode: EncryptionMode.None }\n }\n if (encryption.mode !== EncryptionMode.SseB2 && encryption.mode !== EncryptionMode.SseC) {\n return undefined\n }\n return {\n mode: encryption.mode,\n algorithm: encryption.algorithm,\n }\n}\n\nfunction assertAdvancingPartCursor(\n fileId: LargeFileId,\n previous: number | undefined,\n next: number,\n): void {\n if (!Number.isInteger(next) || next < 1 || (previous !== undefined && next <= previous)) {\n throw new Error(\n `uploadLargeFile: listParts returned a non-advancing nextPartNumber for ${fileId}; aborting resume.`,\n )\n }\n}\n"],"mappings":"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"}
|
package/dist/upload/resume.d.cts
CHANGED
|
@@ -1,6 +1,81 @@
|
|
|
1
1
|
import { AccountInfo } from '../auth/account-info.js';
|
|
2
|
+
import { ResumeFileIdMismatchError } from '../errors/index.js';
|
|
2
3
|
import { RawClient } from '../raw/index.js';
|
|
4
|
+
import { BucketRetentionPolicy } from '../types/bucket.js';
|
|
5
|
+
import { EncryptionSetting } from '../types/encryption.js';
|
|
3
6
|
import { BucketId, LargeFileId } from '../types/ids.js';
|
|
7
|
+
import { FileRetentionValue, LegalHoldValue } from '../types/lock.js';
|
|
8
|
+
export { ResumeFileIdMismatchError };
|
|
9
|
+
/** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */
|
|
10
|
+
export declare const RESUME_SOURCE_SIZE_INFO_KEY = "b2_sdk_resume_source_size";
|
|
11
|
+
/** Compatibility-only file-info key read from legacy unfinished uploads; new uploads do not write it. */
|
|
12
|
+
export declare const RESUME_PART_SIZE_INFO_KEY = "b2_sdk_resume_part_size";
|
|
13
|
+
/** One planned part from the local upload source. */
|
|
14
|
+
export interface ResumePartPlan {
|
|
15
|
+
/** 1-based B2 part number. */
|
|
16
|
+
readonly partNumber: number;
|
|
17
|
+
/** Expected byte length for this part. */
|
|
18
|
+
readonly length: number;
|
|
19
|
+
}
|
|
20
|
+
/** Reason an unfinished same-name large file was not reused for resume. */
|
|
21
|
+
export type ResumeCandidateRejectedReason = 'search-truncated' | 'candidate-limit' | 'file-name-mismatch' | 'content-type-mismatch' | 'file-info-mismatch' | 'source-size-mismatch' | 'part-size-mismatch' | 'encryption-mismatch' | 'sse-c-unsupported' | 'retention-mismatch' | 'legal-hold-mismatch' | 'part-length-mismatch';
|
|
22
|
+
/** Diagnostic event emitted when resume discovery declines a candidate. */
|
|
23
|
+
export interface ResumeCandidateRejectedEvent {
|
|
24
|
+
/** ID of the unfinished large file, when the event is candidate-specific. */
|
|
25
|
+
readonly fileId?: LargeFileId;
|
|
26
|
+
/** Requested destination file name. */
|
|
27
|
+
readonly requestedFileName: string;
|
|
28
|
+
/** Actual candidate file name, when the event is candidate-specific. */
|
|
29
|
+
readonly candidateFileName?: string;
|
|
30
|
+
/** Machine-readable rejection reason. */
|
|
31
|
+
readonly reason: ResumeCandidateRejectedReason;
|
|
32
|
+
}
|
|
33
|
+
/** Diagnostic callback for declined resume candidates. */
|
|
34
|
+
export type ResumeCandidateRejectedListener = (event: ResumeCandidateRejectedEvent) => void;
|
|
35
|
+
/** Compatibility requirements an unfinished large file must satisfy before reuse. */
|
|
36
|
+
export interface ResumeCandidateCriteria {
|
|
37
|
+
/** Effective MIME type for the upload, including SDK defaults. */
|
|
38
|
+
readonly contentType: string;
|
|
39
|
+
/** Caller-owned file info. Legacy SDK resume keys on candidates are ignored separately. */
|
|
40
|
+
readonly fileInfo: Record<string, string>;
|
|
41
|
+
/** Source size in bytes, checked against legacy SDK metadata when a candidate carries it. */
|
|
42
|
+
readonly sourceSize: number;
|
|
43
|
+
/** Effective multipart part size, checked against legacy SDK metadata when present. */
|
|
44
|
+
readonly partSize: number;
|
|
45
|
+
/** Planned local parts used to verify already-uploaded server part lengths. */
|
|
46
|
+
readonly parts: readonly ResumePartPlan[];
|
|
47
|
+
/** Explicit server-side encryption option, if configured by the caller. */
|
|
48
|
+
readonly serverSideEncryption?: EncryptionSetting;
|
|
49
|
+
/** Explicit Object Lock retention option, if configured by the caller. */
|
|
50
|
+
readonly fileRetention?: FileRetentionValue;
|
|
51
|
+
/** Effective readable bucket default retention when the caller omits fileRetention. */
|
|
52
|
+
readonly defaultFileRetention?: BucketRetentionPolicy;
|
|
53
|
+
/** Whether bucket default retention exists but cannot be read by the caller. */
|
|
54
|
+
readonly defaultFileRetentionUnreadable?: boolean;
|
|
55
|
+
/** Explicit legal hold option, if configured by the caller. */
|
|
56
|
+
readonly legalHold?: LegalHoldValue;
|
|
57
|
+
/** Explicit unfinished large-file ID to verify before reuse. */
|
|
58
|
+
readonly resumeFileId?: LargeFileId;
|
|
59
|
+
/** Abort signal used for B2 list requests and checked between pages. */
|
|
60
|
+
readonly signal?: AbortSignal;
|
|
61
|
+
/** Optional diagnostic callback for candidates that are found but not reused. */
|
|
62
|
+
readonly onCandidateRejected?: ResumeCandidateRejectedListener;
|
|
63
|
+
/** Maximum `b2_list_unfinished_large_files` pages to inspect. */
|
|
64
|
+
readonly maxListPages?: number;
|
|
65
|
+
/** Maximum metadata-compatible candidates whose parts may be listed. */
|
|
66
|
+
readonly maxPartCandidates?: number;
|
|
67
|
+
/** Maximum `b2_list_parts` pages to inspect for each metadata-compatible candidate. */
|
|
68
|
+
readonly maxPartPages?: number;
|
|
69
|
+
/** Caller-supplied aggregate resume discovery timeout. */
|
|
70
|
+
readonly discoveryTimeoutMs?: number;
|
|
71
|
+
}
|
|
72
|
+
/** Uploaded part metadata used by the resume planner. */
|
|
73
|
+
export interface ResumePartInfo {
|
|
74
|
+
/** SHA-1 stored by B2 for this uploaded part. */
|
|
75
|
+
readonly contentSha1: string;
|
|
76
|
+
/** Byte length stored by B2 for this uploaded part. */
|
|
77
|
+
readonly contentLength: number;
|
|
78
|
+
}
|
|
4
79
|
/** Information about an unfinished large file eligible for resume. */
|
|
5
80
|
export interface ResumeCandidate {
|
|
6
81
|
/** ID of the unfinished large file. */
|
|
@@ -10,24 +85,19 @@ export interface ResumeCandidate {
|
|
|
10
85
|
}
|
|
11
86
|
/**
|
|
12
87
|
* Finds an unfinished large file matching the given bucket and file name.
|
|
13
|
-
* Returns `null` when no
|
|
88
|
+
* Returns `null` when no compatible candidate exists.
|
|
89
|
+
*
|
|
90
|
+
* With criteria, the newest compatible candidate is selected; incompatible
|
|
91
|
+
* same-name uploads are ignored and optionally reported via
|
|
92
|
+
* `onCandidateRejected`.
|
|
14
93
|
*
|
|
15
94
|
* @param raw - Low-level B2 API client.
|
|
16
95
|
* @param accountInfo - Authorized account state.
|
|
17
96
|
* @param bucketId - Target bucket of the upload.
|
|
18
97
|
* @param fileName - Destination file name of the upload.
|
|
98
|
+
* @param criteria - Upload identity and option checks.
|
|
19
99
|
*
|
|
20
100
|
* @returns A {@link ResumeCandidate} describing the candidate and its uploaded parts, or `null`.
|
|
21
101
|
*/
|
|
22
|
-
export declare function findResumeCandidate(raw: RawClient, accountInfo: AccountInfo, bucketId: BucketId, fileName: string): Promise<ResumeCandidate | null>;
|
|
23
|
-
/**
|
|
24
|
-
* Lists all uploaded parts for a large file, paginating until exhausted.
|
|
25
|
-
*
|
|
26
|
-
* @param raw - Low-level B2 API client.
|
|
27
|
-
* @param accountInfo - Authorized account state.
|
|
28
|
-
* @param fileId - ID of the large file to inspect.
|
|
29
|
-
*
|
|
30
|
-
* @returns A map from 1-based part number to its server-stored SHA-1.
|
|
31
|
-
*/
|
|
32
|
-
export declare function collectPartSha1s(raw: RawClient, accountInfo: AccountInfo, fileId: LargeFileId): Promise<Map<number, string>>;
|
|
102
|
+
export declare function findResumeCandidate(raw: RawClient, accountInfo: AccountInfo, bucketId: BucketId, fileName: string, criteria: ResumeCandidateCriteria): Promise<ResumeCandidate | null>;
|
|
33
103
|
//# sourceMappingURL=resume.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../src/upload/resume.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../src/upload/resume.js"],"names":[],"mappings":"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"}
|