@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
|
@@ -1,203 +1,788 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
1
|
+
const require_ids = require("../types/ids.cjs");
|
|
2
|
+
const require_file_source = require("../streams/file-source.cjs");
|
|
3
|
+
const require_index = require("./actions/index.cjs");
|
|
4
|
+
const require_pairing = require("./pairing.cjs");
|
|
5
|
+
const require_error_reason = require("../util/error-reason.cjs");
|
|
6
|
+
const require_sha1_options = require("./sha1-options.cjs");
|
|
7
|
+
const require_local_sha1 = require("./local-sha1.cjs");
|
|
8
|
+
const require_compare = require("./policies/compare.cjs");
|
|
9
|
+
const require_index$1 = require("./policies/index.cjs");
|
|
10
|
+
const require_path_safety = require("./path-safety.cjs");
|
|
11
|
+
const require_prefix = require("./prefix.cjs");
|
|
12
|
+
const require_filesystem_errors = require("./filesystem-errors.cjs");
|
|
13
|
+
const require_local_filesystem_root = require("./local-filesystem-root.cjs");
|
|
14
|
+
const require_b2_sha1_reader = require("./b2-sha1-reader.cjs");
|
|
15
|
+
const require_local_file_io = require("./local-file-io.cjs");
|
|
16
|
+
//#region src/sync/synchronizer.ts
|
|
17
|
+
var MAX_BUFFERED_SCAN_EVENTS = 100;
|
|
18
|
+
var MAX_AGGREGATE_FAILED_PATHS = 100;
|
|
19
|
+
var DEFAULT_DOWNLOAD_IDLE_TIMEOUT_MILLIS = 6e4;
|
|
20
|
+
/**
|
|
21
|
+
* Test hooks for bounded planning behavior.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
var synchronizerTestHooks = {};
|
|
26
|
+
/**
|
|
27
|
+
* Infers the sync direction from the source and destination folder types.
|
|
28
|
+
* @param source - The folder to read files from.
|
|
29
|
+
* @param dest - The folder to write files to.
|
|
30
|
+
*
|
|
31
|
+
* @returns The resolved sync direction based on folder types.
|
|
32
|
+
*
|
|
33
|
+
* @throws When the source and destination folder types form an unsupported combination.
|
|
34
|
+
*/
|
|
35
|
+
function resolveDirection(source, dest) {
|
|
36
|
+
if (source.type === "local" && dest.type === "b2") return "local-to-b2";
|
|
37
|
+
if (source.type === "b2" && dest.type === "local") return "b2-to-local";
|
|
38
|
+
if (source.type === "b2" && dest.type === "b2") return "b2-to-b2";
|
|
39
|
+
throw new Error(`Unsupported sync direction: ${source.type} to ${dest.type}`);
|
|
38
40
|
}
|
|
39
41
|
async function* synchronize(config) {
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
42
|
+
const { source, dest, options } = config;
|
|
43
|
+
require_compare.assertSupportedCompareMode(options.compareMode);
|
|
44
|
+
const direction = resolveDirection(source, dest);
|
|
45
|
+
const dryRun = options.dryRun ?? false;
|
|
46
|
+
const concurrency = normalizeSyncConcurrency(options.concurrency);
|
|
47
|
+
const keepDays = options.keepDays ?? 0;
|
|
48
|
+
const compareThreshold = options.compareThreshold ?? 0;
|
|
49
|
+
const nowMillis = Date.now();
|
|
50
|
+
const localRootContexts = await resolveLocalRootContexts(config);
|
|
51
|
+
const queuedEvents = [];
|
|
52
|
+
const failedPaths = [];
|
|
53
|
+
const failedPathSet = /* @__PURE__ */ new Set();
|
|
54
|
+
let errorCount = 0;
|
|
55
|
+
let failedPathOmittedCount = 0;
|
|
56
|
+
let scanHadError = false;
|
|
57
|
+
const runningActions = /* @__PURE__ */ new Set();
|
|
58
|
+
const scanEvents = {
|
|
59
|
+
events: [],
|
|
60
|
+
dropped: 0
|
|
61
|
+
};
|
|
62
|
+
const scanOptions = {
|
|
63
|
+
...options.include !== void 0 ? { include: options.include } : {},
|
|
64
|
+
...options.exclude !== void 0 ? { exclude: options.exclude } : {},
|
|
65
|
+
...options.signal !== void 0 ? { signal: options.signal } : {},
|
|
66
|
+
...options.maxScanEntries !== void 0 ? { maxScanEntries: options.maxScanEntries } : {},
|
|
67
|
+
...direction === "b2-to-local" ? { requireLocalSafePaths: true } : {},
|
|
68
|
+
onError: (event) => {
|
|
69
|
+
scanHadError = true;
|
|
70
|
+
recordSyncError(event);
|
|
71
|
+
queueEvent(event);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const factory = createActionFactory(config, localRootContexts);
|
|
75
|
+
const readB2Sha1 = dryRun ? void 0 : createB2Sha1Reader(config);
|
|
76
|
+
const actionAbortController = new AbortController();
|
|
77
|
+
const removeAbortForwarder = forwardAbortSignal(options.signal, actionAbortController);
|
|
78
|
+
let completed = false;
|
|
79
|
+
async function* finishAfterAbort() {
|
|
80
|
+
await drainActions();
|
|
81
|
+
yield* emitQueuedEvents();
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
let pairs;
|
|
85
|
+
try {
|
|
86
|
+
pairs = await collectPairs();
|
|
87
|
+
} catch (err) {
|
|
88
|
+
await drainActions();
|
|
89
|
+
if (options.signal?.aborted) {
|
|
90
|
+
yield* finishAfterAbort();
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (!scanHadError) {
|
|
94
|
+
yield* emitQueuedEvents();
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
yield* emitQueuedEvents();
|
|
98
|
+
yield aggregateErrorEvent();
|
|
99
|
+
completed = true;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
yield* emitQueuedEvents();
|
|
103
|
+
const filesystemError = scanFilesystemError(scanEvents);
|
|
104
|
+
if (filesystemError !== void 0) throw filesystemError;
|
|
105
|
+
if (options.signal?.aborted) {
|
|
106
|
+
yield* finishAfterAbort();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (scanHadError) {
|
|
110
|
+
if (errorCount > 0) yield aggregateErrorEvent();
|
|
111
|
+
completed = true;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (options.compareMode === "sha1") {
|
|
115
|
+
const compareBatchSize = concurrency;
|
|
116
|
+
for (let index = 0; index < pairs.length; index += compareBatchSize) if (yield* emitSha1Batch(pairs.slice(index, index + compareBatchSize))) return;
|
|
117
|
+
} else for (let index = 0; index < pairs.length; index += concurrency) {
|
|
118
|
+
const items = pairs.slice(index, index + concurrency).map((pair) => planPreparedPair(pair, require_compare.readyComparePair(pair)));
|
|
119
|
+
synchronizerTestHooks.afterNonSha1PlanBatch?.(items.length);
|
|
120
|
+
if (yield* emitPreparedItems(items)) return;
|
|
121
|
+
}
|
|
122
|
+
await drainActions();
|
|
123
|
+
yield* emitQueuedEvents();
|
|
124
|
+
if (errorCount > 0) yield aggregateErrorEvent();
|
|
125
|
+
completed = true;
|
|
126
|
+
} finally {
|
|
127
|
+
if (!completed) abortActionController(actionAbortController, new DOMException("Sync iterator closed", "AbortError"));
|
|
128
|
+
removeAbortForwarder();
|
|
129
|
+
await drainActions();
|
|
130
|
+
}
|
|
131
|
+
async function collectPairs() {
|
|
132
|
+
const pairs = [];
|
|
133
|
+
for await (const pair of require_pairing.zipFolders(source, dest, scanOptions, {
|
|
134
|
+
onSourceSkip(event) {
|
|
135
|
+
bufferScanEvent(scanEvents, event, direction, "source");
|
|
136
|
+
},
|
|
137
|
+
onDestSkip(event) {
|
|
138
|
+
bufferScanEvent(scanEvents, event, direction, "dest");
|
|
139
|
+
}
|
|
140
|
+
})) {
|
|
141
|
+
if (options.signal?.aborted) return pairs;
|
|
142
|
+
validateB2SourcePairPrefix(pair, config);
|
|
143
|
+
pairs.push(pair);
|
|
144
|
+
}
|
|
145
|
+
return pairs;
|
|
146
|
+
}
|
|
147
|
+
async function* emitSha1Batch(batch) {
|
|
148
|
+
if (batch.length === 0) return false;
|
|
149
|
+
await drainActions();
|
|
150
|
+
yield* emitQueuedEvents();
|
|
151
|
+
const preparedBatch = await processPreparedBatch(batch);
|
|
152
|
+
if (yield* emitPreparedItems(preparedBatch.items)) return true;
|
|
153
|
+
if (preparedBatch.aborted || options.signal?.aborted) {
|
|
154
|
+
yield* finishAfterAbort();
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
async function* emitPreparedItems(items) {
|
|
160
|
+
for (const item of items) {
|
|
161
|
+
yield* emitQueuedEvents();
|
|
162
|
+
yield item.event;
|
|
163
|
+
yield* emitQueuedEvents();
|
|
164
|
+
/* v8 ignore next -- abort between compare yield and scheduling is timing-dependent */
|
|
165
|
+
if (options.signal?.aborted) {
|
|
166
|
+
yield* finishAfterAbort();
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
for (const action of item.actions) {
|
|
170
|
+
await scheduleAction(action);
|
|
171
|
+
yield* emitQueuedEvents();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
async function processPreparedBatch(batch) {
|
|
177
|
+
if (batch.length === 0) return {
|
|
178
|
+
items: [],
|
|
179
|
+
aborted: false
|
|
180
|
+
};
|
|
181
|
+
const preparedPairs = await require_compare.preparePairsForCompare(batch, "sha1", {
|
|
182
|
+
concurrency,
|
|
183
|
+
...options.signal !== void 0 ? { signal: options.signal } : {},
|
|
184
|
+
...options.sha1ReadTimeoutMillis !== void 0 ? { sha1ReadTimeoutMillis: options.sha1ReadTimeoutMillis } : {},
|
|
185
|
+
readLocalSha1: require_local_sha1.readLocalSha1File,
|
|
186
|
+
...readB2Sha1 !== void 0 ? { readB2Sha1 } : {}
|
|
187
|
+
});
|
|
188
|
+
const items = [];
|
|
189
|
+
for (const { originalPair, prepared } of preparedPairs) {
|
|
190
|
+
if (prepared.aborted || options.signal?.aborted) return {
|
|
191
|
+
items,
|
|
192
|
+
aborted: true
|
|
193
|
+
};
|
|
194
|
+
items.push(planPreparedPair(originalPair, prepared));
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
items,
|
|
198
|
+
aborted: false
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function planPreparedPair(pair, prepared) {
|
|
202
|
+
const event = {
|
|
203
|
+
type: "compare",
|
|
204
|
+
path: (pair[0] ?? pair[1])?.relativePath ?? "",
|
|
205
|
+
size: 0,
|
|
206
|
+
bytesHashed: prepared.bytesHashed,
|
|
207
|
+
...prepared.bytesVerified > 0 ? { bytesVerified: prepared.bytesVerified } : {}
|
|
208
|
+
};
|
|
209
|
+
let preparedErrorEventCount = 0;
|
|
210
|
+
for (const preparedEvent of prepared.events) {
|
|
211
|
+
queueEvent(preparedEvent);
|
|
212
|
+
if (preparedEvent.type === "error") {
|
|
213
|
+
preparedErrorEventCount++;
|
|
214
|
+
recordFailurePath(preparedEvent.path);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
errorCount += prepared.errors.length;
|
|
218
|
+
for (let index = preparedErrorEventCount; index < prepared.errors.length; index++) recordFailurePath(event.path);
|
|
219
|
+
if (prepared.skipActionGeneration) return {
|
|
220
|
+
event,
|
|
221
|
+
actions: []
|
|
222
|
+
};
|
|
223
|
+
if ((scanHadError || scanHadFilesystemError(scanEvents)) && prepared.pair[0] === null && prepared.pair[1] !== null) return {
|
|
224
|
+
event,
|
|
225
|
+
actions: [new require_index.SkipAction(prepared.pair[1].relativePath, "not removed because scan errors occurred")]
|
|
226
|
+
};
|
|
227
|
+
if (sourceInventoryIncomplete(scanEvents) && prepared.pair[0] === null && prepared.pair[1] !== null) return {
|
|
228
|
+
event,
|
|
229
|
+
actions: [new require_index.SkipAction(prepared.pair[1].relativePath, scanEvents.sourceInventoryIncompleteMessage ?? "not removed because the source scan skipped unsafe B2 names")]
|
|
230
|
+
};
|
|
231
|
+
return {
|
|
232
|
+
event,
|
|
233
|
+
actions: [...require_index$1.generateActions(prepared.pair, direction, options.compareMode, options.keepMode, keepDays, nowMillis, factory, compareThreshold)]
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
async function scheduleAction(action) {
|
|
237
|
+
const task = executeAction(action).finally(() => {
|
|
238
|
+
runningActions.delete(task);
|
|
239
|
+
});
|
|
240
|
+
runningActions.add(task);
|
|
241
|
+
if (runningActions.size >= concurrency) await Promise.race(runningActions);
|
|
242
|
+
}
|
|
243
|
+
async function executeAction(action) {
|
|
244
|
+
try {
|
|
245
|
+
if (actionAbortController.signal.aborted) return;
|
|
246
|
+
queueEvent(await action.execute(dryRun, actionAbortController.signal));
|
|
247
|
+
} catch (err) {
|
|
248
|
+
const event = {
|
|
249
|
+
type: "error",
|
|
250
|
+
path: action.relativePath,
|
|
251
|
+
size: 0,
|
|
252
|
+
message: require_error_reason.sanitizeErrorReason(err)
|
|
253
|
+
};
|
|
254
|
+
recordSyncError(event);
|
|
255
|
+
queueEvent(event);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function recordSyncError(event) {
|
|
259
|
+
errorCount += 1;
|
|
260
|
+
recordFailurePath(event.path);
|
|
261
|
+
}
|
|
262
|
+
function recordFailurePath(path) {
|
|
263
|
+
if (path === "") return;
|
|
264
|
+
if (failedPathSet.has(path)) return;
|
|
265
|
+
failedPathSet.add(path);
|
|
266
|
+
if (failedPaths.length < MAX_AGGREGATE_FAILED_PATHS) failedPaths.push(path);
|
|
267
|
+
else failedPathOmittedCount++;
|
|
268
|
+
}
|
|
269
|
+
function aggregateErrorEvent() {
|
|
270
|
+
return {
|
|
271
|
+
type: "error",
|
|
272
|
+
path: "",
|
|
273
|
+
size: 0,
|
|
274
|
+
message: `${errorCount} sync error(s) occurred`,
|
|
275
|
+
failureCount: errorCount,
|
|
276
|
+
failedPaths: [...failedPaths],
|
|
277
|
+
...failedPathOmittedCount > 0 ? { failedPathOmittedCount } : {}
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function queueEvent(event) {
|
|
281
|
+
queuedEvents.push(event);
|
|
282
|
+
}
|
|
283
|
+
async function* emitQueuedEvents() {
|
|
284
|
+
yield* drainScanEvents(scanEvents);
|
|
285
|
+
for (const event of queuedEvents.splice(0)) yield event;
|
|
286
|
+
}
|
|
287
|
+
async function drainActions() {
|
|
288
|
+
while (runningActions.size > 0) await Promise.race(runningActions);
|
|
289
|
+
}
|
|
99
290
|
}
|
|
291
|
+
/**
|
|
292
|
+
* Normalizes user-provided sync concurrency before it controls compare batches and transfers.
|
|
293
|
+
*
|
|
294
|
+
* @param value - Optional concurrency value from sync options.
|
|
295
|
+
*
|
|
296
|
+
* @returns A positive integer concurrency value.
|
|
297
|
+
*
|
|
298
|
+
* @throws When the configured concurrency is not a positive integer.
|
|
299
|
+
*/
|
|
300
|
+
function normalizeSyncConcurrency(value) {
|
|
301
|
+
const candidate = value ?? 4;
|
|
302
|
+
if (!Number.isInteger(candidate) || candidate < 1) throw new RangeError("Sync concurrency must be a positive integer");
|
|
303
|
+
return candidate;
|
|
304
|
+
}
|
|
305
|
+
function normalizeDownloadIdleTimeoutMillis(value) {
|
|
306
|
+
if (value === void 0) return DEFAULT_DOWNLOAD_IDLE_TIMEOUT_MILLIS;
|
|
307
|
+
if (value === Number.POSITIVE_INFINITY) return value;
|
|
308
|
+
if (!Number.isFinite(value) || value < 1) throw new RangeError("downloadIdleTimeoutMillis must be a positive finite number or Infinity");
|
|
309
|
+
return Math.floor(value);
|
|
310
|
+
}
|
|
311
|
+
function assertValidB2ContentLength(contentLength) {
|
|
312
|
+
if (!Number.isSafeInteger(contentLength) || contentLength < 0) throw new Error("B2 contentLength must be a non-negative safe integer");
|
|
313
|
+
return contentLength;
|
|
314
|
+
}
|
|
315
|
+
function createB2Sha1Reader(config) {
|
|
316
|
+
const upConfig = config;
|
|
317
|
+
const downConfig = config;
|
|
318
|
+
const bucket = upConfig.bucket ?? downConfig.bucket;
|
|
319
|
+
if (bucket === void 0) return void 0;
|
|
320
|
+
const readablePrefixes = b2ReadableRawPrefixes(config);
|
|
321
|
+
const idleTimeoutMillis = require_sha1_options.normalizeSha1TimeoutMillis(config.options.sha1ReadTimeoutMillis);
|
|
322
|
+
const verificationTimeoutMillis = require_sha1_options.normalizeSha1TimeoutMillis(config.options.sha1VerificationTimeoutMillis, require_sha1_options.DEFAULT_SHA1_VERIFICATION_TIMEOUT_MILLIS);
|
|
323
|
+
return async (path, signal) => {
|
|
324
|
+
const expectedBytes = assertValidB2ContentLength(path.selectedVersion.contentLength);
|
|
325
|
+
const maxBytes = require_b2_sha1_reader.normalizeSha1VerificationMaxBytes(expectedBytes, config.options.sha1VerificationMaxBytes);
|
|
326
|
+
return require_b2_sha1_reader.withSha1VerificationDeadline(signal, verificationTimeoutMillis, async (deadlineSignal) => {
|
|
327
|
+
deadlineSignal.throwIfAborted();
|
|
328
|
+
if (maxBytes < expectedBytes) throw new Error(`sha1 B2 verification skipped because contentLength ${expectedBytes} exceeds ${maxBytes} byte verification budget`);
|
|
329
|
+
const serverSideEncryption = toSseCDownloadKey(config.options.encryptionProvider?.getSettingForDownload(path.selectedVersion));
|
|
330
|
+
const fileName = validateB2SyncPathInAnyPrefix(readablePrefixes, path, "read");
|
|
331
|
+
const verified = await require_b2_sha1_reader.hashReadableStreamSha1((await bucket.file(fileName).downloadById(path.selectedVersion.fileId, {
|
|
332
|
+
...serverSideEncryption !== void 0 ? { serverSideEncryption } : {},
|
|
333
|
+
signal: deadlineSignal
|
|
334
|
+
})).body, deadlineSignal, {
|
|
335
|
+
idleTimeoutMillis,
|
|
336
|
+
maxBytes,
|
|
337
|
+
expectedBytes
|
|
338
|
+
});
|
|
339
|
+
return {
|
|
340
|
+
contentSha1: verified.contentSha1,
|
|
341
|
+
bytesRead: verified.bytesRead
|
|
342
|
+
};
|
|
343
|
+
});
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
function forwardAbortSignal(source, controller) {
|
|
347
|
+
if (source === void 0) return () => void 0;
|
|
348
|
+
if (source.aborted) {
|
|
349
|
+
abortActionController(controller, source.reason);
|
|
350
|
+
return () => void 0;
|
|
351
|
+
}
|
|
352
|
+
const abort = () => abortActionController(controller, source.reason);
|
|
353
|
+
source.addEventListener("abort", abort, { once: true });
|
|
354
|
+
return () => source.removeEventListener("abort", abort);
|
|
355
|
+
}
|
|
356
|
+
function abortActionController(controller, reason) {
|
|
357
|
+
if (!controller.signal.aborted) controller.abort(reason);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Narrowing assertion that a `Bucket` is present for an action that requires
|
|
361
|
+
* it. Throws with a consistent, context-tagged message when the configured
|
|
362
|
+
* direction did not supply one (e.g. `b2-to-local` direction asking for an
|
|
363
|
+
* upload action).
|
|
364
|
+
*
|
|
365
|
+
* Uses TypeScript's `asserts` signature so call-site flow narrows
|
|
366
|
+
* `bucket` from `Bucket | undefined` to `Bucket` after the check, without
|
|
367
|
+
* requiring a separate `if (!bucket) throw ...` line per action factory.
|
|
368
|
+
*
|
|
369
|
+
* @param bucket - The (possibly missing) bucket reference.
|
|
370
|
+
* @param context - Short verb describing the action being constructed
|
|
371
|
+
* (e.g. `'upload'`, `'download'`). Surfaced in the error message.
|
|
372
|
+
*
|
|
373
|
+
* @throws `Error` when `bucket` is `undefined` or `null`.
|
|
374
|
+
*/
|
|
100
375
|
function assertBucket(bucket, context) {
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
376
|
+
if (!bucket) throw new Error(`Bucket required for ${context} actions`);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Returns the root for a local sync folder required by an action.
|
|
380
|
+
*
|
|
381
|
+
* @param folder - The configured folder to validate.
|
|
382
|
+
* @param role - Whether the local folder is the source or destination.
|
|
383
|
+
* @param context - Short verb describing the action being constructed.
|
|
384
|
+
*
|
|
385
|
+
* @returns The local filesystem root.
|
|
386
|
+
*
|
|
387
|
+
* @throws `Error` when the folder is not local or has no root.
|
|
388
|
+
*/
|
|
389
|
+
function requireLocalRoot(folder, role, context) {
|
|
390
|
+
const root = folder?.type === "local" ? folder.root : void 0;
|
|
391
|
+
if (typeof root !== "string" || root === "") throw new Error(`Local ${role} root required for ${context} actions`);
|
|
392
|
+
return root;
|
|
393
|
+
}
|
|
394
|
+
async function resolveLocalRootContexts(config) {
|
|
395
|
+
const sourceIsLocalFilesystem = isLocalFilesystemFolder(config.source);
|
|
396
|
+
const destIsLocalFilesystem = isLocalFilesystemFolder(config.dest);
|
|
397
|
+
if (!sourceIsLocalFilesystem && !destIsLocalFilesystem) return {};
|
|
398
|
+
const sourceContext = config.dest.type === "b2" ? "upload" : "sync";
|
|
399
|
+
const destContext = config.source.type === "b2" ? "download" : "sync";
|
|
400
|
+
return {
|
|
401
|
+
...sourceIsLocalFilesystem ? { source: await resolveLocalRootContext(requireLocalRoot(config.source, "source", sourceContext)) } : {},
|
|
402
|
+
...destIsLocalFilesystem ? { dest: await resolveLocalRootContext(requireLocalRoot(config.dest, "destination", destContext)) } : {}
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
async function resolveLocalRootContext(root) {
|
|
406
|
+
const { realpath, stat } = await import("node:fs/promises");
|
|
407
|
+
const { resolve } = await import("node:path");
|
|
408
|
+
const safeRoot = resolve(root);
|
|
409
|
+
const realPath = await realpath(safeRoot).catch((err) => {
|
|
410
|
+
if (isNotFoundError(err)) return safeRoot;
|
|
411
|
+
throw err;
|
|
412
|
+
});
|
|
413
|
+
const stats = await stat(realPath).catch((err) => {
|
|
414
|
+
if (isNotFoundError(err)) return void 0;
|
|
415
|
+
throw err;
|
|
416
|
+
});
|
|
417
|
+
if (stats !== void 0 && !stats.isDirectory()) throw new Error("Local sync root is not a directory");
|
|
418
|
+
return {
|
|
419
|
+
root: safeRoot,
|
|
420
|
+
realPath,
|
|
421
|
+
...stats === void 0 ? {} : { identity: {
|
|
422
|
+
deviceId: stats.dev,
|
|
423
|
+
inode: stats.ino
|
|
424
|
+
} }
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
function isLocalFilesystemFolder(folder) {
|
|
428
|
+
return folder?.type === "local" && require_local_filesystem_root.isLocalFilesystemRoot(folder);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Narrows a setting to SSE-C; non-SSE-C source settings need no key on read.
|
|
432
|
+
*
|
|
433
|
+
* @param setting - Provider-supplied encryption setting, or undefined.
|
|
434
|
+
*
|
|
435
|
+
* @returns The SSE-C setting when one is provided; otherwise undefined.
|
|
436
|
+
*/
|
|
437
|
+
function toSseCEncryptionSetting(setting) {
|
|
438
|
+
if (setting?.mode !== "SSE-C") return void 0;
|
|
439
|
+
return setting;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Returns a download key from SSE-C settings; non-SSE-C downloads need no key.
|
|
443
|
+
*
|
|
444
|
+
* @param setting - Provider-supplied encryption setting, or undefined.
|
|
445
|
+
*
|
|
446
|
+
* @returns A download key for SSE-C files; otherwise undefined.
|
|
447
|
+
*/
|
|
448
|
+
function toSseCDownloadKey(setting) {
|
|
449
|
+
return toSseCEncryptionSetting(setting);
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Creates a configured sync engine wired to the bucket and paths in the given config.
|
|
453
|
+
*
|
|
454
|
+
* For sync operations that may need to remove destination-only files (the
|
|
455
|
+
* `keepMode: 'delete'` policy), the factory reads the destination
|
|
456
|
+
* bucket's cached `fileLockConfiguration` once so `removeOrphan` can
|
|
457
|
+
* dispatch to either `hide` (locked buckets) or `deleteFileVersion`
|
|
458
|
+
* (vanilla buckets) without a per-file branch. The cache is whatever
|
|
459
|
+
* `client.listBuckets()` or `client.createBucket()` returned — callers
|
|
460
|
+
* who flipped lock state mid-sync (rare) should refresh before
|
|
461
|
+
* synchronize().
|
|
462
|
+
*
|
|
463
|
+
* @param config - Synchronizer configuration containing source, destination, and options.
|
|
464
|
+
* @param localRootContexts - Resolved filesystem roots captured before action creation.
|
|
465
|
+
*
|
|
466
|
+
* @returns An action factory bound to the provided configuration.
|
|
467
|
+
*/
|
|
468
|
+
function createActionFactory(config, localRootContexts) {
|
|
469
|
+
const upConfig = config;
|
|
470
|
+
const downConfig = config;
|
|
471
|
+
const uploadPrefix = require_prefix.asRawB2KeyPrefix(upConfig.prefix ?? b2FolderRawPrefix(config.dest) ?? "");
|
|
472
|
+
const sourceB2Prefix = b2FolderRawPrefix(config.source);
|
|
473
|
+
const bucketIsLocked = (upConfig.bucket ?? downConfig.bucket)?.info?.fileLockConfiguration?.value?.isFileLockEnabled ?? false;
|
|
474
|
+
const factory = {
|
|
475
|
+
upload(source, dest) {
|
|
476
|
+
const bucket = upConfig.bucket;
|
|
477
|
+
assertBucket(bucket, "upload");
|
|
478
|
+
return new require_index.UploadAction(source.relativePath, source.absolutePath, source.size, async (absPath, relPath, signal) => {
|
|
479
|
+
const rootContext = localRootContexts.source;
|
|
480
|
+
const root = rootContext?.root ?? upConfig.source.root ?? "";
|
|
481
|
+
const fileName = dest !== void 0 ? validateB2SyncPathInPrefix(uploadPrefix, dest) : `${uploadPrefix}${relPath}`;
|
|
482
|
+
if (rootContext !== void 0) await assertLocalRootContextCurrent(rootContext, relPath, { allowSymlinkRoot: true });
|
|
483
|
+
const targetPath = rootContext === void 0 ? await resolveContainedLocalPath(root, source.relativePath, absPath) : await resolveContainedLocalPath(rootContext.realPath, source.relativePath);
|
|
484
|
+
throwIfAborted(signal);
|
|
485
|
+
const fileSource = await createValidatedUploadFileSource(source, targetPath);
|
|
486
|
+
throwIfAborted(signal);
|
|
487
|
+
const serverSideEncryption = config.options.encryptionProvider?.getSettingForUpload(fileName, fileSource.size);
|
|
488
|
+
await bucket.upload({
|
|
489
|
+
fileName,
|
|
490
|
+
source: fileSource,
|
|
491
|
+
...serverSideEncryption !== void 0 ? { serverSideEncryption } : {},
|
|
492
|
+
...signal !== void 0 ? { signal } : {}
|
|
493
|
+
});
|
|
494
|
+
});
|
|
495
|
+
},
|
|
496
|
+
download(source, scannedDest) {
|
|
497
|
+
const bucket = downConfig.bucket;
|
|
498
|
+
assertBucket(bucket, "download");
|
|
499
|
+
return new require_index.DownloadAction(source.relativePath, source.size, async (relPath, signal) => {
|
|
500
|
+
const rootContext = localRootContexts.dest;
|
|
501
|
+
const root = rootContext?.root ?? downConfig.dest.root ?? "";
|
|
502
|
+
require_path_safety.safeRelativePathSegments(relPath);
|
|
503
|
+
const b2FileName = sourceB2Prefix === void 0 ? source.selectedVersion.fileName : validateB2SyncPathInPrefix(sourceB2Prefix, source, "read");
|
|
504
|
+
const idleTimeoutMillis = normalizeDownloadIdleTimeoutMillis(config.options.downloadIdleTimeoutMillis);
|
|
505
|
+
const expectedBytes = assertValidB2ContentLength(source.selectedVersion.contentLength);
|
|
506
|
+
if (rootContext !== void 0) await assertLocalRootContextCurrent(rootContext, relPath, { allowSymlinkRoot: false });
|
|
507
|
+
await ensureLocalSyncRootDirectory(root, relPath);
|
|
508
|
+
const serverSideEncryption = toSseCDownloadKey(config.options.encryptionProvider?.getSettingForDownload(source.selectedVersion));
|
|
509
|
+
const result = await bucket.file(b2FileName).downloadById(source.selectedVersion.fileId, {
|
|
510
|
+
...serverSideEncryption !== void 0 ? { serverSideEncryption } : {},
|
|
511
|
+
...signal !== void 0 ? { signal } : {}
|
|
512
|
+
});
|
|
513
|
+
try {
|
|
514
|
+
await require_local_file_io.writeLocalStreamInsideRoot(root, relPath, result.body, {
|
|
515
|
+
expectedBytes,
|
|
516
|
+
...scannedDest !== void 0 ? { expectedDestination: scannedDest } : {},
|
|
517
|
+
idleTimeoutMillis,
|
|
518
|
+
...signal !== void 0 ? { signal } : {}
|
|
519
|
+
});
|
|
520
|
+
} catch (err) {
|
|
521
|
+
await cancelReadableStreamBody(result.body, err);
|
|
522
|
+
throw err;
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
},
|
|
526
|
+
copy(source, destRelativePath) {
|
|
527
|
+
return copyToB2Key(source, `${uploadPrefix}${destRelativePath}`);
|
|
528
|
+
},
|
|
529
|
+
copyB2Path(source, dest) {
|
|
530
|
+
return copyToB2Key(source, validateB2SyncPathInPrefix(uploadPrefix, dest));
|
|
531
|
+
},
|
|
532
|
+
hide(path) {
|
|
533
|
+
const bucket = upConfig.bucket ?? downConfig.bucket;
|
|
534
|
+
assertBucket(bucket, "hide");
|
|
535
|
+
return new require_index.HideAction(path, async (_relPath, signal) => {
|
|
536
|
+
await bucket.hideFile(`${uploadPrefix}${path}`, signal === void 0 ? void 0 : { signal });
|
|
537
|
+
});
|
|
538
|
+
},
|
|
539
|
+
hideB2Path(path) {
|
|
540
|
+
const bucket = upConfig.bucket ?? downConfig.bucket;
|
|
541
|
+
assertBucket(bucket, "hide");
|
|
542
|
+
const b2FileName = validateB2SyncPathInPrefix(uploadPrefix, path);
|
|
543
|
+
return new require_index.HideAction(path.relativePath, async (_relPath, signal) => {
|
|
544
|
+
await bucket.hideFile(b2FileName, signal === void 0 ? void 0 : { signal });
|
|
545
|
+
});
|
|
546
|
+
},
|
|
547
|
+
deleteRemote(path) {
|
|
548
|
+
const bucket = upConfig.bucket ?? downConfig.bucket;
|
|
549
|
+
assertBucket(bucket, "delete");
|
|
550
|
+
const b2FileName = validateB2SyncPathInPrefix(uploadPrefix, path);
|
|
551
|
+
return new require_index.DeleteRemoteAction(path.relativePath, path.selectedVersion.fileId, async (fileId$1, _fileName, signal) => {
|
|
552
|
+
await bucket.deleteFileVersion(b2FileName, require_ids.fileId(fileId$1), signal === void 0 ? void 0 : { signal });
|
|
553
|
+
});
|
|
554
|
+
},
|
|
555
|
+
deleteLocal(path) {
|
|
556
|
+
const rootContext = localRootContexts.dest;
|
|
557
|
+
const root = rootContext?.root ?? localSyncRoot(downConfig.dest);
|
|
558
|
+
return new require_index.DeleteLocalAction(path.relativePath, path.absolutePath, async (absPath, signal) => {
|
|
559
|
+
signal?.throwIfAborted();
|
|
560
|
+
if (absPath !== path.absolutePath) throw new Error(`Refusing to delete outside sync root: ${path.relativePath}`);
|
|
561
|
+
signal?.throwIfAborted();
|
|
562
|
+
try {
|
|
563
|
+
if (rootContext !== void 0) await assertLocalRootContextCurrent(rootContext, path.relativePath, { allowSymlinkRoot: false });
|
|
564
|
+
await require_local_file_io.deleteLocalFileInsideRoot(root, path);
|
|
565
|
+
} catch (err) {
|
|
566
|
+
if (isLocalDeleteSafetyError(err)) throw err;
|
|
567
|
+
throw new Error(`failed to delete local file: ${require_filesystem_errors.localFilesystemErrorReason(err)}`);
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
},
|
|
571
|
+
removeOrphan(dest) {
|
|
572
|
+
return bucketIsLocked ? factory.hideB2Path?.(dest) ?? factory.hide(dest.relativePath) : factory.deleteRemote(dest);
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
function copyToB2Key(source, targetPath) {
|
|
576
|
+
const bucket = upConfig.bucket;
|
|
577
|
+
assertBucket(bucket, "copy");
|
|
578
|
+
return new require_index.CopyAction(source.relativePath, source.size, async (_relPath, signal) => {
|
|
579
|
+
if (sourceB2Prefix !== void 0) validateB2SyncPathInPrefix(sourceB2Prefix, source, "read");
|
|
580
|
+
const destinationServerSideEncryption = config.options.encryptionProvider?.getSettingForUpload(targetPath, source.size);
|
|
581
|
+
const sourceServerSideEncryption = toSseCEncryptionSetting(config.options.encryptionProvider?.getSettingForDownload(source.selectedVersion));
|
|
582
|
+
await bucket.copyFile({
|
|
583
|
+
sourceFileId: source.selectedVersion.fileId,
|
|
584
|
+
fileName: targetPath,
|
|
585
|
+
...destinationServerSideEncryption !== void 0 ? { destinationServerSideEncryption } : {},
|
|
586
|
+
...sourceServerSideEncryption !== void 0 ? { sourceServerSideEncryption } : {},
|
|
587
|
+
...signal !== void 0 ? { signal } : {}
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
return factory;
|
|
592
|
+
}
|
|
593
|
+
async function createValidatedUploadFileSource(source, absolutePath) {
|
|
594
|
+
try {
|
|
595
|
+
const fileSource = await require_file_source.FileSource.fromPath(absolutePath);
|
|
596
|
+
await require_local_file_io.validateScannedLocalFile({
|
|
597
|
+
...source,
|
|
598
|
+
absolutePath
|
|
599
|
+
});
|
|
600
|
+
return fileSource;
|
|
601
|
+
} catch (err) {
|
|
602
|
+
throw normalizeLocalUploadSourceError(err);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
function normalizeLocalUploadSourceError(err) {
|
|
606
|
+
if (err instanceof Error && err.message.startsWith("local file changed before upload")) return err;
|
|
607
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
608
|
+
if (message.includes("not a regular file")) return /* @__PURE__ */ new Error("local file changed before upload: not a regular file");
|
|
609
|
+
if (message.includes("changed") || message.includes("modified")) return /* @__PURE__ */ new Error("local file changed before upload");
|
|
610
|
+
return /* @__PURE__ */ new Error(`local file changed before upload: ${require_error_reason.sanitizeErrorReason(err)}`);
|
|
611
|
+
}
|
|
612
|
+
function localSyncRoot(folder) {
|
|
613
|
+
return folder?.type === "local" ? folder.root : "";
|
|
614
|
+
}
|
|
615
|
+
function b2FolderRawPrefix(folder) {
|
|
616
|
+
if (folder?.type !== "b2") return void 0;
|
|
617
|
+
const rawPrefix = folder.rawPrefix;
|
|
618
|
+
return typeof rawPrefix === "string" ? rawPrefix : void 0;
|
|
619
|
+
}
|
|
620
|
+
function validateB2SourcePairPrefix(pair, config) {
|
|
621
|
+
const [source] = pair;
|
|
622
|
+
if (config.source.type !== "b2" || source === null || !isB2SyncPath(source)) return;
|
|
623
|
+
const sourcePrefix = b2FolderRawPrefix(config.source);
|
|
624
|
+
if (sourcePrefix === void 0) return;
|
|
625
|
+
validateB2SyncPathInPrefix(sourcePrefix, source, "read");
|
|
626
|
+
}
|
|
627
|
+
function b2ReadableRawPrefixes(config) {
|
|
628
|
+
const prefixes = [];
|
|
629
|
+
const sourcePrefix = b2FolderRawPrefix(config.source);
|
|
630
|
+
if (config.source.type === "b2") prefixes.push(sourcePrefix ?? "");
|
|
631
|
+
const upConfig = config;
|
|
632
|
+
if (config.dest.type === "b2") prefixes.push(upConfig.prefix ?? b2FolderRawPrefix(config.dest) ?? "");
|
|
633
|
+
return [...new Set(prefixes.map((prefix) => require_prefix.asRawB2KeyPrefix(prefix)))];
|
|
634
|
+
}
|
|
635
|
+
function validateB2SyncPathInAnyPrefix(prefixes, path, operation) {
|
|
636
|
+
let firstError = /* @__PURE__ */ new Error(`Refusing to ${operation} B2 key: ${path.relativePath}`);
|
|
637
|
+
for (const prefix of prefixes) try {
|
|
638
|
+
return validateB2SyncPathInPrefix(prefix, path, operation);
|
|
639
|
+
} catch (err) {
|
|
640
|
+
if (err instanceof Error) firstError = err;
|
|
641
|
+
}
|
|
642
|
+
throw firstError;
|
|
643
|
+
}
|
|
644
|
+
function validateB2SyncPathInPrefix(prefix, path, operation = "mutate") {
|
|
645
|
+
const fileName = path.selectedVersion.fileName;
|
|
646
|
+
if (!fileName.startsWith(prefix)) throw new Error(`Refusing to ${operation} B2 key outside configured prefix: ${path.relativePath}`);
|
|
647
|
+
if (require_prefix.b2KeyToRelativePathUnderPrefix(prefix, fileName) !== path.relativePath) throw new Error(`Refusing to ${operation} mismatched B2 key for sync path: ${path.relativePath}`);
|
|
648
|
+
return fileName;
|
|
649
|
+
}
|
|
650
|
+
function isB2SyncPath(path) {
|
|
651
|
+
return "selectedVersion" in path;
|
|
652
|
+
}
|
|
653
|
+
function throwIfAborted(signal) {
|
|
654
|
+
if (signal?.aborted === true) throw signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
655
|
+
}
|
|
656
|
+
async function cancelReadableStreamBody(body, reason) {
|
|
657
|
+
if (body.locked) return;
|
|
658
|
+
try {
|
|
659
|
+
await body.cancel(reason);
|
|
660
|
+
} catch {}
|
|
661
|
+
}
|
|
662
|
+
async function assertLocalRootContextCurrent(context, relativePath, options) {
|
|
663
|
+
if (context.identity === void 0) return;
|
|
664
|
+
const { lstat, realpath, stat } = await import("node:fs/promises");
|
|
665
|
+
let currentRealPath;
|
|
666
|
+
try {
|
|
667
|
+
const rootLinkStats = await lstat(context.root);
|
|
668
|
+
if (!options.allowSymlinkRoot && rootLinkStats.isSymbolicLink()) throw new Error(`Refusing to access sync root through symlink: ${relativePath}`);
|
|
669
|
+
currentRealPath = await realpath(context.root);
|
|
670
|
+
} catch (err) {
|
|
671
|
+
if (err instanceof Error && err.message.startsWith("Refusing to access sync root")) throw err;
|
|
672
|
+
throw new Error(`Local sync root changed before filesystem action: ${relativePath}`);
|
|
673
|
+
}
|
|
674
|
+
if (currentRealPath !== context.realPath) throw new Error(`Local sync root changed before filesystem action: ${relativePath}`);
|
|
675
|
+
let currentStats;
|
|
676
|
+
try {
|
|
677
|
+
currentStats = await stat(context.realPath);
|
|
678
|
+
} catch {
|
|
679
|
+
throw new Error(`Local sync root changed before filesystem action: ${relativePath}`);
|
|
680
|
+
}
|
|
681
|
+
if (!currentStats.isDirectory() || currentStats.dev !== context.identity.deviceId || currentStats.ino !== context.identity.inode) throw new Error(`Local sync root changed before filesystem action: ${relativePath}`);
|
|
682
|
+
}
|
|
683
|
+
async function ensureLocalSyncRootDirectory(root, relativePath) {
|
|
684
|
+
if (root === "") throw new Error("Local sync root required for filesystem mutation");
|
|
685
|
+
const { lstat, mkdir } = await import("node:fs/promises");
|
|
686
|
+
const { resolve } = await import("node:path");
|
|
687
|
+
const safeRoot = resolve(root);
|
|
688
|
+
try {
|
|
689
|
+
const stats = await lstat(safeRoot);
|
|
690
|
+
if (stats.isSymbolicLink()) throw new Error(`Refusing to access sync root through symlink: ${relativePath}`);
|
|
691
|
+
if (!stats.isDirectory()) throw new Error(`Local sync root is not a directory: ${relativePath}`);
|
|
692
|
+
return;
|
|
693
|
+
} catch (error) {
|
|
694
|
+
if (!isNotFoundError(error)) throw error;
|
|
695
|
+
}
|
|
696
|
+
await mkdir(safeRoot, { recursive: true });
|
|
697
|
+
await assertLocalRootHasNoSymlink(safeRoot, relativePath);
|
|
698
|
+
}
|
|
699
|
+
function bufferScanEvent(buffer, event, direction, scanSide) {
|
|
700
|
+
if (event.type === "skip" && event.reason === "filesystem-error") buffer.fatalFilesystemErrorMessage ??= event.message;
|
|
701
|
+
if (sourceSkipMakesInventoryIncomplete(event, direction, scanSide)) buffer.sourceInventoryIncompleteMessage ??= sourceInventoryIncompleteMessage(direction);
|
|
702
|
+
if (buffer.events.length < MAX_BUFFERED_SCAN_EVENTS) buffer.events.push(event);
|
|
703
|
+
else buffer.dropped++;
|
|
704
|
+
}
|
|
705
|
+
function* drainScanEvents(buffer) {
|
|
706
|
+
while (buffer.events.length > 0) {
|
|
707
|
+
const event = buffer.events.shift();
|
|
708
|
+
if (event) yield event;
|
|
709
|
+
}
|
|
710
|
+
if (buffer.dropped > 0) {
|
|
711
|
+
yield {
|
|
712
|
+
type: "skip",
|
|
713
|
+
path: "",
|
|
714
|
+
size: 0,
|
|
715
|
+
reason: "scan-skip-overflow",
|
|
716
|
+
message: `${buffer.dropped} scanner skip event(s) were omitted after ${MAX_BUFFERED_SCAN_EVENTS} buffered diagnostics`
|
|
717
|
+
};
|
|
718
|
+
buffer.dropped = 0;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
function scanHadFilesystemError(scanEvents) {
|
|
722
|
+
return scanEvents.fatalFilesystemErrorMessage !== void 0;
|
|
723
|
+
}
|
|
724
|
+
function sourceInventoryIncomplete(scanEvents) {
|
|
725
|
+
return scanEvents.sourceInventoryIncompleteMessage !== void 0;
|
|
726
|
+
}
|
|
727
|
+
function scanFilesystemError(scanEvents) {
|
|
728
|
+
return scanEvents.fatalFilesystemErrorMessage === void 0 ? void 0 : new Error(scanEvents.fatalFilesystemErrorMessage);
|
|
729
|
+
}
|
|
730
|
+
function sourceSkipMakesInventoryIncomplete(event, direction, scanSide) {
|
|
731
|
+
if (scanSide !== "source" || event.type !== "skip") return false;
|
|
732
|
+
if (direction === "local-to-b2") return event.reason === "unsafe-name" || event.reason === "stale-download-partial" || event.reason === "path-too-long-for-regexp";
|
|
733
|
+
if (direction === "b2-to-local" || direction === "b2-to-b2") return event.reason === "unsafe-name" || event.reason === "local-unsafe-name" || event.reason === "relative-path-collision" || event.reason === "local-path-collision" || event.reason === "path-too-long-for-regexp";
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
function sourceInventoryIncompleteMessage(direction) {
|
|
737
|
+
return direction === "local-to-b2" ? "not removed because the source scan skipped local paths" : "not removed because the source scan skipped unsafe B2 names";
|
|
738
|
+
}
|
|
739
|
+
function isLocalDeleteSafetyError(err) {
|
|
740
|
+
if (!(err instanceof Error)) return false;
|
|
741
|
+
return err.message === "Local sync root required for filesystem mutation" || err.message.startsWith("Local sync root changed before filesystem action: ") || err.message.startsWith("Refusing to ") || err.message.startsWith("Local sync root is not a directory: ") || err.message.startsWith("unsafe local delete path: ");
|
|
742
|
+
}
|
|
743
|
+
async function resolveContainedLocalPath(root, relativePath, absolutePath) {
|
|
744
|
+
if (root === "") throw new Error("Local sync root required for filesystem mutation");
|
|
745
|
+
const { isAbsolute, relative, resolve, sep } = await import("node:path");
|
|
746
|
+
const safeRoot = resolve(root);
|
|
747
|
+
const target = absolutePath === void 0 ? resolve(safeRoot, relativePath) : resolve(absolutePath);
|
|
748
|
+
const pathFromRoot = relative(safeRoot, target);
|
|
749
|
+
/* v8 ignore next -- defense-in-depth after prior no-follow and symlink checks. */
|
|
750
|
+
if (pathFromRoot === ".." || pathFromRoot.startsWith(`..${sep}`) || isAbsolute(pathFromRoot)) throw new Error(`Refusing to access path outside sync root: ${relativePath}`);
|
|
751
|
+
await assertLocalRootHasNoSymlink(safeRoot, relativePath);
|
|
752
|
+
await assertPathHasNoSymlinkComponents(safeRoot, pathFromRoot, relativePath);
|
|
753
|
+
return target;
|
|
754
|
+
}
|
|
755
|
+
async function assertLocalRootHasNoSymlink(safeRoot, relativePath) {
|
|
756
|
+
const { lstat } = await import("node:fs/promises");
|
|
757
|
+
try {
|
|
758
|
+
if ((await lstat(safeRoot)).isSymbolicLink()) throw new Error(`Refusing to access sync root through symlink: ${relativePath}`);
|
|
759
|
+
} catch (error) {
|
|
760
|
+
if (isNotFoundError(error)) return;
|
|
761
|
+
throw error;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
async function assertPathHasNoSymlinkComponents(safeRoot, pathFromRoot, relativePath) {
|
|
765
|
+
if (pathFromRoot === "") return;
|
|
766
|
+
const { lstat } = await import("node:fs/promises");
|
|
767
|
+
const { join, sep } = await import("node:path");
|
|
768
|
+
let current = safeRoot;
|
|
769
|
+
for (const segment of pathFromRoot.split(sep)) {
|
|
770
|
+
current = join(current, segment);
|
|
771
|
+
let stats;
|
|
772
|
+
try {
|
|
773
|
+
stats = await lstat(current);
|
|
774
|
+
} catch (error) {
|
|
775
|
+
if (isNotFoundError(error)) return;
|
|
776
|
+
throw error;
|
|
777
|
+
}
|
|
778
|
+
if (stats.isSymbolicLink()) throw new Error(`Refusing to access path through symlink: ${relativePath}`);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
function isNotFoundError(error) {
|
|
782
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
201
783
|
}
|
|
784
|
+
//#endregion
|
|
202
785
|
exports.synchronize = synchronize;
|
|
203
|
-
|
|
786
|
+
exports.synchronizerTestHooks = synchronizerTestHooks;
|
|
787
|
+
|
|
788
|
+
//# sourceMappingURL=synchronizer.cjs.map
|