@backblaze-labs/b2-sdk 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +86 -1
- package/README.md +38 -7
- package/dist/_virtual/_b2-sdk-version-json.cjs +1 -1
- package/dist/_virtual/_b2-sdk-version-json.js +1 -1
- package/dist/auth/file.cjs.map +1 -1
- package/dist/auth/reauth-coalescer.cjs +65 -0
- package/dist/auth/reauth-coalescer.cjs.map +1 -0
- package/dist/auth/reauth-coalescer.d.cts +34 -0
- package/dist/auth/reauth-coalescer.d.cts.map +1 -0
- package/dist/auth/reauth-coalescer.d.ts +34 -0
- package/dist/auth/reauth-coalescer.d.ts.map +1 -0
- package/dist/auth/reauth-coalescer.js +65 -0
- package/dist/auth/reauth-coalescer.js.map +1 -0
- package/dist/backup/client.cjs +206 -0
- package/dist/backup/client.cjs.map +1 -0
- package/dist/backup/client.d.cts +238 -0
- package/dist/backup/client.d.cts.map +1 -0
- package/dist/backup/client.d.ts +238 -0
- package/dist/backup/client.d.ts.map +1 -0
- package/dist/backup/client.js +206 -0
- package/dist/backup/client.js.map +1 -0
- package/dist/backup/index.cjs +15 -0
- package/dist/backup/index.d.cts +22 -0
- package/dist/backup/index.d.cts.map +1 -0
- package/dist/backup/index.d.ts +22 -0
- package/dist/backup/index.d.ts.map +1 -0
- package/dist/backup/index.js +7 -0
- package/dist/backup/raw.cjs +168 -0
- package/dist/backup/raw.cjs.map +1 -0
- package/dist/backup/raw.d.cts +122 -0
- package/dist/backup/raw.d.cts.map +1 -0
- package/dist/backup/raw.d.ts +122 -0
- package/dist/backup/raw.d.ts.map +1 -0
- package/dist/backup/raw.js +168 -0
- package/dist/backup/raw.js.map +1 -0
- package/dist/bucket-validation.cjs +111 -0
- package/dist/bucket-validation.cjs.map +1 -0
- package/dist/bucket-validation.d.cts +27 -0
- package/dist/bucket-validation.d.cts.map +1 -0
- package/dist/bucket-validation.d.ts +27 -0
- package/dist/bucket-validation.d.ts.map +1 -0
- package/dist/bucket-validation.js +109 -0
- package/dist/bucket-validation.js.map +1 -0
- package/dist/bucket.cjs +125 -74
- package/dist/bucket.cjs.map +1 -1
- package/dist/bucket.d.cts +156 -61
- package/dist/bucket.d.cts.map +1 -1
- package/dist/bucket.d.ts +156 -61
- package/dist/bucket.d.ts.map +1 -1
- package/dist/bucket.js +125 -74
- package/dist/bucket.js.map +1 -1
- package/dist/client.cjs +29 -8
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +30 -9
- package/dist/client.d.cts.map +1 -1
- package/dist/client.d.ts +30 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +29 -8
- package/dist/client.js.map +1 -1
- package/dist/copy/large.cjs +5 -3
- package/dist/copy/large.cjs.map +1 -1
- package/dist/copy/large.d.cts.map +1 -1
- package/dist/copy/large.d.ts.map +1 -1
- package/dist/copy/large.js +5 -3
- package/dist/copy/large.js.map +1 -1
- package/dist/download/checksum.cjs +6 -2
- package/dist/download/checksum.cjs.map +1 -1
- package/dist/download/checksum.js +6 -2
- package/dist/download/checksum.js.map +1 -1
- package/dist/download/parallel.cjs +52 -15
- package/dist/download/parallel.cjs.map +1 -1
- package/dist/download/parallel.d.cts +8 -1
- package/dist/download/parallel.d.cts.map +1 -1
- package/dist/download/parallel.d.ts +8 -1
- package/dist/download/parallel.d.ts.map +1 -1
- package/dist/download/parallel.js +52 -15
- package/dist/download/parallel.js.map +1 -1
- package/dist/download/single.cjs +179 -19
- package/dist/download/single.cjs.map +1 -1
- package/dist/download/single.d.cts +10 -4
- package/dist/download/single.d.cts.map +1 -1
- package/dist/download/single.d.ts +10 -4
- package/dist/download/single.d.ts.map +1 -1
- package/dist/download/single.js +179 -19
- package/dist/download/single.js.map +1 -1
- package/dist/errors/index.cjs +196 -3
- package/dist/errors/index.cjs.map +1 -1
- package/dist/errors/index.d.cts +134 -0
- package/dist/errors/index.d.cts.map +1 -1
- package/dist/errors/index.d.ts +134 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +183 -4
- package/dist/errors/index.js.map +1 -1
- package/dist/http/non-idempotent-mutations.cjs +38 -0
- package/dist/http/non-idempotent-mutations.cjs.map +1 -0
- package/dist/http/non-idempotent-mutations.d.cts +25 -0
- package/dist/http/non-idempotent-mutations.d.cts.map +1 -0
- package/dist/http/non-idempotent-mutations.d.ts +25 -0
- package/dist/http/non-idempotent-mutations.d.ts.map +1 -0
- package/dist/http/non-idempotent-mutations.js +35 -0
- package/dist/http/non-idempotent-mutations.js.map +1 -0
- package/dist/http/retry.cjs +1 -1
- package/dist/http/retry.cjs.map +1 -1
- package/dist/http/retry.js +1 -1
- package/dist/http/retry.js.map +1 -1
- package/dist/http/transport.cjs +62 -23
- package/dist/http/transport.cjs.map +1 -1
- package/dist/http/transport.d.cts +30 -3
- package/dist/http/transport.d.cts.map +1 -1
- package/dist/http/transport.d.ts +30 -3
- package/dist/http/transport.d.ts.map +1 -1
- package/dist/http/transport.js +60 -22
- package/dist/http/transport.js.map +1 -1
- package/dist/http/user-agent.cjs +12 -1
- package/dist/http/user-agent.cjs.map +1 -1
- package/dist/http/user-agent.d.cts +8 -0
- package/dist/http/user-agent.d.cts.map +1 -1
- package/dist/http/user-agent.d.ts +8 -0
- package/dist/http/user-agent.d.ts.map +1 -1
- package/dist/http/user-agent.js +13 -3
- package/dist/http/user-agent.js.map +1 -1
- package/dist/index.cjs +50 -2
- package/dist/index.d.cts +15 -12
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +15 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -10
- package/dist/notifications/index.cjs +3 -0
- package/dist/notifications/index.d.cts +2 -0
- package/dist/notifications/index.d.cts.map +1 -1
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +2 -1
- package/dist/object.cjs +13 -2
- package/dist/object.cjs.map +1 -1
- package/dist/object.d.cts +11 -3
- package/dist/object.d.cts.map +1 -1
- package/dist/object.d.ts +11 -3
- package/dist/object.d.ts.map +1 -1
- package/dist/object.js +13 -2
- package/dist/object.js.map +1 -1
- package/dist/partner/account-info.d.cts +43 -0
- package/dist/partner/account-info.d.cts.map +1 -0
- package/dist/partner/account-info.d.ts +43 -0
- package/dist/partner/account-info.d.ts.map +1 -0
- package/dist/partner/auth-clone.cjs +64 -0
- package/dist/partner/auth-clone.cjs.map +1 -0
- package/dist/partner/auth-clone.d.cts +27 -0
- package/dist/partner/auth-clone.d.cts.map +1 -0
- package/dist/partner/auth-clone.d.ts +27 -0
- package/dist/partner/auth-clone.d.ts.map +1 -0
- package/dist/partner/auth-clone.js +63 -0
- package/dist/partner/auth-clone.js.map +1 -0
- package/dist/partner/auth-core.cjs +156 -0
- package/dist/partner/auth-core.cjs.map +1 -0
- package/dist/partner/auth-core.d.cts +111 -0
- package/dist/partner/auth-core.d.cts.map +1 -0
- package/dist/partner/auth-core.d.ts +111 -0
- package/dist/partner/auth-core.d.ts.map +1 -0
- package/dist/partner/auth-core.js +156 -0
- package/dist/partner/auth-core.js.map +1 -0
- package/dist/partner/auth-shape.cjs +36 -0
- package/dist/partner/auth-shape.cjs.map +1 -0
- package/dist/partner/auth-shape.d.cts +12 -0
- package/dist/partner/auth-shape.d.cts.map +1 -0
- package/dist/partner/auth-shape.d.ts +12 -0
- package/dist/partner/auth-shape.d.ts.map +1 -0
- package/dist/partner/auth-shape.js +36 -0
- package/dist/partner/auth-shape.js.map +1 -0
- package/dist/partner/client.cjs +270 -0
- package/dist/partner/client.cjs.map +1 -0
- package/dist/partner/client.d.cts +357 -0
- package/dist/partner/client.d.cts.map +1 -0
- package/dist/partner/client.d.ts +357 -0
- package/dist/partner/client.d.ts.map +1 -0
- package/dist/partner/client.js +270 -0
- package/dist/partner/client.js.map +1 -0
- package/dist/partner/endpoint-url.cjs +109 -0
- package/dist/partner/endpoint-url.cjs.map +1 -0
- package/dist/partner/endpoint-url.d.cts +74 -0
- package/dist/partner/endpoint-url.d.cts.map +1 -0
- package/dist/partner/endpoint-url.d.ts +74 -0
- package/dist/partner/endpoint-url.d.ts.map +1 -0
- package/dist/partner/endpoint-url.js +106 -0
- package/dist/partner/endpoint-url.js.map +1 -0
- package/dist/partner/in-memory.cjs +135 -0
- package/dist/partner/in-memory.cjs.map +1 -0
- package/dist/partner/in-memory.d.cts +99 -0
- package/dist/partner/in-memory.d.cts.map +1 -0
- package/dist/partner/in-memory.d.ts +99 -0
- package/dist/partner/in-memory.d.ts.map +1 -0
- package/dist/partner/in-memory.js +135 -0
- package/dist/partner/in-memory.js.map +1 -0
- package/dist/partner/index.cjs +27 -0
- package/dist/partner/index.d.cts +32 -0
- package/dist/partner/index.d.cts.map +1 -0
- package/dist/partner/index.d.ts +32 -0
- package/dist/partner/index.d.ts.map +1 -0
- package/dist/partner/index.js +9 -0
- package/dist/partner/raw.cjs +400 -0
- package/dist/partner/raw.cjs.map +1 -0
- package/dist/partner/raw.d.cts +220 -0
- package/dist/partner/raw.d.cts.map +1 -0
- package/dist/partner/raw.d.ts +220 -0
- package/dist/partner/raw.d.ts.map +1 -0
- package/dist/partner/raw.js +398 -0
- package/dist/partner/raw.js.map +1 -0
- package/dist/partner/redaction-placeholders.cjs +10 -0
- package/dist/partner/redaction-placeholders.cjs.map +1 -0
- package/dist/partner/redaction-placeholders.d.cts +5 -0
- package/dist/partner/redaction-placeholders.d.cts.map +1 -0
- package/dist/partner/redaction-placeholders.d.ts +5 -0
- package/dist/partner/redaction-placeholders.d.ts.map +1 -0
- package/dist/partner/redaction-placeholders.js +9 -0
- package/dist/partner/redaction-placeholders.js.map +1 -0
- package/dist/partner/redaction.cjs +292 -0
- package/dist/partner/redaction.cjs.map +1 -0
- package/dist/partner/redaction.d.cts +158 -0
- package/dist/partner/redaction.d.cts.map +1 -0
- package/dist/partner/redaction.d.ts +158 -0
- package/dist/partner/redaction.d.ts.map +1 -0
- package/dist/partner/redaction.js +281 -0
- package/dist/partner/redaction.js.map +1 -0
- package/dist/raw/encoding.cjs +29 -10
- package/dist/raw/encoding.cjs.map +1 -1
- package/dist/raw/encoding.d.cts +3 -2
- package/dist/raw/encoding.d.cts.map +1 -1
- package/dist/raw/encoding.d.ts +3 -2
- package/dist/raw/encoding.d.ts.map +1 -1
- package/dist/raw/encoding.js +29 -10
- package/dist/raw/encoding.js.map +1 -1
- package/dist/raw/index.cjs +131 -44
- package/dist/raw/index.cjs.map +1 -1
- package/dist/raw/index.d.cts +21 -15
- package/dist/raw/index.d.cts.map +1 -1
- package/dist/raw/index.d.ts +21 -15
- package/dist/raw/index.d.ts.map +1 -1
- package/dist/raw/index.js +114 -45
- package/dist/raw/index.js.map +1 -1
- package/dist/raw/url.cjs +111 -0
- package/dist/raw/url.cjs.map +1 -0
- package/dist/raw/url.d.cts +41 -0
- package/dist/raw/url.d.cts.map +1 -0
- package/dist/raw/url.d.ts +41 -0
- package/dist/raw/url.d.ts.map +1 -0
- package/dist/raw/url.js +110 -0
- package/dist/raw/url.js.map +1 -0
- package/dist/s3/sigv4.cjs +15 -10
- package/dist/s3/sigv4.cjs.map +1 -1
- package/dist/s3/sigv4.js +15 -10
- package/dist/s3/sigv4.js.map +1 -1
- package/dist/simulator/index.cjs +1579 -257
- package/dist/simulator/index.cjs.map +1 -1
- package/dist/simulator/index.d.cts +124 -11
- package/dist/simulator/index.d.cts.map +1 -1
- package/dist/simulator/index.d.ts +124 -11
- package/dist/simulator/index.d.ts.map +1 -1
- package/dist/simulator/index.js +1568 -262
- package/dist/simulator/index.js.map +1 -1
- package/dist/simulator/partner-capabilities.cjs +77 -0
- package/dist/simulator/partner-capabilities.cjs.map +1 -0
- package/dist/simulator/partner-capabilities.d.cts +53 -0
- package/dist/simulator/partner-capabilities.d.cts.map +1 -0
- package/dist/simulator/partner-capabilities.d.ts +53 -0
- package/dist/simulator/partner-capabilities.d.ts.map +1 -0
- package/dist/simulator/partner-capabilities.js +73 -0
- package/dist/simulator/partner-capabilities.js.map +1 -0
- package/dist/simulator/partner.cjs +713 -0
- package/dist/simulator/partner.cjs.map +1 -0
- package/dist/simulator/partner.d.cts +186 -0
- package/dist/simulator/partner.d.cts.map +1 -0
- package/dist/simulator/partner.d.ts +186 -0
- package/dist/simulator/partner.d.ts.map +1 -0
- package/dist/simulator/partner.js +713 -0
- package/dist/simulator/partner.js.map +1 -0
- package/dist/simulator/validation.cjs +732 -25
- package/dist/simulator/validation.cjs.map +1 -1
- package/dist/simulator/validation.d.cts +145 -6
- package/dist/simulator/validation.d.cts.map +1 -1
- package/dist/simulator/validation.d.ts +145 -6
- package/dist/simulator/validation.d.ts.map +1 -1
- package/dist/simulator/validation.js +705 -26
- package/dist/simulator/validation.js.map +1 -1
- package/dist/streams/file-source.cjs +2 -2
- package/dist/streams/file-source.cjs.map +1 -1
- package/dist/streams/file-source.js +2 -2
- package/dist/streams/file-source.js.map +1 -1
- package/dist/streams/hash.cjs +246 -13
- package/dist/streams/hash.cjs.map +1 -1
- package/dist/streams/hash.d.cts +37 -12
- package/dist/streams/hash.d.cts.map +1 -1
- package/dist/streams/hash.d.ts +37 -12
- package/dist/streams/hash.d.ts.map +1 -1
- package/dist/streams/hash.js +246 -15
- package/dist/streams/hash.js.map +1 -1
- package/dist/streams/index.cjs +3 -1
- package/dist/streams/index.d.cts +1 -1
- package/dist/streams/index.d.cts.map +1 -1
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.d.ts.map +1 -1
- package/dist/streams/index.js +3 -3
- package/dist/streams/progress.cjs +63 -4
- package/dist/streams/progress.cjs.map +1 -1
- package/dist/streams/progress.d.cts +28 -2
- package/dist/streams/progress.d.cts.map +1 -1
- package/dist/streams/progress.d.ts +28 -2
- package/dist/streams/progress.d.ts.map +1 -1
- package/dist/streams/progress.js +63 -4
- package/dist/streams/progress.js.map +1 -1
- package/dist/streams/source.cjs +2 -1
- package/dist/streams/source.cjs.map +1 -1
- package/dist/streams/source.js +2 -1
- package/dist/streams/source.js.map +1 -1
- package/dist/sync/b2-sha1-reader.cjs +6 -2
- package/dist/sync/b2-sha1-reader.cjs.map +1 -1
- package/dist/sync/b2-sha1-reader.d.cts.map +1 -1
- package/dist/sync/b2-sha1-reader.d.ts.map +1 -1
- package/dist/sync/b2-sha1-reader.js +6 -2
- package/dist/sync/b2-sha1-reader.js.map +1 -1
- package/dist/sync/download-staging.cjs +156 -43
- package/dist/sync/download-staging.cjs.map +1 -1
- package/dist/sync/download-staging.d.cts +26 -2
- package/dist/sync/download-staging.d.cts.map +1 -1
- package/dist/sync/download-staging.d.ts +26 -2
- package/dist/sync/download-staging.d.ts.map +1 -1
- package/dist/sync/download-staging.js +155 -44
- package/dist/sync/download-staging.js.map +1 -1
- package/dist/sync/filters.cjs.map +1 -1
- package/dist/sync/filters.js.map +1 -1
- package/dist/sync/index.d.cts +1 -1
- package/dist/sync/index.d.cts.map +1 -1
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/local-file-io.cjs +15 -6
- package/dist/sync/local-file-io.cjs.map +1 -1
- package/dist/sync/local-file-io.d.cts +3 -0
- package/dist/sync/local-file-io.d.cts.map +1 -1
- package/dist/sync/local-file-io.d.ts +3 -0
- package/dist/sync/local-file-io.d.ts.map +1 -1
- package/dist/sync/local-file-io.js +15 -6
- package/dist/sync/local-file-io.js.map +1 -1
- package/dist/sync/local-sha1.cjs +6 -15
- package/dist/sync/local-sha1.cjs.map +1 -1
- package/dist/sync/local-sha1.d.cts +0 -8
- package/dist/sync/local-sha1.d.cts.map +1 -1
- package/dist/sync/local-sha1.d.ts +0 -8
- package/dist/sync/local-sha1.d.ts.map +1 -1
- package/dist/sync/local-sha1.js +7 -15
- package/dist/sync/local-sha1.js.map +1 -1
- package/dist/sync/pairing.cjs +1 -0
- package/dist/sync/pairing.cjs.map +1 -1
- package/dist/sync/pairing.js +1 -0
- package/dist/sync/pairing.js.map +1 -1
- package/dist/sync/policies/compare.cjs +5 -3
- package/dist/sync/policies/compare.cjs.map +1 -1
- package/dist/sync/policies/compare.d.cts.map +1 -1
- package/dist/sync/policies/compare.d.ts.map +1 -1
- package/dist/sync/policies/compare.js +6 -4
- package/dist/sync/policies/compare.js.map +1 -1
- package/dist/sync/policies/index.cjs +4 -10
- package/dist/sync/policies/index.cjs.map +1 -1
- package/dist/sync/policies/index.js +4 -10
- package/dist/sync/policies/index.js.map +1 -1
- package/dist/sync/scanners/b2.cjs +4 -2
- package/dist/sync/scanners/b2.cjs.map +1 -1
- package/dist/sync/scanners/b2.d.cts.map +1 -1
- package/dist/sync/scanners/b2.d.ts.map +1 -1
- package/dist/sync/scanners/b2.js +4 -2
- package/dist/sync/scanners/b2.js.map +1 -1
- package/dist/sync/scanners/local.cjs +150 -33
- package/dist/sync/scanners/local.cjs.map +1 -1
- package/dist/sync/scanners/local.d.cts +6 -0
- package/dist/sync/scanners/local.d.cts.map +1 -1
- package/dist/sync/scanners/local.d.ts +6 -0
- package/dist/sync/scanners/local.d.ts.map +1 -1
- package/dist/sync/scanners/local.js +150 -33
- package/dist/sync/scanners/local.js.map +1 -1
- package/dist/sync/synchronizer.cjs +79 -31
- package/dist/sync/synchronizer.cjs.map +1 -1
- package/dist/sync/synchronizer.d.cts +1 -0
- package/dist/sync/synchronizer.d.cts.map +1 -1
- package/dist/sync/synchronizer.d.ts +1 -0
- package/dist/sync/synchronizer.d.ts.map +1 -1
- package/dist/sync/synchronizer.js +79 -31
- package/dist/sync/synchronizer.js.map +1 -1
- package/dist/sync/types.d.cts +19 -3
- package/dist/sync/types.d.cts.map +1 -1
- package/dist/sync/types.d.ts +19 -3
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/types/auth.cjs +4 -0
- package/dist/types/auth.cjs.map +1 -1
- package/dist/types/auth.d.cts +4 -0
- package/dist/types/auth.d.cts.map +1 -1
- package/dist/types/auth.d.ts +4 -0
- package/dist/types/auth.d.ts.map +1 -1
- package/dist/types/auth.js +4 -0
- package/dist/types/auth.js.map +1 -1
- package/dist/types/backup.d.cts +85 -0
- package/dist/types/backup.d.cts.map +1 -0
- package/dist/types/backup.d.ts +85 -0
- package/dist/types/backup.d.ts.map +1 -0
- package/dist/types/bucket.cjs +81 -11
- package/dist/types/bucket.cjs.map +1 -1
- package/dist/types/bucket.d.cts +194 -41
- package/dist/types/bucket.d.cts.map +1 -1
- package/dist/types/bucket.d.ts +194 -41
- package/dist/types/bucket.d.ts.map +1 -1
- package/dist/types/bucket.js +67 -12
- package/dist/types/bucket.js.map +1 -1
- package/dist/types/download.cjs +62 -0
- package/dist/types/download.cjs.map +1 -0
- package/dist/types/download.d.cts +100 -16
- package/dist/types/download.d.cts.map +1 -1
- package/dist/types/download.d.ts +100 -16
- package/dist/types/download.d.ts.map +1 -1
- package/dist/types/download.js +61 -0
- package/dist/types/download.js.map +1 -0
- package/dist/types/encryption.cjs +76 -229
- package/dist/types/encryption.cjs.map +1 -1
- package/dist/types/encryption.d.cts +48 -6
- package/dist/types/encryption.d.cts.map +1 -1
- package/dist/types/encryption.d.ts +48 -6
- package/dist/types/encryption.d.ts.map +1 -1
- package/dist/types/encryption.js +74 -229
- package/dist/types/encryption.js.map +1 -1
- package/dist/types/errors.cjs +9 -0
- package/dist/types/errors.cjs.map +1 -1
- package/dist/types/errors.d.cts +1 -1
- package/dist/types/errors.d.cts.map +1 -1
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +9 -0
- package/dist/types/errors.js.map +1 -1
- package/dist/types/file.cjs +3 -0
- package/dist/types/file.cjs.map +1 -1
- package/dist/types/file.d.cts +140 -18
- package/dist/types/file.d.cts.map +1 -1
- package/dist/types/file.d.ts +140 -18
- package/dist/types/file.d.ts.map +1 -1
- package/dist/types/file.js +3 -1
- package/dist/types/file.js.map +1 -1
- package/dist/types/ids.cjs +30 -0
- package/dist/types/ids.cjs.map +1 -1
- package/dist/types/ids.d.cts +32 -0
- package/dist/types/ids.d.cts.map +1 -1
- package/dist/types/ids.d.ts +32 -0
- package/dist/types/ids.d.ts.map +1 -1
- package/dist/types/ids.js +28 -1
- package/dist/types/ids.js.map +1 -1
- package/dist/types/index.d.cts +16 -12
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +16 -12
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/key.d.cts +4 -3
- package/dist/types/key.d.cts.map +1 -1
- package/dist/types/key.d.ts +4 -3
- package/dist/types/key.d.ts.map +1 -1
- package/dist/types/lock.cjs.map +1 -1
- package/dist/types/lock.d.cts +14 -0
- package/dist/types/lock.d.cts.map +1 -1
- package/dist/types/lock.d.ts +14 -0
- package/dist/types/lock.d.ts.map +1 -1
- package/dist/types/lock.js.map +1 -1
- package/dist/types/notifications.cjs +31 -1
- package/dist/types/notifications.cjs.map +1 -1
- package/dist/types/notifications.d.cts +31 -4
- package/dist/types/notifications.d.cts.map +1 -1
- package/dist/types/notifications.d.ts +31 -4
- package/dist/types/notifications.d.ts.map +1 -1
- package/dist/types/notifications.js +30 -2
- package/dist/types/notifications.js.map +1 -1
- package/dist/types/partner.cjs +32 -0
- package/dist/types/partner.cjs.map +1 -0
- package/dist/types/partner.d.cts +386 -0
- package/dist/types/partner.d.cts.map +1 -0
- package/dist/types/partner.d.ts +386 -0
- package/dist/types/partner.d.ts.map +1 -0
- package/dist/types/partner.js +29 -0
- package/dist/types/partner.js.map +1 -0
- package/dist/types/upload.d.cts +35 -18
- package/dist/types/upload.d.cts.map +1 -1
- package/dist/types/upload.d.ts +35 -18
- package/dist/types/upload.d.ts.map +1 -1
- package/dist/upload/abort-scope.cjs +0 -45
- package/dist/upload/abort-scope.cjs.map +1 -1
- package/dist/upload/abort-scope.d.cts +0 -22
- package/dist/upload/abort-scope.d.cts.map +1 -1
- package/dist/upload/abort-scope.d.ts +0 -22
- package/dist/upload/abort-scope.d.ts.map +1 -1
- package/dist/upload/abort-scope.js +1 -44
- package/dist/upload/abort-scope.js.map +1 -1
- package/dist/upload/finish.cjs +3 -8
- package/dist/upload/finish.cjs.map +1 -1
- package/dist/upload/finish.d.cts.map +1 -1
- package/dist/upload/finish.d.ts.map +1 -1
- package/dist/upload/finish.js +1 -6
- package/dist/upload/finish.js.map +1 -1
- package/dist/upload/large.cjs +15 -8
- package/dist/upload/large.cjs.map +1 -1
- package/dist/upload/large.d.cts +31 -8
- package/dist/upload/large.d.cts.map +1 -1
- package/dist/upload/large.d.ts +31 -8
- package/dist/upload/large.d.ts.map +1 -1
- package/dist/upload/large.js +15 -8
- package/dist/upload/large.js.map +1 -1
- package/dist/upload/options.cjs.map +1 -1
- package/dist/upload/options.d.cts +24 -0
- package/dist/upload/options.d.cts.map +1 -1
- package/dist/upload/options.d.ts +24 -0
- package/dist/upload/options.d.ts.map +1 -1
- package/dist/upload/options.js.map +1 -1
- package/dist/upload/resume.cjs +6 -4
- package/dist/upload/resume.cjs.map +1 -1
- package/dist/upload/resume.d.cts +9 -5
- package/dist/upload/resume.d.cts.map +1 -1
- package/dist/upload/resume.d.ts +9 -5
- package/dist/upload/resume.d.ts.map +1 -1
- package/dist/upload/resume.js +6 -4
- package/dist/upload/resume.js.map +1 -1
- package/dist/upload/retry.cjs +25 -13
- package/dist/upload/retry.cjs.map +1 -1
- package/dist/upload/retry.d.cts.map +1 -1
- package/dist/upload/retry.d.ts.map +1 -1
- package/dist/upload/retry.js +25 -13
- package/dist/upload/retry.js.map +1 -1
- package/dist/upload/single.cjs +35 -30
- package/dist/upload/single.cjs.map +1 -1
- package/dist/upload/single.d.cts +12 -0
- package/dist/upload/single.d.cts.map +1 -1
- package/dist/upload/single.d.ts +12 -0
- package/dist/upload/single.d.ts.map +1 -1
- package/dist/upload/single.js +35 -30
- package/dist/upload/single.js.map +1 -1
- package/dist/upload/stream.cjs +18 -5
- package/dist/upload/stream.cjs.map +1 -1
- package/dist/upload/stream.d.cts +12 -0
- package/dist/upload/stream.d.cts.map +1 -1
- package/dist/upload/stream.d.ts +12 -0
- package/dist/upload/stream.d.ts.map +1 -1
- package/dist/upload/stream.js +15 -2
- package/dist/upload/stream.js.map +1 -1
- package/dist/util/abort.cjs +114 -0
- package/dist/util/abort.cjs.map +1 -0
- package/dist/util/abort.d.cts +65 -0
- package/dist/util/abort.d.cts.map +1 -0
- package/dist/util/abort.d.ts +65 -0
- package/dist/util/abort.d.ts.map +1 -0
- package/dist/util/abort.js +109 -0
- package/dist/util/abort.js.map +1 -0
- package/dist/util/defaults.cjs +3 -0
- package/dist/util/defaults.cjs.map +1 -1
- package/dist/util/defaults.d.cts +2 -0
- package/dist/util/defaults.d.cts.map +1 -1
- package/dist/util/defaults.d.ts +2 -0
- package/dist/util/defaults.d.ts.map +1 -1
- package/dist/util/defaults.js +3 -1
- package/dist/util/defaults.js.map +1 -1
- package/dist/util/md5.cjs +211 -0
- package/dist/util/md5.cjs.map +1 -0
- package/dist/util/md5.d.cts +43 -0
- package/dist/util/md5.d.cts.map +1 -0
- package/dist/util/md5.d.ts +43 -0
- package/dist/util/md5.d.ts.map +1 -0
- package/dist/util/md5.js +209 -0
- package/dist/util/md5.js.map +1 -0
- package/dist/util/normalize.cjs +5 -5
- package/dist/util/normalize.cjs.map +1 -1
- package/dist/util/normalize.d.cts +7 -7
- package/dist/util/normalize.d.cts.map +1 -1
- package/dist/util/normalize.d.ts +7 -7
- package/dist/util/normalize.d.ts.map +1 -1
- package/dist/util/normalize.js +5 -5
- package/dist/util/normalize.js.map +1 -1
- package/dist/util/paginator.cjs +7 -1
- package/dist/util/paginator.cjs.map +1 -1
- package/dist/util/paginator.d.cts +3 -1
- package/dist/util/paginator.d.cts.map +1 -1
- package/dist/util/paginator.d.ts +3 -1
- package/dist/util/paginator.d.ts.map +1 -1
- package/dist/util/paginator.js +7 -1
- package/dist/util/paginator.js.map +1 -1
- package/dist/version.cjs +56 -4
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.cts +53 -4
- package/dist/version.d.cts.map +1 -1
- package/dist/version.d.ts +53 -4
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +52 -5
- package/dist/version.js.map +1 -1
- package/package.json +47 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-sha1.cjs","names":[],"sources":["../../src/sync/local-sha1.ts"],"sourcesContent":["import { IncrementalSha1 } from '../streams/hash.ts'\nimport { sanitizeErrorReason } from '../util/error-reason.ts'\nimport {
|
|
1
|
+
{"version":3,"file":"local-sha1.cjs","names":[],"sources":["../../src/sync/local-sha1.ts"],"sourcesContent":["import { IncrementalSha1 } from '../streams/hash.ts'\nimport { sanitizeErrorReason } from '../util/error-reason.ts'\nimport { assertSameScannedRegularFile } from './local-file-identity.ts'\nimport { normalizeSha1TimeoutMillis } from './sha1-options.ts'\nimport type { LocalSyncPath } from './types.ts'\n\n/** Options for reading a local file SHA-1 digest. */\nexport interface LocalSha1ReadOptions {\n /**\n * Maximum milliseconds to allow without filesystem progress while hashing.\n * Defaults to 30 seconds.\n */\n readonly timeoutMillis?: number\n}\n\n/** Reads a local file and returns its SHA-1 digest, or null when unavailable. */\nexport type LocalSha1Reader = (\n path: LocalSyncPath,\n signal?: AbortSignal,\n options?: LocalSha1ReadOptions,\n) => Promise<string | null>\n\n/**\n * Formats a hash error for public sync events without leaking filesystem paths.\n *\n * @param error - Error thrown while hashing.\n *\n * @returns A sanitized reason suitable for event messages.\n */\nexport function formatHashError(error: Error): string {\n return sanitizeErrorReason(error)\n}\n\n/**\n * Reads a local file and computes its SHA-1 digest with non-regular-file rejection,\n * scanned-size bounds, abort support, and an idle/no-progress timeout.\n *\n * @param path - Local sync path to hash.\n * @param signal - Optional abort signal.\n * @param options - Optional idle timeout override.\n *\n * @returns The lowercase SHA-1 digest of the file bytes.\n */\nexport async function readLocalSha1File(\n path: LocalSyncPath,\n signal?: AbortSignal,\n options: LocalSha1ReadOptions = {},\n): Promise<string> {\n const { constants } = await import('node:fs')\n const { lstat, open } = await import('node:fs/promises')\n const timeoutMillis = normalizeSha1TimeoutMillis(options.timeoutMillis)\n const flags = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0)\n const hash = new IncrementalSha1()\n let stream: (AsyncIterable<Uint8Array> & { destroy(error?: Error): void }) | undefined\n let file: Awaited<ReturnType<typeof open>> | undefined\n let timeout: ReturnType<typeof setTimeout> | undefined\n\n function armTimeout(onTimeout: () => void): void {\n if (timeout !== undefined) clearTimeout(timeout)\n timeout = setTimeout(onTimeout, timeoutMillis)\n }\n\n try {\n signal?.throwIfAborted()\n\n const preOpenStat = await withTimeout(\n lstat(path.absolutePath),\n timeoutMillis,\n 'sha1 file status',\n )\n assertSameScannedRegularFile(preOpenStat, path, 'sha1 comparison')\n\n file = await openWithTimeout(open(path.absolutePath, flags), timeoutMillis)\n\n const postOpenStat = await withTimeout(\n lstat(path.absolutePath),\n timeoutMillis,\n 'sha1 file status',\n )\n assertSameScannedRegularFile(postOpenStat, path, 'sha1 comparison')\n\n const stat = await withTimeout(file.stat(), timeoutMillis, 'sha1 file status')\n assertSameScannedRegularFile(stat, path, 'sha1 comparison')\n\n stream = file.createReadStream({\n ...(path.size > 0 ? { start: 0, end: path.size - 1 } : {}),\n ...(signal !== undefined ? { signal } : {}),\n })\n\n let bytesRead = 0\n /* v8 ignore next 3 -- idle-timeout firing is timing-dependent in filesystem tests */\n armTimeout(() => {\n stream?.destroy(new Error(`sha1 read stalled for ${timeoutMillis} ms`))\n })\n for await (const chunk of stream) {\n bytesRead += chunk.byteLength\n await hash.update(chunk)\n /* v8 ignore next 3 -- idle-timeout firing is timing-dependent in filesystem tests */\n armTimeout(() => {\n stream?.destroy(new Error(`sha1 read stalled for ${timeoutMillis} ms`))\n })\n }\n\n /* v8 ignore next -- defensive TOCTOU guard after the bounded stream completes */\n if (bytesRead !== path.size) throw new Error('file changed during sha1 comparison')\n return hash.digest()\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n stream?.destroy()\n await file?.close().catch(() => {})\n }\n}\n\n/* v8 ignore start -- defensive stale-filesystem stall handling is not portable to trigger */\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMillis: number,\n operation: string,\n): Promise<T> {\n let timeout: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n reject(new Error(`${operation} stalled for ${timeoutMillis} ms`))\n }, timeoutMillis)\n }),\n ])\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n }\n}\n\nasync function openWithTimeout<T extends { close(): Promise<void> }>(\n promise: Promise<T>,\n timeoutMillis: number,\n): Promise<T> {\n let timedOut = false\n const tracked = promise.then(\n (file) => {\n if (timedOut) void file.close().catch(() => {})\n return file\n },\n (err: unknown) => {\n throw err\n },\n )\n\n try {\n return await withTimeout(tracked, timeoutMillis, 'sha1 file open')\n } catch (err) {\n timedOut = true\n throw err\n }\n}\n/* v8 ignore stop */\n"],"mappings":";;;;;;;;;;;;AA6BA,SAAgB,gBAAgB,OAAsB;CACpD,OAAO,qBAAA,oBAAoB,KAAK;AAClC;;;;;;;;;;;AAYA,eAAsB,kBACpB,MACA,QACA,UAAgC,CAAC,GAChB;CACjB,MAAM,EAAE,cAAc,MAAM,OAAO;CACnC,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO;CACrC,MAAM,gBAAgB,qBAAA,2BAA2B,QAAQ,aAAa;CACtE,MAAM,QAAQ,UAAU,YAAY,UAAU,cAAc,MAAM,UAAU,cAAc;CAC1F,MAAM,OAAO,IAAI,aAAA,gBAAgB;CACjC,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,SAAS,WAAW,WAA6B;EAC/C,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;EAC/C,UAAU,WAAW,WAAW,aAAa;CAC/C;CAEA,IAAI;EACF,QAAQ,eAAe;EAEvB,MAAM,cAAc,MAAM,YACxB,MAAM,KAAK,YAAY,GACvB,eACA,kBACF;EACA,4BAAA,6BAA6B,aAAa,MAAM,iBAAiB;EAEjE,OAAO,MAAM,gBAAgB,KAAK,KAAK,cAAc,KAAK,GAAG,aAAa;EAE1E,MAAM,eAAe,MAAM,YACzB,MAAM,KAAK,YAAY,GACvB,eACA,kBACF;EACA,4BAAA,6BAA6B,cAAc,MAAM,iBAAiB;EAElE,MAAM,OAAO,MAAM,YAAY,KAAK,KAAK,GAAG,eAAe,kBAAkB;EAC7E,4BAAA,6BAA6B,MAAM,MAAM,iBAAiB;EAE1D,SAAS,KAAK,iBAAiB;GAC7B,GAAI,KAAK,OAAO,IAAI;IAAE,OAAO;IAAG,KAAK,KAAK,OAAO;GAAE,IAAI,CAAC;GACxD,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;EAC3C,CAAC;EAED,IAAI,YAAY;;EAEhB,iBAAiB;GACf,QAAQ,wBAAQ,IAAI,MAAM,yBAAyB,cAAc,IAAI,CAAC;EACxE,CAAC;EACD,WAAW,MAAM,SAAS,QAAQ;GAChC,aAAa,MAAM;GACnB,MAAM,KAAK,OAAO,KAAK;;GAEvB,iBAAiB;IACf,QAAQ,wBAAQ,IAAI,MAAM,yBAAyB,cAAc,IAAI,CAAC;GACxE,CAAC;EACH;;EAGA,IAAI,cAAc,KAAK,MAAM,MAAM,IAAI,MAAM,qCAAqC;EAClF,OAAO,KAAK,OAAO;CACrB,UAAU;EACR,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;EAC/C,QAAQ,QAAQ;EAChB,MAAM,MAAM,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;CACpC;AACF;;AAGA,eAAe,YACb,SACA,eACA,WACY;CACZ,IAAI;CACJ,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CACxB,SACA,IAAI,SAAgB,GAAG,WAAW;GAChC,UAAU,iBAAiB;IACzB,uBAAO,IAAI,MAAM,GAAG,UAAU,eAAe,cAAc,IAAI,CAAC;GAClE,GAAG,aAAa;EAClB,CAAC,CACH,CAAC;CACH,UAAU;EACR,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;CACjD;AACF;AAEA,eAAe,gBACb,SACA,eACY;CACZ,IAAI,WAAW;CACf,MAAM,UAAU,QAAQ,MACrB,SAAS;EACR,IAAI,UAAU,KAAU,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;EAC9C,OAAO;CACT,IACC,QAAiB;EAChB,MAAM;CACR,CACF;CAEA,IAAI;EACF,OAAO,MAAM,YAAY,SAAS,eAAe,gBAAgB;CACnE,SAAS,KAAK;EACZ,WAAW;EACX,MAAM;CACR;AACF"}
|
|
@@ -17,14 +17,6 @@ export type LocalSha1Reader = (path: LocalSyncPath, signal?: AbortSignal, option
|
|
|
17
17
|
* @returns A sanitized reason suitable for event messages.
|
|
18
18
|
*/
|
|
19
19
|
export declare function formatHashError(error: Error): string;
|
|
20
|
-
/**
|
|
21
|
-
* Returns whether an error represents an abort.
|
|
22
|
-
*
|
|
23
|
-
* @param err - Unknown thrown value.
|
|
24
|
-
*
|
|
25
|
-
* @returns True for AbortError values.
|
|
26
|
-
*/
|
|
27
|
-
export declare function isAbortError(err: unknown): boolean;
|
|
28
20
|
/**
|
|
29
21
|
* Reads a local file and computes its SHA-1 digest with non-regular-file rejection,
|
|
30
22
|
* scanned-size bounds, abort support, and an idle/no-progress timeout.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-sha1.d.ts","sourceRoot":"","sources":["../../src/sync/local-sha1.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"local-sha1.d.ts","sourceRoot":"","sources":["../../src/sync/local-sha1.js"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,qDAAqD;AACrD,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAChC;AAED,iFAAiF;AACjF,MAAM,MAAM,eAAe,GAAG,CAC5B,IAAI,EAAE,aAAa,EACnB,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,oBAAoB,KAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;AAE3B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAEpD;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,aAAa,EACnB,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,CAAC,CAgEjB"}
|
|
@@ -17,14 +17,6 @@ export type LocalSha1Reader = (path: LocalSyncPath, signal?: AbortSignal, option
|
|
|
17
17
|
* @returns A sanitized reason suitable for event messages.
|
|
18
18
|
*/
|
|
19
19
|
export declare function formatHashError(error: Error): string;
|
|
20
|
-
/**
|
|
21
|
-
* Returns whether an error represents an abort.
|
|
22
|
-
*
|
|
23
|
-
* @param err - Unknown thrown value.
|
|
24
|
-
*
|
|
25
|
-
* @returns True for AbortError values.
|
|
26
|
-
*/
|
|
27
|
-
export declare function isAbortError(err: unknown): boolean;
|
|
28
20
|
/**
|
|
29
21
|
* Reads a local file and computes its SHA-1 digest with non-regular-file rejection,
|
|
30
22
|
* scanned-size bounds, abort support, and an idle/no-progress timeout.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-sha1.d.ts","sourceRoot":"","sources":["../../src/sync/local-sha1.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"local-sha1.d.ts","sourceRoot":"","sources":["../../src/sync/local-sha1.js"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,qDAAqD;AACrD,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAChC;AAED,iFAAiF;AACjF,MAAM,MAAM,eAAe,GAAG,CAC5B,IAAI,EAAE,aAAa,EACnB,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,oBAAoB,KAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;AAE3B;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAEpD;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,aAAa,EACnB,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,CAAC,CAgEjB"}
|
package/dist/sync/local-sha1.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { IncrementalSha1 } from "../streams/hash.js";
|
|
2
|
-
import { toError } from "../util/to-error.js";
|
|
3
2
|
import { sanitizeErrorReason } from "../util/error-reason.js";
|
|
4
3
|
import { assertSameScannedRegularFile } from "./local-file-identity.js";
|
|
5
4
|
import { normalizeSha1TimeoutMillis } from "./sha1-options.js";
|
|
@@ -15,16 +14,6 @@ function formatHashError(error) {
|
|
|
15
14
|
return sanitizeErrorReason(error);
|
|
16
15
|
}
|
|
17
16
|
/**
|
|
18
|
-
* Returns whether an error represents an abort.
|
|
19
|
-
*
|
|
20
|
-
* @param err - Unknown thrown value.
|
|
21
|
-
*
|
|
22
|
-
* @returns True for AbortError values.
|
|
23
|
-
*/
|
|
24
|
-
function isAbortError(err) {
|
|
25
|
-
return toError(err).name === "AbortError";
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
17
|
* Reads a local file and computes its SHA-1 digest with non-regular-file rejection,
|
|
29
18
|
* scanned-size bounds, abort support, and an idle/no-progress timeout.
|
|
30
19
|
*
|
|
@@ -49,10 +38,13 @@ async function readLocalSha1File(path, signal, options = {}) {
|
|
|
49
38
|
}
|
|
50
39
|
try {
|
|
51
40
|
signal?.throwIfAborted();
|
|
52
|
-
|
|
41
|
+
const preOpenStat = await withTimeout(lstat(path.absolutePath), timeoutMillis, "sha1 file status");
|
|
42
|
+
assertSameScannedRegularFile(preOpenStat, path, "sha1 comparison");
|
|
53
43
|
file = await openWithTimeout(open(path.absolutePath, flags), timeoutMillis);
|
|
54
|
-
|
|
55
|
-
assertSameScannedRegularFile(
|
|
44
|
+
const postOpenStat = await withTimeout(lstat(path.absolutePath), timeoutMillis, "sha1 file status");
|
|
45
|
+
assertSameScannedRegularFile(postOpenStat, path, "sha1 comparison");
|
|
46
|
+
const stat = await withTimeout(file.stat(), timeoutMillis, "sha1 file status");
|
|
47
|
+
assertSameScannedRegularFile(stat, path, "sha1 comparison");
|
|
56
48
|
stream = file.createReadStream({
|
|
57
49
|
...path.size > 0 ? {
|
|
58
50
|
start: 0,
|
|
@@ -112,6 +104,6 @@ async function openWithTimeout(promise, timeoutMillis) {
|
|
|
112
104
|
}
|
|
113
105
|
/* v8 ignore stop */
|
|
114
106
|
//#endregion
|
|
115
|
-
export { formatHashError,
|
|
107
|
+
export { formatHashError, readLocalSha1File };
|
|
116
108
|
|
|
117
109
|
//# sourceMappingURL=local-sha1.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-sha1.js","names":[],"sources":["../../src/sync/local-sha1.ts"],"sourcesContent":["import { IncrementalSha1 } from '../streams/hash.ts'\nimport { sanitizeErrorReason } from '../util/error-reason.ts'\nimport {
|
|
1
|
+
{"version":3,"file":"local-sha1.js","names":[],"sources":["../../src/sync/local-sha1.ts"],"sourcesContent":["import { IncrementalSha1 } from '../streams/hash.ts'\nimport { sanitizeErrorReason } from '../util/error-reason.ts'\nimport { assertSameScannedRegularFile } from './local-file-identity.ts'\nimport { normalizeSha1TimeoutMillis } from './sha1-options.ts'\nimport type { LocalSyncPath } from './types.ts'\n\n/** Options for reading a local file SHA-1 digest. */\nexport interface LocalSha1ReadOptions {\n /**\n * Maximum milliseconds to allow without filesystem progress while hashing.\n * Defaults to 30 seconds.\n */\n readonly timeoutMillis?: number\n}\n\n/** Reads a local file and returns its SHA-1 digest, or null when unavailable. */\nexport type LocalSha1Reader = (\n path: LocalSyncPath,\n signal?: AbortSignal,\n options?: LocalSha1ReadOptions,\n) => Promise<string | null>\n\n/**\n * Formats a hash error for public sync events without leaking filesystem paths.\n *\n * @param error - Error thrown while hashing.\n *\n * @returns A sanitized reason suitable for event messages.\n */\nexport function formatHashError(error: Error): string {\n return sanitizeErrorReason(error)\n}\n\n/**\n * Reads a local file and computes its SHA-1 digest with non-regular-file rejection,\n * scanned-size bounds, abort support, and an idle/no-progress timeout.\n *\n * @param path - Local sync path to hash.\n * @param signal - Optional abort signal.\n * @param options - Optional idle timeout override.\n *\n * @returns The lowercase SHA-1 digest of the file bytes.\n */\nexport async function readLocalSha1File(\n path: LocalSyncPath,\n signal?: AbortSignal,\n options: LocalSha1ReadOptions = {},\n): Promise<string> {\n const { constants } = await import('node:fs')\n const { lstat, open } = await import('node:fs/promises')\n const timeoutMillis = normalizeSha1TimeoutMillis(options.timeoutMillis)\n const flags = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0)\n const hash = new IncrementalSha1()\n let stream: (AsyncIterable<Uint8Array> & { destroy(error?: Error): void }) | undefined\n let file: Awaited<ReturnType<typeof open>> | undefined\n let timeout: ReturnType<typeof setTimeout> | undefined\n\n function armTimeout(onTimeout: () => void): void {\n if (timeout !== undefined) clearTimeout(timeout)\n timeout = setTimeout(onTimeout, timeoutMillis)\n }\n\n try {\n signal?.throwIfAborted()\n\n const preOpenStat = await withTimeout(\n lstat(path.absolutePath),\n timeoutMillis,\n 'sha1 file status',\n )\n assertSameScannedRegularFile(preOpenStat, path, 'sha1 comparison')\n\n file = await openWithTimeout(open(path.absolutePath, flags), timeoutMillis)\n\n const postOpenStat = await withTimeout(\n lstat(path.absolutePath),\n timeoutMillis,\n 'sha1 file status',\n )\n assertSameScannedRegularFile(postOpenStat, path, 'sha1 comparison')\n\n const stat = await withTimeout(file.stat(), timeoutMillis, 'sha1 file status')\n assertSameScannedRegularFile(stat, path, 'sha1 comparison')\n\n stream = file.createReadStream({\n ...(path.size > 0 ? { start: 0, end: path.size - 1 } : {}),\n ...(signal !== undefined ? { signal } : {}),\n })\n\n let bytesRead = 0\n /* v8 ignore next 3 -- idle-timeout firing is timing-dependent in filesystem tests */\n armTimeout(() => {\n stream?.destroy(new Error(`sha1 read stalled for ${timeoutMillis} ms`))\n })\n for await (const chunk of stream) {\n bytesRead += chunk.byteLength\n await hash.update(chunk)\n /* v8 ignore next 3 -- idle-timeout firing is timing-dependent in filesystem tests */\n armTimeout(() => {\n stream?.destroy(new Error(`sha1 read stalled for ${timeoutMillis} ms`))\n })\n }\n\n /* v8 ignore next -- defensive TOCTOU guard after the bounded stream completes */\n if (bytesRead !== path.size) throw new Error('file changed during sha1 comparison')\n return hash.digest()\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n stream?.destroy()\n await file?.close().catch(() => {})\n }\n}\n\n/* v8 ignore start -- defensive stale-filesystem stall handling is not portable to trigger */\nasync function withTimeout<T>(\n promise: Promise<T>,\n timeoutMillis: number,\n operation: string,\n): Promise<T> {\n let timeout: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timeout = setTimeout(() => {\n reject(new Error(`${operation} stalled for ${timeoutMillis} ms`))\n }, timeoutMillis)\n }),\n ])\n } finally {\n if (timeout !== undefined) clearTimeout(timeout)\n }\n}\n\nasync function openWithTimeout<T extends { close(): Promise<void> }>(\n promise: Promise<T>,\n timeoutMillis: number,\n): Promise<T> {\n let timedOut = false\n const tracked = promise.then(\n (file) => {\n if (timedOut) void file.close().catch(() => {})\n return file\n },\n (err: unknown) => {\n throw err\n },\n )\n\n try {\n return await withTimeout(tracked, timeoutMillis, 'sha1 file open')\n } catch (err) {\n timedOut = true\n throw err\n }\n}\n/* v8 ignore stop */\n"],"mappings":";;;;;;;;;;;;AA6BA,SAAgB,gBAAgB,OAAsB;CACpD,OAAO,oBAAoB,KAAK;AAClC;;;;;;;;;;;AAYA,eAAsB,kBACpB,MACA,QACA,UAAgC,CAAC,GAChB;CACjB,MAAM,EAAE,cAAc,MAAM,OAAO;CACnC,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO;CACrC,MAAM,gBAAgB,2BAA2B,QAAQ,aAAa;CACtE,MAAM,QAAQ,UAAU,YAAY,UAAU,cAAc,MAAM,UAAU,cAAc;CAC1F,MAAM,OAAO,IAAI,gBAAgB;CACjC,IAAI;CACJ,IAAI;CACJ,IAAI;CAEJ,SAAS,WAAW,WAA6B;EAC/C,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;EAC/C,UAAU,WAAW,WAAW,aAAa;CAC/C;CAEA,IAAI;EACF,QAAQ,eAAe;EAEvB,MAAM,cAAc,MAAM,YACxB,MAAM,KAAK,YAAY,GACvB,eACA,kBACF;EACA,6BAA6B,aAAa,MAAM,iBAAiB;EAEjE,OAAO,MAAM,gBAAgB,KAAK,KAAK,cAAc,KAAK,GAAG,aAAa;EAE1E,MAAM,eAAe,MAAM,YACzB,MAAM,KAAK,YAAY,GACvB,eACA,kBACF;EACA,6BAA6B,cAAc,MAAM,iBAAiB;EAElE,MAAM,OAAO,MAAM,YAAY,KAAK,KAAK,GAAG,eAAe,kBAAkB;EAC7E,6BAA6B,MAAM,MAAM,iBAAiB;EAE1D,SAAS,KAAK,iBAAiB;GAC7B,GAAI,KAAK,OAAO,IAAI;IAAE,OAAO;IAAG,KAAK,KAAK,OAAO;GAAE,IAAI,CAAC;GACxD,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;EAC3C,CAAC;EAED,IAAI,YAAY;;EAEhB,iBAAiB;GACf,QAAQ,wBAAQ,IAAI,MAAM,yBAAyB,cAAc,IAAI,CAAC;EACxE,CAAC;EACD,WAAW,MAAM,SAAS,QAAQ;GAChC,aAAa,MAAM;GACnB,MAAM,KAAK,OAAO,KAAK;;GAEvB,iBAAiB;IACf,QAAQ,wBAAQ,IAAI,MAAM,yBAAyB,cAAc,IAAI,CAAC;GACxE,CAAC;EACH;;EAGA,IAAI,cAAc,KAAK,MAAM,MAAM,IAAI,MAAM,qCAAqC;EAClF,OAAO,KAAK,OAAO;CACrB,UAAU;EACR,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;EAC/C,QAAQ,QAAQ;EAChB,MAAM,MAAM,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;CACpC;AACF;;AAGA,eAAe,YACb,SACA,eACA,WACY;CACZ,IAAI;CACJ,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CACxB,SACA,IAAI,SAAgB,GAAG,WAAW;GAChC,UAAU,iBAAiB;IACzB,uBAAO,IAAI,MAAM,GAAG,UAAU,eAAe,cAAc,IAAI,CAAC;GAClE,GAAG,aAAa;EAClB,CAAC,CACH,CAAC;CACH,UAAU;EACR,IAAI,YAAY,KAAA,GAAW,aAAa,OAAO;CACjD;AACF;AAEA,eAAe,gBACb,SACA,eACY;CACZ,IAAI,WAAW;CACf,MAAM,UAAU,QAAQ,MACrB,SAAS;EACR,IAAI,UAAU,KAAU,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;EAC9C,OAAO;CACT,IACC,QAAiB;EAChB,MAAM;CACR,CACF;CAEA,IAAI;EACF,OAAO,MAAM,YAAY,SAAS,eAAe,gBAAgB;CACnE,SAAS,KAAK;EACZ,WAAW;EACX,MAAM;CACR;AACF"}
|
package/dist/sync/pairing.cjs
CHANGED
|
@@ -108,6 +108,7 @@ function frozenScanOptions(options, include, exclude, onSkip) {
|
|
|
108
108
|
...options.onError !== void 0 ? { onError: options.onError } : {},
|
|
109
109
|
...onSkip !== void 0 ? { onSkip } : {},
|
|
110
110
|
...options.requireLocalSafePaths !== void 0 ? { requireLocalSafePaths: options.requireLocalSafePaths } : {},
|
|
111
|
+
...options.localSymlinks !== void 0 ? { localSymlinks: options.localSymlinks } : {},
|
|
111
112
|
...options.maxScanEntries !== void 0 ? { maxScanEntries: options.maxScanEntries } : {}
|
|
112
113
|
});
|
|
113
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairing.cjs","names":[],"sources":["../../src/sync/pairing.ts"],"sourcesContent":["import { filterSyncPaths } from './filters.ts'\nimport { compareSyncRelativePaths } from './path-order.ts'\nimport { validateSyncFilters } from './regexp-safety.ts'\nimport { assertScanEntryLimit, scanEntryLimit } from './scan-limit.ts'\nimport type {\n SyncFilterPattern,\n SyncFolder,\n SyncPath,\n SyncScanOptions,\n SyncSkipEvent,\n} from './types.ts'\n\n/** A paired tuple of source and destination files. Either side may be null if the file is absent. */\nexport type SyncPair = readonly [SyncPath | null, SyncPath | null]\n\n/**\n * Merge-joins two sorted folder scans by relative path, yielding paired tuples.\n * Files present only in source yield `[source, null]`, only in dest yield `[null, dest]`,\n * and files in both yield `[source, dest]`.\n *\n * @param source - The source folder to scan.\n * @param dest - The destination folder to scan.\n * @param options - Optional scan controls and filters shared by both folders.\n * @param scanCallbacks - Optional internal source/destination skip callbacks.\n */\nexport async function* zipFolders(\n source: SyncFolder,\n dest: SyncFolder,\n options: SyncScanOptions = {},\n scanCallbacks: {\n readonly onSourceSkip?: (event: SyncSkipEvent) => void\n readonly onDestSkip?: (event: SyncSkipEvent) => void\n } = {},\n): AsyncGenerator<SyncPair> {\n validateSyncFilters(options)\n const sourceOptions = scanOptionsSnapshot(options, scanCallbacks.onSourceSkip)\n const destOptions = scanOptionsSnapshot(options, scanCallbacks.onDestSkip)\n const sourceIter = scanWithFilters(source, sourceOptions)[Symbol.asyncIterator]()\n const destIter = scanWithFilters(dest, destOptions)[Symbol.asyncIterator]()\n let sourceDone = false\n let destDone = false\n\n try {\n let [sourceResult, destResult] = await Promise.all([sourceIter.next(), destIter.next()])\n sourceDone = sourceResult.done === true\n destDone = destResult.done === true\n\n while (!sourceResult.done || !destResult.done) {\n const s = sourceResult.done ? null : sourceResult.value\n const d = destResult.done ? null : destResult.value\n\n if (s === null) {\n yield [null, d]\n destResult = await destIter.next()\n destDone = destResult.done === true\n } else if (d === null) {\n yield [s, null]\n sourceResult = await sourceIter.next()\n sourceDone = sourceResult.done === true\n } else {\n const comparison = compareSyncRelativePaths(s.relativePath, d.relativePath)\n if (comparison < 0) {\n yield [s, null]\n sourceResult = await sourceIter.next()\n sourceDone = sourceResult.done === true\n } else if (comparison > 0) {\n yield [null, d]\n destResult = await destIter.next()\n destDone = destResult.done === true\n } else {\n yield [s, d]\n sourceResult = await sourceIter.next()\n destResult = await destIter.next()\n sourceDone = sourceResult.done === true\n destDone = destResult.done === true\n }\n }\n }\n } finally {\n await closeScanIterator(sourceIter, sourceDone)\n await closeScanIterator(destIter, destDone)\n }\n}\n\nasync function closeScanIterator(\n iterator: AsyncIterator<SyncPath>,\n alreadyDone: boolean,\n): Promise<void> {\n if (alreadyDone || iterator.return === undefined) return\n try {\n await iterator.return()\n } catch {\n // Best-effort scanner cleanup should not mask the original stop reason.\n }\n}\n\nfunction scanWithFilters(\n folder: SyncFolder,\n options: { readonly scanner: SyncScanOptions; readonly sdk: SyncScanOptions },\n): AsyncIterable<SyncPath> {\n const scanned = filterSyncPaths(folder.scan(options.scanner), options.sdk)\n if (folder.appliesScanSorting === true) return limitSyncPaths(scanned, options.sdk)\n return sortSyncPaths(scanned, options.sdk)\n}\n\nasync function* limitSyncPaths(\n paths: AsyncIterable<SyncPath>,\n filters: SyncScanOptions | undefined,\n): AsyncGenerator<SyncPath> {\n const maxScanEntries = scanEntryLimit(filters)\n let count = 0\n for await (const path of paths) {\n count++\n assertScanEntryLimit(count, maxScanEntries)\n yield path\n }\n}\n\nasync function* sortSyncPaths(\n paths: AsyncIterable<SyncPath>,\n filters: SyncScanOptions | undefined,\n): AsyncGenerator<SyncPath> {\n const maxScanEntries = scanEntryLimit(filters)\n const collected: SyncPath[] = []\n for await (const path of paths) {\n collected.push(path)\n assertScanEntryLimit(collected.length, maxScanEntries)\n }\n collected.sort((a, b) => compareSyncRelativePaths(a.relativePath, b.relativePath))\n yield* collected\n}\n\nfunction scanOptionsSnapshot(\n options: SyncScanOptions,\n onSkip: ((event: SyncSkipEvent) => void) | undefined,\n): { readonly scanner: SyncScanOptions; readonly sdk: SyncScanOptions } {\n const onSkipSnapshot =\n options.onSkip === undefined && onSkip === undefined\n ? undefined\n : (event: SyncSkipEvent): void => {\n options.onSkip?.(event)\n onSkip?.(event)\n }\n\n return {\n scanner: frozenScanOptions(\n options,\n frozenPatterns(options.include),\n frozenPatterns(options.exclude),\n onSkipSnapshot,\n ),\n sdk: frozenScanOptions(\n options,\n frozenPatterns(options.include),\n frozenPatterns(options.exclude),\n onSkipSnapshot,\n ),\n }\n}\n\nfunction frozenScanOptions(\n options: SyncScanOptions,\n include: readonly SyncFilterPattern[] | undefined,\n exclude: readonly SyncFilterPattern[] | undefined,\n onSkip: ((event: SyncSkipEvent) => void) | undefined,\n): SyncScanOptions {\n return Object.freeze({\n ...(include !== undefined ? { include } : {}),\n ...(exclude !== undefined ? { exclude } : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.onError !== undefined ? { onError: options.onError } : {}),\n ...(onSkip !== undefined ? { onSkip } : {}),\n ...(options.requireLocalSafePaths !== undefined\n ? { requireLocalSafePaths: options.requireLocalSafePaths }\n : {}),\n ...(options.maxScanEntries !== undefined ? { maxScanEntries: options.maxScanEntries } : {}),\n })\n}\n\nfunction frozenPatterns(\n patterns: readonly SyncFilterPattern[] | undefined,\n): readonly SyncFilterPattern[] | undefined {\n return patterns === undefined ? undefined : Object.freeze([...patterns])\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pairing.cjs","names":[],"sources":["../../src/sync/pairing.ts"],"sourcesContent":["import { filterSyncPaths } from './filters.ts'\nimport { compareSyncRelativePaths } from './path-order.ts'\nimport { validateSyncFilters } from './regexp-safety.ts'\nimport { assertScanEntryLimit, scanEntryLimit } from './scan-limit.ts'\nimport type {\n SyncFilterPattern,\n SyncFolder,\n SyncPath,\n SyncScanOptions,\n SyncSkipEvent,\n} from './types.ts'\n\n/** A paired tuple of source and destination files. Either side may be null if the file is absent. */\nexport type SyncPair = readonly [SyncPath | null, SyncPath | null]\n\n/**\n * Merge-joins two sorted folder scans by relative path, yielding paired tuples.\n * Files present only in source yield `[source, null]`, only in dest yield `[null, dest]`,\n * and files in both yield `[source, dest]`.\n *\n * @param source - The source folder to scan.\n * @param dest - The destination folder to scan.\n * @param options - Optional scan controls and filters shared by both folders.\n * @param scanCallbacks - Optional internal source/destination skip callbacks.\n */\nexport async function* zipFolders(\n source: SyncFolder,\n dest: SyncFolder,\n options: SyncScanOptions = {},\n scanCallbacks: {\n readonly onSourceSkip?: (event: SyncSkipEvent) => void\n readonly onDestSkip?: (event: SyncSkipEvent) => void\n } = {},\n): AsyncGenerator<SyncPair> {\n validateSyncFilters(options)\n const sourceOptions = scanOptionsSnapshot(options, scanCallbacks.onSourceSkip)\n const destOptions = scanOptionsSnapshot(options, scanCallbacks.onDestSkip)\n const sourceIter = scanWithFilters(source, sourceOptions)[Symbol.asyncIterator]()\n const destIter = scanWithFilters(dest, destOptions)[Symbol.asyncIterator]()\n let sourceDone = false\n let destDone = false\n\n try {\n let [sourceResult, destResult] = await Promise.all([sourceIter.next(), destIter.next()])\n sourceDone = sourceResult.done === true\n destDone = destResult.done === true\n\n while (!sourceResult.done || !destResult.done) {\n const s = sourceResult.done ? null : sourceResult.value\n const d = destResult.done ? null : destResult.value\n\n if (s === null) {\n yield [null, d]\n destResult = await destIter.next()\n destDone = destResult.done === true\n } else if (d === null) {\n yield [s, null]\n sourceResult = await sourceIter.next()\n sourceDone = sourceResult.done === true\n } else {\n const comparison = compareSyncRelativePaths(s.relativePath, d.relativePath)\n if (comparison < 0) {\n yield [s, null]\n sourceResult = await sourceIter.next()\n sourceDone = sourceResult.done === true\n } else if (comparison > 0) {\n yield [null, d]\n destResult = await destIter.next()\n destDone = destResult.done === true\n } else {\n yield [s, d]\n sourceResult = await sourceIter.next()\n destResult = await destIter.next()\n sourceDone = sourceResult.done === true\n destDone = destResult.done === true\n }\n }\n }\n } finally {\n await closeScanIterator(sourceIter, sourceDone)\n await closeScanIterator(destIter, destDone)\n }\n}\n\nasync function closeScanIterator(\n iterator: AsyncIterator<SyncPath>,\n alreadyDone: boolean,\n): Promise<void> {\n if (alreadyDone || iterator.return === undefined) return\n try {\n await iterator.return()\n } catch {\n // Best-effort scanner cleanup should not mask the original stop reason.\n }\n}\n\nfunction scanWithFilters(\n folder: SyncFolder,\n options: { readonly scanner: SyncScanOptions; readonly sdk: SyncScanOptions },\n): AsyncIterable<SyncPath> {\n const scanned = filterSyncPaths(folder.scan(options.scanner), options.sdk)\n if (folder.appliesScanSorting === true) return limitSyncPaths(scanned, options.sdk)\n return sortSyncPaths(scanned, options.sdk)\n}\n\nasync function* limitSyncPaths(\n paths: AsyncIterable<SyncPath>,\n filters: SyncScanOptions | undefined,\n): AsyncGenerator<SyncPath> {\n const maxScanEntries = scanEntryLimit(filters)\n let count = 0\n for await (const path of paths) {\n count++\n assertScanEntryLimit(count, maxScanEntries)\n yield path\n }\n}\n\nasync function* sortSyncPaths(\n paths: AsyncIterable<SyncPath>,\n filters: SyncScanOptions | undefined,\n): AsyncGenerator<SyncPath> {\n const maxScanEntries = scanEntryLimit(filters)\n const collected: SyncPath[] = []\n for await (const path of paths) {\n collected.push(path)\n assertScanEntryLimit(collected.length, maxScanEntries)\n }\n collected.sort((a, b) => compareSyncRelativePaths(a.relativePath, b.relativePath))\n yield* collected\n}\n\nfunction scanOptionsSnapshot(\n options: SyncScanOptions,\n onSkip: ((event: SyncSkipEvent) => void) | undefined,\n): { readonly scanner: SyncScanOptions; readonly sdk: SyncScanOptions } {\n const onSkipSnapshot =\n options.onSkip === undefined && onSkip === undefined\n ? undefined\n : (event: SyncSkipEvent): void => {\n options.onSkip?.(event)\n onSkip?.(event)\n }\n\n return {\n scanner: frozenScanOptions(\n options,\n frozenPatterns(options.include),\n frozenPatterns(options.exclude),\n onSkipSnapshot,\n ),\n sdk: frozenScanOptions(\n options,\n frozenPatterns(options.include),\n frozenPatterns(options.exclude),\n onSkipSnapshot,\n ),\n }\n}\n\nfunction frozenScanOptions(\n options: SyncScanOptions,\n include: readonly SyncFilterPattern[] | undefined,\n exclude: readonly SyncFilterPattern[] | undefined,\n onSkip: ((event: SyncSkipEvent) => void) | undefined,\n): SyncScanOptions {\n return Object.freeze({\n ...(include !== undefined ? { include } : {}),\n ...(exclude !== undefined ? { exclude } : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.onError !== undefined ? { onError: options.onError } : {}),\n ...(onSkip !== undefined ? { onSkip } : {}),\n ...(options.requireLocalSafePaths !== undefined\n ? { requireLocalSafePaths: options.requireLocalSafePaths }\n : {}),\n ...(options.localSymlinks !== undefined ? { localSymlinks: options.localSymlinks } : {}),\n ...(options.maxScanEntries !== undefined ? { maxScanEntries: options.maxScanEntries } : {}),\n })\n}\n\nfunction frozenPatterns(\n patterns: readonly SyncFilterPattern[] | undefined,\n): readonly SyncFilterPattern[] | undefined {\n return patterns === undefined ? undefined : Object.freeze([...patterns])\n}\n"],"mappings":"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"}
|
package/dist/sync/pairing.js
CHANGED
|
@@ -108,6 +108,7 @@ function frozenScanOptions(options, include, exclude, onSkip) {
|
|
|
108
108
|
...options.onError !== void 0 ? { onError: options.onError } : {},
|
|
109
109
|
...onSkip !== void 0 ? { onSkip } : {},
|
|
110
110
|
...options.requireLocalSafePaths !== void 0 ? { requireLocalSafePaths: options.requireLocalSafePaths } : {},
|
|
111
|
+
...options.localSymlinks !== void 0 ? { localSymlinks: options.localSymlinks } : {},
|
|
111
112
|
...options.maxScanEntries !== void 0 ? { maxScanEntries: options.maxScanEntries } : {}
|
|
112
113
|
});
|
|
113
114
|
}
|
package/dist/sync/pairing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pairing.js","names":[],"sources":["../../src/sync/pairing.ts"],"sourcesContent":["import { filterSyncPaths } from './filters.ts'\nimport { compareSyncRelativePaths } from './path-order.ts'\nimport { validateSyncFilters } from './regexp-safety.ts'\nimport { assertScanEntryLimit, scanEntryLimit } from './scan-limit.ts'\nimport type {\n SyncFilterPattern,\n SyncFolder,\n SyncPath,\n SyncScanOptions,\n SyncSkipEvent,\n} from './types.ts'\n\n/** A paired tuple of source and destination files. Either side may be null if the file is absent. */\nexport type SyncPair = readonly [SyncPath | null, SyncPath | null]\n\n/**\n * Merge-joins two sorted folder scans by relative path, yielding paired tuples.\n * Files present only in source yield `[source, null]`, only in dest yield `[null, dest]`,\n * and files in both yield `[source, dest]`.\n *\n * @param source - The source folder to scan.\n * @param dest - The destination folder to scan.\n * @param options - Optional scan controls and filters shared by both folders.\n * @param scanCallbacks - Optional internal source/destination skip callbacks.\n */\nexport async function* zipFolders(\n source: SyncFolder,\n dest: SyncFolder,\n options: SyncScanOptions = {},\n scanCallbacks: {\n readonly onSourceSkip?: (event: SyncSkipEvent) => void\n readonly onDestSkip?: (event: SyncSkipEvent) => void\n } = {},\n): AsyncGenerator<SyncPair> {\n validateSyncFilters(options)\n const sourceOptions = scanOptionsSnapshot(options, scanCallbacks.onSourceSkip)\n const destOptions = scanOptionsSnapshot(options, scanCallbacks.onDestSkip)\n const sourceIter = scanWithFilters(source, sourceOptions)[Symbol.asyncIterator]()\n const destIter = scanWithFilters(dest, destOptions)[Symbol.asyncIterator]()\n let sourceDone = false\n let destDone = false\n\n try {\n let [sourceResult, destResult] = await Promise.all([sourceIter.next(), destIter.next()])\n sourceDone = sourceResult.done === true\n destDone = destResult.done === true\n\n while (!sourceResult.done || !destResult.done) {\n const s = sourceResult.done ? null : sourceResult.value\n const d = destResult.done ? null : destResult.value\n\n if (s === null) {\n yield [null, d]\n destResult = await destIter.next()\n destDone = destResult.done === true\n } else if (d === null) {\n yield [s, null]\n sourceResult = await sourceIter.next()\n sourceDone = sourceResult.done === true\n } else {\n const comparison = compareSyncRelativePaths(s.relativePath, d.relativePath)\n if (comparison < 0) {\n yield [s, null]\n sourceResult = await sourceIter.next()\n sourceDone = sourceResult.done === true\n } else if (comparison > 0) {\n yield [null, d]\n destResult = await destIter.next()\n destDone = destResult.done === true\n } else {\n yield [s, d]\n sourceResult = await sourceIter.next()\n destResult = await destIter.next()\n sourceDone = sourceResult.done === true\n destDone = destResult.done === true\n }\n }\n }\n } finally {\n await closeScanIterator(sourceIter, sourceDone)\n await closeScanIterator(destIter, destDone)\n }\n}\n\nasync function closeScanIterator(\n iterator: AsyncIterator<SyncPath>,\n alreadyDone: boolean,\n): Promise<void> {\n if (alreadyDone || iterator.return === undefined) return\n try {\n await iterator.return()\n } catch {\n // Best-effort scanner cleanup should not mask the original stop reason.\n }\n}\n\nfunction scanWithFilters(\n folder: SyncFolder,\n options: { readonly scanner: SyncScanOptions; readonly sdk: SyncScanOptions },\n): AsyncIterable<SyncPath> {\n const scanned = filterSyncPaths(folder.scan(options.scanner), options.sdk)\n if (folder.appliesScanSorting === true) return limitSyncPaths(scanned, options.sdk)\n return sortSyncPaths(scanned, options.sdk)\n}\n\nasync function* limitSyncPaths(\n paths: AsyncIterable<SyncPath>,\n filters: SyncScanOptions | undefined,\n): AsyncGenerator<SyncPath> {\n const maxScanEntries = scanEntryLimit(filters)\n let count = 0\n for await (const path of paths) {\n count++\n assertScanEntryLimit(count, maxScanEntries)\n yield path\n }\n}\n\nasync function* sortSyncPaths(\n paths: AsyncIterable<SyncPath>,\n filters: SyncScanOptions | undefined,\n): AsyncGenerator<SyncPath> {\n const maxScanEntries = scanEntryLimit(filters)\n const collected: SyncPath[] = []\n for await (const path of paths) {\n collected.push(path)\n assertScanEntryLimit(collected.length, maxScanEntries)\n }\n collected.sort((a, b) => compareSyncRelativePaths(a.relativePath, b.relativePath))\n yield* collected\n}\n\nfunction scanOptionsSnapshot(\n options: SyncScanOptions,\n onSkip: ((event: SyncSkipEvent) => void) | undefined,\n): { readonly scanner: SyncScanOptions; readonly sdk: SyncScanOptions } {\n const onSkipSnapshot =\n options.onSkip === undefined && onSkip === undefined\n ? undefined\n : (event: SyncSkipEvent): void => {\n options.onSkip?.(event)\n onSkip?.(event)\n }\n\n return {\n scanner: frozenScanOptions(\n options,\n frozenPatterns(options.include),\n frozenPatterns(options.exclude),\n onSkipSnapshot,\n ),\n sdk: frozenScanOptions(\n options,\n frozenPatterns(options.include),\n frozenPatterns(options.exclude),\n onSkipSnapshot,\n ),\n }\n}\n\nfunction frozenScanOptions(\n options: SyncScanOptions,\n include: readonly SyncFilterPattern[] | undefined,\n exclude: readonly SyncFilterPattern[] | undefined,\n onSkip: ((event: SyncSkipEvent) => void) | undefined,\n): SyncScanOptions {\n return Object.freeze({\n ...(include !== undefined ? { include } : {}),\n ...(exclude !== undefined ? { exclude } : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.onError !== undefined ? { onError: options.onError } : {}),\n ...(onSkip !== undefined ? { onSkip } : {}),\n ...(options.requireLocalSafePaths !== undefined\n ? { requireLocalSafePaths: options.requireLocalSafePaths }\n : {}),\n ...(options.maxScanEntries !== undefined ? { maxScanEntries: options.maxScanEntries } : {}),\n })\n}\n\nfunction frozenPatterns(\n patterns: readonly SyncFilterPattern[] | undefined,\n): readonly SyncFilterPattern[] | undefined {\n return patterns === undefined ? undefined : Object.freeze([...patterns])\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pairing.js","names":[],"sources":["../../src/sync/pairing.ts"],"sourcesContent":["import { filterSyncPaths } from './filters.ts'\nimport { compareSyncRelativePaths } from './path-order.ts'\nimport { validateSyncFilters } from './regexp-safety.ts'\nimport { assertScanEntryLimit, scanEntryLimit } from './scan-limit.ts'\nimport type {\n SyncFilterPattern,\n SyncFolder,\n SyncPath,\n SyncScanOptions,\n SyncSkipEvent,\n} from './types.ts'\n\n/** A paired tuple of source and destination files. Either side may be null if the file is absent. */\nexport type SyncPair = readonly [SyncPath | null, SyncPath | null]\n\n/**\n * Merge-joins two sorted folder scans by relative path, yielding paired tuples.\n * Files present only in source yield `[source, null]`, only in dest yield `[null, dest]`,\n * and files in both yield `[source, dest]`.\n *\n * @param source - The source folder to scan.\n * @param dest - The destination folder to scan.\n * @param options - Optional scan controls and filters shared by both folders.\n * @param scanCallbacks - Optional internal source/destination skip callbacks.\n */\nexport async function* zipFolders(\n source: SyncFolder,\n dest: SyncFolder,\n options: SyncScanOptions = {},\n scanCallbacks: {\n readonly onSourceSkip?: (event: SyncSkipEvent) => void\n readonly onDestSkip?: (event: SyncSkipEvent) => void\n } = {},\n): AsyncGenerator<SyncPair> {\n validateSyncFilters(options)\n const sourceOptions = scanOptionsSnapshot(options, scanCallbacks.onSourceSkip)\n const destOptions = scanOptionsSnapshot(options, scanCallbacks.onDestSkip)\n const sourceIter = scanWithFilters(source, sourceOptions)[Symbol.asyncIterator]()\n const destIter = scanWithFilters(dest, destOptions)[Symbol.asyncIterator]()\n let sourceDone = false\n let destDone = false\n\n try {\n let [sourceResult, destResult] = await Promise.all([sourceIter.next(), destIter.next()])\n sourceDone = sourceResult.done === true\n destDone = destResult.done === true\n\n while (!sourceResult.done || !destResult.done) {\n const s = sourceResult.done ? null : sourceResult.value\n const d = destResult.done ? null : destResult.value\n\n if (s === null) {\n yield [null, d]\n destResult = await destIter.next()\n destDone = destResult.done === true\n } else if (d === null) {\n yield [s, null]\n sourceResult = await sourceIter.next()\n sourceDone = sourceResult.done === true\n } else {\n const comparison = compareSyncRelativePaths(s.relativePath, d.relativePath)\n if (comparison < 0) {\n yield [s, null]\n sourceResult = await sourceIter.next()\n sourceDone = sourceResult.done === true\n } else if (comparison > 0) {\n yield [null, d]\n destResult = await destIter.next()\n destDone = destResult.done === true\n } else {\n yield [s, d]\n sourceResult = await sourceIter.next()\n destResult = await destIter.next()\n sourceDone = sourceResult.done === true\n destDone = destResult.done === true\n }\n }\n }\n } finally {\n await closeScanIterator(sourceIter, sourceDone)\n await closeScanIterator(destIter, destDone)\n }\n}\n\nasync function closeScanIterator(\n iterator: AsyncIterator<SyncPath>,\n alreadyDone: boolean,\n): Promise<void> {\n if (alreadyDone || iterator.return === undefined) return\n try {\n await iterator.return()\n } catch {\n // Best-effort scanner cleanup should not mask the original stop reason.\n }\n}\n\nfunction scanWithFilters(\n folder: SyncFolder,\n options: { readonly scanner: SyncScanOptions; readonly sdk: SyncScanOptions },\n): AsyncIterable<SyncPath> {\n const scanned = filterSyncPaths(folder.scan(options.scanner), options.sdk)\n if (folder.appliesScanSorting === true) return limitSyncPaths(scanned, options.sdk)\n return sortSyncPaths(scanned, options.sdk)\n}\n\nasync function* limitSyncPaths(\n paths: AsyncIterable<SyncPath>,\n filters: SyncScanOptions | undefined,\n): AsyncGenerator<SyncPath> {\n const maxScanEntries = scanEntryLimit(filters)\n let count = 0\n for await (const path of paths) {\n count++\n assertScanEntryLimit(count, maxScanEntries)\n yield path\n }\n}\n\nasync function* sortSyncPaths(\n paths: AsyncIterable<SyncPath>,\n filters: SyncScanOptions | undefined,\n): AsyncGenerator<SyncPath> {\n const maxScanEntries = scanEntryLimit(filters)\n const collected: SyncPath[] = []\n for await (const path of paths) {\n collected.push(path)\n assertScanEntryLimit(collected.length, maxScanEntries)\n }\n collected.sort((a, b) => compareSyncRelativePaths(a.relativePath, b.relativePath))\n yield* collected\n}\n\nfunction scanOptionsSnapshot(\n options: SyncScanOptions,\n onSkip: ((event: SyncSkipEvent) => void) | undefined,\n): { readonly scanner: SyncScanOptions; readonly sdk: SyncScanOptions } {\n const onSkipSnapshot =\n options.onSkip === undefined && onSkip === undefined\n ? undefined\n : (event: SyncSkipEvent): void => {\n options.onSkip?.(event)\n onSkip?.(event)\n }\n\n return {\n scanner: frozenScanOptions(\n options,\n frozenPatterns(options.include),\n frozenPatterns(options.exclude),\n onSkipSnapshot,\n ),\n sdk: frozenScanOptions(\n options,\n frozenPatterns(options.include),\n frozenPatterns(options.exclude),\n onSkipSnapshot,\n ),\n }\n}\n\nfunction frozenScanOptions(\n options: SyncScanOptions,\n include: readonly SyncFilterPattern[] | undefined,\n exclude: readonly SyncFilterPattern[] | undefined,\n onSkip: ((event: SyncSkipEvent) => void) | undefined,\n): SyncScanOptions {\n return Object.freeze({\n ...(include !== undefined ? { include } : {}),\n ...(exclude !== undefined ? { exclude } : {}),\n ...(options.signal !== undefined ? { signal: options.signal } : {}),\n ...(options.onError !== undefined ? { onError: options.onError } : {}),\n ...(onSkip !== undefined ? { onSkip } : {}),\n ...(options.requireLocalSafePaths !== undefined\n ? { requireLocalSafePaths: options.requireLocalSafePaths }\n : {}),\n ...(options.localSymlinks !== undefined ? { localSymlinks: options.localSymlinks } : {}),\n ...(options.maxScanEntries !== undefined ? { maxScanEntries: options.maxScanEntries } : {}),\n })\n}\n\nfunction frozenPatterns(\n patterns: readonly SyncFilterPattern[] | undefined,\n): readonly SyncFilterPattern[] | undefined {\n return patterns === undefined ? undefined : Object.freeze([...patterns])\n}\n"],"mappings":";;;;;;;;;;;;;;;AAyBA,gBAAuB,WACrB,QACA,MACA,UAA2B,CAAC,GAC5B,gBAGI,CAAC,GACqB;CAC1B,oBAAoB,OAAO;CAC3B,MAAM,gBAAgB,oBAAoB,SAAS,cAAc,YAAY;CAC7E,MAAM,cAAc,oBAAoB,SAAS,cAAc,UAAU;CACzE,MAAM,aAAa,gBAAgB,QAAQ,aAAa,CAAC,CAAC,OAAO,cAAc,CAAC;CAChF,MAAM,WAAW,gBAAgB,MAAM,WAAW,CAAC,CAAC,OAAO,cAAc,CAAC;CAC1E,IAAI,aAAa;CACjB,IAAI,WAAW;CAEf,IAAI;EACF,IAAI,CAAC,cAAc,cAAc,MAAM,QAAQ,IAAI,CAAC,WAAW,KAAK,GAAG,SAAS,KAAK,CAAC,CAAC;EACvF,aAAa,aAAa,SAAS;EACnC,WAAW,WAAW,SAAS;EAE/B,OAAO,CAAC,aAAa,QAAQ,CAAC,WAAW,MAAM;GAC7C,MAAM,IAAI,aAAa,OAAO,OAAO,aAAa;GAClD,MAAM,IAAI,WAAW,OAAO,OAAO,WAAW;GAE9C,IAAI,MAAM,MAAM;IACd,MAAM,CAAC,MAAM,CAAC;IACd,aAAa,MAAM,SAAS,KAAK;IACjC,WAAW,WAAW,SAAS;GACjC,OAAO,IAAI,MAAM,MAAM;IACrB,MAAM,CAAC,GAAG,IAAI;IACd,eAAe,MAAM,WAAW,KAAK;IACrC,aAAa,aAAa,SAAS;GACrC,OAAO;IACL,MAAM,aAAa,yBAAyB,EAAE,cAAc,EAAE,YAAY;IAC1E,IAAI,aAAa,GAAG;KAClB,MAAM,CAAC,GAAG,IAAI;KACd,eAAe,MAAM,WAAW,KAAK;KACrC,aAAa,aAAa,SAAS;IACrC,OAAO,IAAI,aAAa,GAAG;KACzB,MAAM,CAAC,MAAM,CAAC;KACd,aAAa,MAAM,SAAS,KAAK;KACjC,WAAW,WAAW,SAAS;IACjC,OAAO;KACL,MAAM,CAAC,GAAG,CAAC;KACX,eAAe,MAAM,WAAW,KAAK;KACrC,aAAa,MAAM,SAAS,KAAK;KACjC,aAAa,aAAa,SAAS;KACnC,WAAW,WAAW,SAAS;IACjC;GACF;EACF;CACF,UAAU;EACR,MAAM,kBAAkB,YAAY,UAAU;EAC9C,MAAM,kBAAkB,UAAU,QAAQ;CAC5C;AACF;AAEA,eAAe,kBACb,UACA,aACe;CACf,IAAI,eAAe,SAAS,WAAW,KAAA,GAAW;CAClD,IAAI;EACF,MAAM,SAAS,OAAO;CACxB,QAAQ,CAER;AACF;AAEA,SAAS,gBACP,QACA,SACyB;CACzB,MAAM,UAAU,gBAAgB,OAAO,KAAK,QAAQ,OAAO,GAAG,QAAQ,GAAG;CACzE,IAAI,OAAO,uBAAuB,MAAM,OAAO,eAAe,SAAS,QAAQ,GAAG;CAClF,OAAO,cAAc,SAAS,QAAQ,GAAG;AAC3C;AAEA,gBAAgB,eACd,OACA,SAC0B;CAC1B,MAAM,iBAAiB,eAAe,OAAO;CAC7C,IAAI,QAAQ;CACZ,WAAW,MAAM,QAAQ,OAAO;EAC9B;EACA,qBAAqB,OAAO,cAAc;EAC1C,MAAM;CACR;AACF;AAEA,gBAAgB,cACd,OACA,SAC0B;CAC1B,MAAM,iBAAiB,eAAe,OAAO;CAC7C,MAAM,YAAwB,CAAC;CAC/B,WAAW,MAAM,QAAQ,OAAO;EAC9B,UAAU,KAAK,IAAI;EACnB,qBAAqB,UAAU,QAAQ,cAAc;CACvD;CACA,UAAU,MAAM,GAAG,MAAM,yBAAyB,EAAE,cAAc,EAAE,YAAY,CAAC;CACjF,OAAO;AACT;AAEA,SAAS,oBACP,SACA,QACsE;CACtE,MAAM,iBACJ,QAAQ,WAAW,KAAA,KAAa,WAAW,KAAA,IACvC,KAAA,KACC,UAA+B;EAC9B,QAAQ,SAAS,KAAK;EACtB,SAAS,KAAK;CAChB;CAEN,OAAO;EACL,SAAS,kBACP,SACA,eAAe,QAAQ,OAAO,GAC9B,eAAe,QAAQ,OAAO,GAC9B,cACF;EACA,KAAK,kBACH,SACA,eAAe,QAAQ,OAAO,GAC9B,eAAe,QAAQ,OAAO,GAC9B,cACF;CACF;AACF;AAEA,SAAS,kBACP,SACA,SACA,SACA,QACiB;CACjB,OAAO,OAAO,OAAO;EACnB,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;EAC3C,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;EAC3C,GAAI,QAAQ,WAAW,KAAA,IAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;EACjE,GAAI,QAAQ,YAAY,KAAA,IAAY,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;EACpE,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;EACzC,GAAI,QAAQ,0BAA0B,KAAA,IAClC,EAAE,uBAAuB,QAAQ,sBAAsB,IACvD,CAAC;EACL,GAAI,QAAQ,kBAAkB,KAAA,IAAY,EAAE,eAAe,QAAQ,cAAc,IAAI,CAAC;EACtF,GAAI,QAAQ,mBAAmB,KAAA,IAAY,EAAE,gBAAgB,QAAQ,eAAe,IAAI,CAAC;CAC3F,CAAC;AACH;AAEA,SAAS,eACP,UAC0C;CAC1C,OAAO,aAAa,KAAA,IAAY,KAAA,IAAY,OAAO,OAAO,CAAC,GAAG,QAAQ,CAAC;AACzE"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_concurrency = require("../../upload/concurrency.cjs");
|
|
2
|
+
const require_abort = require("../../util/abort.cjs");
|
|
2
3
|
const require_sha1 = require("../../util/sha1.cjs");
|
|
3
4
|
const require_to_error = require("../../util/to-error.cjs");
|
|
4
5
|
const require_local_sha1 = require("../local-sha1.cjs");
|
|
@@ -109,7 +110,8 @@ async function preparePairsForCompare(pairs, compareMode, options = {}) {
|
|
|
109
110
|
originalPair: pair,
|
|
110
111
|
prepared: readyComparePair(pair)
|
|
111
112
|
}));
|
|
112
|
-
|
|
113
|
+
const concurrency = normalizeConcurrency(options.concurrency);
|
|
114
|
+
return require_concurrency.mapConcurrent(pairs, concurrency, async (pair) => {
|
|
113
115
|
if (options.signal?.aborted) return {
|
|
114
116
|
originalPair: pair,
|
|
115
117
|
prepared: aborted(pair)
|
|
@@ -174,7 +176,7 @@ async function prepareLocalPathSha1(path, options) {
|
|
|
174
176
|
aborted: false
|
|
175
177
|
};
|
|
176
178
|
} catch (err) {
|
|
177
|
-
if (options.signal
|
|
179
|
+
if (require_abort.isSignalAbortError(options.signal, err)) return {
|
|
178
180
|
path,
|
|
179
181
|
bytesHashed: 0,
|
|
180
182
|
bytesVerified: 0,
|
|
@@ -251,7 +253,7 @@ async function prepareB2PathSha1(path, options) {
|
|
|
251
253
|
aborted: false
|
|
252
254
|
};
|
|
253
255
|
} catch (err) {
|
|
254
|
-
if (options.signal
|
|
256
|
+
if (require_abort.isSignalAbortError(options.signal, err)) return {
|
|
255
257
|
path,
|
|
256
258
|
bytesHashed: 0,
|
|
257
259
|
bytesVerified: 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compare.cjs","names":[],"sources":["../../../src/sync/policies/compare.ts"],"sourcesContent":["import { mapConcurrent } from '../../upload/concurrency.ts'\nimport { normalizeVerifiableSha1 } from '../../util/sha1.ts'\nimport { toError } from '../../util/to-error.ts'\nimport { formatHashError, isAbortError, type LocalSha1Reader } from '../local-sha1.ts'\nimport type { SyncPair } from '../pairing.ts'\nimport { selectB2ComparableSha1, syncSha1StateOf } from '../sha1-metadata.ts'\nimport type {\n B2SyncPath,\n CompareMode,\n LocalSyncPath,\n SyncEvent,\n SyncPath,\n SyncSkipEvent,\n} from '../types.ts'\n\nexport { selectB2ComparableSha1 } from '../sha1-metadata.ts'\n\n/** Result from a B2 SHA-1 verification read. */\nexport interface B2Sha1ReadResult {\n /** SHA-1 digest of the selected B2 bytes, or null when unavailable. */\n readonly contentSha1: string | null\n /** Number of B2 bytes downloaded and hashed while verifying. */\n readonly bytesRead: number\n}\n\n/** Reads a B2 file and returns the SHA-1 digest of its actual bytes, or null when unavailable. */\nexport type B2Sha1Reader = (\n path: B2SyncPath,\n signal?: AbortSignal,\n) => Promise<string | null | B2Sha1ReadResult>\n\n/** Options for preparing a file pair before comparison. */\nexport interface PreparePairForCompareOptions {\n /** Signal used to abort local file hashing. */\n readonly signal?: AbortSignal\n /** Optional idle/no-progress timeout for local SHA-1 reads. */\n readonly sha1ReadTimeoutMillis?: number\n /** Optional local hashing override for tests or custom runtimes. */\n readonly readLocalSha1?: LocalSha1Reader\n /** Optional B2 hashing override used to verify metadata matches before skipping. */\n readonly readB2Sha1?: B2Sha1Reader\n}\n\n/** Options for preparing multiple file pairs before comparison. */\nexport interface PreparePairsForCompareOptions extends PreparePairForCompareOptions {\n /** Maximum number of file pairs to prepare concurrently. */\n readonly concurrency?: number\n}\n\n/** Result of preparing a file pair before policy comparison. */\nexport interface ComparePreparationResult {\n /** The pair with compare-mode metadata populated where possible. */\n readonly pair: SyncPair\n /** Events surfaced while preparing the pair, such as per-file hash errors or skips. */\n readonly events: readonly SyncEvent[]\n /** Errors surfaced while preparing the pair. These contribute to the final summary. */\n readonly errors: readonly Error[]\n /** Local file bytes read for hashing while preparing this pair. */\n readonly bytesHashed: number\n /** B2 bytes read for untrusted metadata verification while preparing this pair. */\n readonly bytesVerified: number\n /** Whether action generation should be skipped for this pair. */\n readonly skipActionGeneration: boolean\n /** Whether preparation stopped because the abort signal fired. */\n readonly aborted: boolean\n}\n\n/** A prepared pair result with the original pair retained for event context. */\nexport interface PreparedComparePair {\n /** Original pair from {@link zipFolders}. */\n readonly originalPair: SyncPair\n /** Preparation result for the original pair. */\n readonly prepared: ComparePreparationResult\n}\n\n/**\n * Determines whether two files should be considered different based on the compare mode.\n * For `sha1`, callers that use the low-level policy helpers should first prepare the pair so\n * local hashes and comparable B2 hashes are populated.\n *\n * @param source - The source file metadata.\n * @param dest - The destination file metadata.\n * @param compareMode - The comparison strategy: 'modtime', 'size', 'sha1', or 'none'.\n * @param threshold - Tolerance for the comparison (bytes for size, milliseconds for modtime).\n *\n * @returns `true` if the files are considered different.\n *\n * @throws When `compareMode` is not one of the supported compare modes.\n */\nexport function filesAreDifferent(\n source: SyncPath,\n dest: SyncPath,\n compareMode: CompareMode,\n threshold = 0,\n): boolean {\n switch (compareMode) {\n case 'none':\n return false\n case 'size':\n return Math.abs(source.size - dest.size) > threshold\n case 'sha1':\n return sha1ValuesAreDifferent(source, dest)\n case 'modtime':\n return Math.abs(source.modTimeMillis - dest.modTimeMillis) > threshold\n default:\n throw new Error(`Unsupported compare mode: ${String(compareMode)}`)\n }\n}\n\n/**\n * Throws when a runtime compare mode value is unsupported.\n *\n * @param compareMode - User-supplied compare mode.\n *\n * @throws When `compareMode` is not one of the supported values.\n */\nexport function assertSupportedCompareMode(\n compareMode: unknown,\n): asserts compareMode is CompareMode {\n switch (compareMode) {\n case 'none':\n case 'size':\n case 'sha1':\n case 'modtime':\n return\n default:\n throw new Error(`Unsupported compare mode: ${String(compareMode)}`)\n }\n}\n\nfunction sha1ValuesAreDifferent(source: SyncPath, dest: SyncPath): boolean {\n if (source.size !== dest.size) return true\n\n const sourceSha1 = comparableSha1(source)\n const destSha1 = comparableSha1(dest)\n if (sourceSha1.kind === 'untrusted' || destSha1.kind === 'untrusted') return true\n if (sourceSha1.kind === 'unavailable' || destSha1.kind === 'unavailable') return true\n return sourceSha1.value !== destSha1.value\n}\n\n/**\n * Prepares a pair for the selected compare mode.\n *\n * For `sha1`, this fills missing B2 hashes from comparable metadata and, when an explicit local\n * reader is supplied, hashes the local side only when size cannot already prove a difference.\n * Reader failures are converted into per-file sync events instead of aborting the whole run.\n *\n * @param pair - Source/destination pair from {@link zipFolders}.\n * @param compareMode - The comparison strategy.\n * @param options - Optional hashing dependencies and cancellation signal.\n *\n * @returns The prepared pair plus any preparation events.\n */\nexport async function preparePairForCompare(\n pair: SyncPair,\n compareMode: CompareMode,\n options: PreparePairForCompareOptions = {},\n): Promise<ComparePreparationResult> {\n assertSupportedCompareMode(compareMode)\n if (compareMode !== 'sha1') return readyComparePair(pair)\n\n const [source, dest] = pair\n if (source === null || dest === null) return readyComparePair(pair)\n if (source.size !== dest.size) return readyComparePair(pair)\n\n const metadataPair: SyncPair = [withB2ContentSha1(source), withB2ContentSha1(dest)]\n if (hasUnavailableB2Sha1(metadataPair)) {\n return skipped(metadataPair, unavailableSha1Event(metadataPair))\n }\n if (\n options.readB2Sha1 === undefined &&\n hasUntrustedSha1(metadataPair) &&\n !hasVerifiableUntrustedSha1(metadataPair)\n ) {\n return readyComparePair(metadataPair)\n }\n\n const [metadataSource, metadataDest] = metadataPair\n if (metadataSource === null || metadataDest === null) return readyComparePair(metadataPair)\n\n const sourceResult = await prepareLocalPathSha1(metadataSource, options)\n if (sourceResult.aborted) return aborted(metadataPair)\n if (sourceResult.event) {\n return skipped(metadataPair, sourceResult.event, sourceResult.error, sourceResult.bytesHashed)\n }\n\n const destResult = await prepareLocalPathSha1(metadataDest, options)\n if (destResult.aborted) return aborted([sourceResult.path, destResult.path])\n if (destResult.event) {\n return skipped(\n [sourceResult.path, destResult.path],\n destResult.event,\n destResult.error,\n sourceResult.bytesHashed,\n )\n }\n\n const preparedPair: SyncPair = [sourceResult.path, destResult.path]\n const sourceState = comparableSha1(sourceResult.path)\n const destState = comparableSha1(destResult.path)\n const bytesHashed = sourceResult.bytesHashed + destResult.bytesHashed\n\n if (sourceState.kind === 'unavailable' || destState.kind === 'unavailable') {\n return skipped(preparedPair, unavailableSha1Event(preparedPair), undefined, bytesHashed)\n }\n\n const shouldVerifyB2Bytes = untrustedSha1CouldSuppressTransfer(sourceState, destState)\n const readB2Sha1 = options.readB2Sha1\n if (shouldVerifyB2Bytes && hasB2Path(preparedPair) && readB2Sha1 !== undefined) {\n return verifyB2Sha1Bytes(preparedPair, { ...options, readB2Sha1 }, bytesHashed)\n }\n\n return readyComparePair(preparedPair, bytesHashed)\n}\n\n/**\n * Prepares a list of pairs for the selected compare mode with bounded concurrency.\n *\n * @param pairs - Source/destination pairs from {@link zipFolders}.\n * @param compareMode - The comparison strategy.\n * @param options - Optional hashing dependencies, cancellation signal, and concurrency.\n *\n * @returns Prepared results in the same order as the input pairs.\n */\nexport async function preparePairsForCompare(\n pairs: readonly SyncPair[],\n compareMode: CompareMode,\n options: PreparePairsForCompareOptions = {},\n): Promise<PreparedComparePair[]> {\n assertSupportedCompareMode(compareMode)\n if (compareMode !== 'sha1') {\n return pairs.map((pair) => ({ originalPair: pair, prepared: readyComparePair(pair) }))\n }\n\n const concurrency = normalizeConcurrency(options.concurrency)\n return mapConcurrent(pairs, concurrency, async (pair): Promise<PreparedComparePair> => {\n if (options.signal?.aborted) return { originalPair: pair, prepared: aborted(pair) }\n return {\n originalPair: pair,\n prepared: await preparePairForCompare(pair, compareMode, options),\n }\n })\n}\n\ntype Sha1State =\n | { readonly kind: 'verified'; readonly value: string }\n | { readonly kind: 'untrusted'; readonly value: string | null }\n | { readonly kind: 'unavailable' }\n\ninterface PreparedPath {\n readonly path: SyncPath\n readonly bytesHashed: number\n readonly bytesVerified: number\n readonly event?: SyncEvent\n readonly error?: Error\n readonly aborted: boolean\n}\n\nasync function prepareLocalPathSha1(\n path: SyncPath,\n options: PreparePairForCompareOptions,\n): Promise<PreparedPath> {\n if (!isLocalSyncPath(path)) {\n return { path, bytesHashed: 0, bytesVerified: 0, aborted: false }\n }\n\n if (options.signal?.aborted) return { path, bytesHashed: 0, bytesVerified: 0, aborted: true }\n\n try {\n const state = syncSha1StateOf(path)\n if (state.kind === 'verified') {\n return {\n path: { ...path, contentSha1: state.value },\n bytesHashed: 0,\n bytesVerified: 0,\n aborted: false,\n }\n }\n if (state.kind === 'unavailable') {\n return {\n path: { ...path, contentSha1: null },\n bytesHashed: 0,\n bytesVerified: 0,\n aborted: false,\n }\n }\n\n const readLocalSha1 = options.readLocalSha1\n if (readLocalSha1 === undefined) {\n return {\n path: { ...path, contentSha1: path.contentSha1 ?? null },\n bytesHashed: 0,\n bytesVerified: 0,\n aborted: false,\n }\n }\n const contentSha1 = await readLocalSha1(path, options.signal, {\n ...(options.sha1ReadTimeoutMillis !== undefined\n ? { timeoutMillis: options.sha1ReadTimeoutMillis }\n : {}),\n })\n return {\n path: {\n ...path,\n contentSha1,\n },\n bytesHashed: normalizeVerifiableSha1(contentSha1) === null ? 0 : path.size,\n bytesVerified: 0,\n aborted: false,\n }\n } catch (err) {\n if (options.signal?.aborted || isAbortError(err)) {\n return { path, bytesHashed: 0, bytesVerified: 0, aborted: true }\n }\n const error = toError(err)\n return {\n path,\n bytesHashed: 0,\n event: {\n type: 'error',\n path: path.relativePath,\n size: 0,\n message: `failed to hash local file for sha1 comparison: ${formatHashError(error)}`,\n },\n error,\n bytesVerified: 0,\n aborted: false,\n }\n }\n}\n\nasync function verifyB2Sha1Bytes(\n pair: SyncPair,\n options: PreparePairForCompareOptions & { readonly readB2Sha1: B2Sha1Reader },\n bytesHashed: number,\n): Promise<ComparePreparationResult> {\n const [source, dest] = pair\n /* v8 ignore next -- callers only verify B2 bytes for paired compare results */\n if (source === null || dest === null) return readyComparePair(pair, bytesHashed)\n\n const sourceResult = await prepareUntrustedB2PathSha1(source, options)\n const sourceBytesVerified = sourceResult.bytesVerified\n if (sourceResult.aborted) return aborted(pair)\n if (sourceResult.event) {\n return skipped(\n [sourceResult.path, dest],\n sourceResult.event,\n sourceResult.error,\n bytesHashed,\n sourceBytesVerified,\n )\n }\n\n const destResult = await prepareUntrustedB2PathSha1(dest, options)\n const bytesVerified = sourceBytesVerified + destResult.bytesVerified\n /* v8 ignore next -- destination abort mirrors the covered source abort path */\n if (destResult.aborted) return aborted([sourceResult.path, destResult.path])\n if (destResult.event) {\n return skipped(\n [sourceResult.path, destResult.path],\n destResult.event,\n destResult.error,\n bytesHashed,\n bytesVerified,\n )\n }\n\n return readyComparePair([sourceResult.path, destResult.path], bytesHashed, bytesVerified)\n}\n\nasync function prepareUntrustedB2PathSha1(\n path: SyncPath,\n options: PreparePairForCompareOptions & { readonly readB2Sha1: B2Sha1Reader },\n): Promise<PreparedPath> {\n if (!isB2SyncPath(path) || comparableSha1(path).kind !== 'untrusted') {\n return { path, bytesHashed: 0, bytesVerified: 0, aborted: false }\n }\n return prepareB2PathSha1(path, options)\n}\n\nasync function prepareB2PathSha1(\n path: B2SyncPath,\n options: PreparePairForCompareOptions & { readonly readB2Sha1: B2Sha1Reader },\n): Promise<PreparedPath> {\n /* v8 ignore next -- pre-aborted B2 reads are covered at pair level */\n if (options.signal?.aborted) return { path, bytesHashed: 0, bytesVerified: 0, aborted: true }\n\n try {\n const result = await options.readB2Sha1(path, options.signal)\n const contentSha1 = typeof result === 'object' && result !== null ? result.contentSha1 : result\n const bytesVerified =\n typeof result === 'object' && result !== null ? Math.max(0, result.bytesRead) : 0\n const preparedPath = {\n ...path,\n contentSha1,\n contentSha1State: syncSha1StateOf({ contentSha1 }),\n }\n if (contentSha1 === null) {\n return {\n path: preparedPath,\n bytesHashed: 0,\n bytesVerified,\n event: unavailableSha1PathEvent(path),\n aborted: false,\n }\n }\n return {\n path: preparedPath,\n bytesHashed: 0,\n bytesVerified,\n aborted: false,\n }\n } catch (err) {\n if (options.signal?.aborted || isAbortError(err)) {\n return { path, bytesHashed: 0, bytesVerified: 0, aborted: true }\n }\n const error = toError(err)\n return {\n path,\n bytesHashed: 0,\n bytesVerified: 0,\n event: {\n type: 'skip',\n path: path.relativePath,\n size: 0,\n message: `sha1 comparison skipped because B2 verification failed: ${formatHashError(error)}`,\n },\n aborted: false,\n }\n }\n}\n\nfunction comparableSha1(path: SyncPath): Sha1State {\n const state = syncSha1StateOf(path)\n if (state.kind === 'verified') return { kind: 'verified', value: state.value }\n if (state.kind === 'untrusted') return { kind: 'untrusted', value: state.value }\n return { kind: 'unavailable' }\n}\n\nfunction untrustedSha1CouldSuppressTransfer(source: Sha1State, dest: Sha1State): boolean {\n if (source.kind === 'untrusted' && dest.kind === 'verified') return source.value === dest.value\n if (dest.kind === 'untrusted' && source.kind === 'verified') return dest.value === source.value\n if (source.kind === 'untrusted' && dest.kind === 'untrusted') {\n return source.value !== null && source.value === dest.value\n }\n return false\n}\n\nfunction withB2ContentSha1(path: SyncPath): SyncPath {\n if (\n !isB2SyncPath(path) ||\n path.contentSha1 !== undefined ||\n path.contentSha1State !== undefined\n ) {\n return path\n }\n const contentSha1 = selectB2ComparableSha1(path.selectedVersion)\n return { ...path, contentSha1, contentSha1State: syncSha1StateOf({ contentSha1 }) }\n}\n\nfunction hasUnavailableB2Sha1(pair: SyncPair): boolean {\n const [source, dest] = pair\n return (\n (source !== null && isB2SyncPath(source) && comparableSha1(source).kind === 'unavailable') ||\n (dest !== null && isB2SyncPath(dest) && comparableSha1(dest).kind === 'unavailable')\n )\n}\n\nfunction hasUntrustedSha1(pair: SyncPair): boolean {\n const [source, dest] = pair\n return (\n (source !== null && comparableSha1(source).kind === 'untrusted') ||\n (dest !== null && comparableSha1(dest).kind === 'untrusted')\n )\n}\n\nfunction hasVerifiableUntrustedSha1(pair: SyncPair): boolean {\n const [source, dest] = pair\n return (\n (source !== null && verifiableUntrustedSha1(source)) ||\n (dest !== null && verifiableUntrustedSha1(dest))\n )\n}\n\nfunction verifiableUntrustedSha1(path: SyncPath): boolean {\n const state = comparableSha1(path)\n return state.kind === 'untrusted' && state.value !== null\n}\n\nfunction hasB2Path(pair: SyncPair): boolean {\n const [source, dest] = pair\n return (source !== null && isB2SyncPath(source)) || (dest !== null && isB2SyncPath(dest))\n}\n\nfunction isB2SyncPath(path: SyncPath): path is B2SyncPath {\n return 'selectedVersion' in path\n}\n\nfunction isLocalSyncPath(path: SyncPath): path is LocalSyncPath {\n return 'absolutePath' in path\n}\n\n/**\n * Creates a successful no-op compare preparation result for a pair.\n *\n * @param pair - Source/destination pair from {@link zipFolders}.\n * @param bytesHashed - Local file bytes read while preparing the pair.\n * @param bytesVerified - B2 bytes read while verifying untrusted SHA-1 metadata.\n *\n * @returns A ready preparation result that allows action generation.\n */\nexport function readyComparePair(\n pair: SyncPair,\n bytesHashed = 0,\n bytesVerified = 0,\n): ComparePreparationResult {\n return {\n pair,\n events: [],\n errors: [],\n bytesHashed,\n bytesVerified,\n skipActionGeneration: false,\n aborted: false,\n }\n}\n\nfunction skipped(\n pair: SyncPair,\n event: SyncEvent,\n error?: Error,\n bytesHashed = 0,\n bytesVerified = 0,\n): ComparePreparationResult {\n return {\n pair,\n events: [event],\n errors: error !== undefined ? [error] : [],\n bytesHashed,\n bytesVerified,\n skipActionGeneration: true,\n aborted: false,\n }\n}\n\nfunction aborted(pair: SyncPair): ComparePreparationResult {\n return {\n pair,\n events: [],\n errors: [],\n bytesHashed: 0,\n bytesVerified: 0,\n skipActionGeneration: true,\n aborted: true,\n }\n}\n\nfunction unavailableSha1Event(pair: SyncPair): SyncSkipEvent {\n /* v8 ignore next -- unavailable SHA-1 events always have at least one side */\n const path = (pair[0] ?? pair[1])?.relativePath ?? ''\n return unavailableSha1PathEvent({ relativePath: path })\n}\n\nfunction unavailableSha1PathEvent(path: Pick<SyncPath, 'relativePath'>): SyncSkipEvent {\n return {\n type: 'skip',\n path: path.relativePath,\n size: 0,\n message: 'sha1 comparison skipped because a verifiable SHA-1 is unavailable',\n }\n}\n\nfunction normalizeConcurrency(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value) || value < 1) return 1\n return Math.max(1, Math.floor(value))\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compare.cjs","names":[],"sources":["../../../src/sync/policies/compare.ts"],"sourcesContent":["import { mapConcurrent } from '../../upload/concurrency.ts'\nimport { isSignalAbortError } from '../../util/abort.ts'\nimport { normalizeVerifiableSha1 } from '../../util/sha1.ts'\nimport { toError } from '../../util/to-error.ts'\nimport { formatHashError, type LocalSha1Reader } from '../local-sha1.ts'\nimport type { SyncPair } from '../pairing.ts'\nimport { selectB2ComparableSha1, syncSha1StateOf } from '../sha1-metadata.ts'\nimport type {\n B2SyncPath,\n CompareMode,\n LocalSyncPath,\n SyncEvent,\n SyncPath,\n SyncSkipEvent,\n} from '../types.ts'\n\nexport { selectB2ComparableSha1 } from '../sha1-metadata.ts'\n\n/** Result from a B2 SHA-1 verification read. */\nexport interface B2Sha1ReadResult {\n /** SHA-1 digest of the selected B2 bytes, or null when unavailable. */\n readonly contentSha1: string | null\n /** Number of B2 bytes downloaded and hashed while verifying. */\n readonly bytesRead: number\n}\n\n/** Reads a B2 file and returns the SHA-1 digest of its actual bytes, or null when unavailable. */\nexport type B2Sha1Reader = (\n path: B2SyncPath,\n signal?: AbortSignal,\n) => Promise<string | null | B2Sha1ReadResult>\n\n/** Options for preparing a file pair before comparison. */\nexport interface PreparePairForCompareOptions {\n /** Signal used to abort local file hashing. */\n readonly signal?: AbortSignal\n /** Optional idle/no-progress timeout for local SHA-1 reads. */\n readonly sha1ReadTimeoutMillis?: number\n /** Optional local hashing override for tests or custom runtimes. */\n readonly readLocalSha1?: LocalSha1Reader\n /** Optional B2 hashing override used to verify metadata matches before skipping. */\n readonly readB2Sha1?: B2Sha1Reader\n}\n\n/** Options for preparing multiple file pairs before comparison. */\nexport interface PreparePairsForCompareOptions extends PreparePairForCompareOptions {\n /** Maximum number of file pairs to prepare concurrently. */\n readonly concurrency?: number\n}\n\n/** Result of preparing a file pair before policy comparison. */\nexport interface ComparePreparationResult {\n /** The pair with compare-mode metadata populated where possible. */\n readonly pair: SyncPair\n /** Events surfaced while preparing the pair, such as per-file hash errors or skips. */\n readonly events: readonly SyncEvent[]\n /** Errors surfaced while preparing the pair. These contribute to the final summary. */\n readonly errors: readonly Error[]\n /** Local file bytes read for hashing while preparing this pair. */\n readonly bytesHashed: number\n /** B2 bytes read for untrusted metadata verification while preparing this pair. */\n readonly bytesVerified: number\n /** Whether action generation should be skipped for this pair. */\n readonly skipActionGeneration: boolean\n /** Whether preparation stopped because the abort signal fired. */\n readonly aborted: boolean\n}\n\n/** A prepared pair result with the original pair retained for event context. */\nexport interface PreparedComparePair {\n /** Original pair from {@link zipFolders}. */\n readonly originalPair: SyncPair\n /** Preparation result for the original pair. */\n readonly prepared: ComparePreparationResult\n}\n\n/**\n * Determines whether two files should be considered different based on the compare mode.\n * For `sha1`, callers that use the low-level policy helpers should first prepare the pair so\n * local hashes and comparable B2 hashes are populated.\n *\n * @param source - The source file metadata.\n * @param dest - The destination file metadata.\n * @param compareMode - The comparison strategy: 'modtime', 'size', 'sha1', or 'none'.\n * @param threshold - Tolerance for the comparison (bytes for size, milliseconds for modtime).\n *\n * @returns `true` if the files are considered different.\n *\n * @throws When `compareMode` is not one of the supported compare modes.\n */\nexport function filesAreDifferent(\n source: SyncPath,\n dest: SyncPath,\n compareMode: CompareMode,\n threshold = 0,\n): boolean {\n switch (compareMode) {\n case 'none':\n return false\n case 'size':\n return Math.abs(source.size - dest.size) > threshold\n case 'sha1':\n return sha1ValuesAreDifferent(source, dest)\n case 'modtime':\n return Math.abs(source.modTimeMillis - dest.modTimeMillis) > threshold\n default:\n throw new Error(`Unsupported compare mode: ${String(compareMode)}`)\n }\n}\n\n/**\n * Throws when a runtime compare mode value is unsupported.\n *\n * @param compareMode - User-supplied compare mode.\n *\n * @throws When `compareMode` is not one of the supported values.\n */\nexport function assertSupportedCompareMode(\n compareMode: unknown,\n): asserts compareMode is CompareMode {\n switch (compareMode) {\n case 'none':\n case 'size':\n case 'sha1':\n case 'modtime':\n return\n default:\n throw new Error(`Unsupported compare mode: ${String(compareMode)}`)\n }\n}\n\nfunction sha1ValuesAreDifferent(source: SyncPath, dest: SyncPath): boolean {\n if (source.size !== dest.size) return true\n\n const sourceSha1 = comparableSha1(source)\n const destSha1 = comparableSha1(dest)\n if (sourceSha1.kind === 'untrusted' || destSha1.kind === 'untrusted') return true\n if (sourceSha1.kind === 'unavailable' || destSha1.kind === 'unavailable') return true\n return sourceSha1.value !== destSha1.value\n}\n\n/**\n * Prepares a pair for the selected compare mode.\n *\n * For `sha1`, this fills missing B2 hashes from comparable metadata and, when an explicit local\n * reader is supplied, hashes the local side only when size cannot already prove a difference.\n * Reader failures are converted into per-file sync events instead of aborting the whole run.\n *\n * @param pair - Source/destination pair from {@link zipFolders}.\n * @param compareMode - The comparison strategy.\n * @param options - Optional hashing dependencies and cancellation signal.\n *\n * @returns The prepared pair plus any preparation events.\n */\nexport async function preparePairForCompare(\n pair: SyncPair,\n compareMode: CompareMode,\n options: PreparePairForCompareOptions = {},\n): Promise<ComparePreparationResult> {\n assertSupportedCompareMode(compareMode)\n if (compareMode !== 'sha1') return readyComparePair(pair)\n\n const [source, dest] = pair\n if (source === null || dest === null) return readyComparePair(pair)\n if (source.size !== dest.size) return readyComparePair(pair)\n\n const metadataPair: SyncPair = [withB2ContentSha1(source), withB2ContentSha1(dest)]\n if (hasUnavailableB2Sha1(metadataPair)) {\n return skipped(metadataPair, unavailableSha1Event(metadataPair))\n }\n if (\n options.readB2Sha1 === undefined &&\n hasUntrustedSha1(metadataPair) &&\n !hasVerifiableUntrustedSha1(metadataPair)\n ) {\n return readyComparePair(metadataPair)\n }\n\n const [metadataSource, metadataDest] = metadataPair\n if (metadataSource === null || metadataDest === null) return readyComparePair(metadataPair)\n\n const sourceResult = await prepareLocalPathSha1(metadataSource, options)\n if (sourceResult.aborted) return aborted(metadataPair)\n if (sourceResult.event) {\n return skipped(metadataPair, sourceResult.event, sourceResult.error, sourceResult.bytesHashed)\n }\n\n const destResult = await prepareLocalPathSha1(metadataDest, options)\n if (destResult.aborted) return aborted([sourceResult.path, destResult.path])\n if (destResult.event) {\n return skipped(\n [sourceResult.path, destResult.path],\n destResult.event,\n destResult.error,\n sourceResult.bytesHashed,\n )\n }\n\n const preparedPair: SyncPair = [sourceResult.path, destResult.path]\n const sourceState = comparableSha1(sourceResult.path)\n const destState = comparableSha1(destResult.path)\n const bytesHashed = sourceResult.bytesHashed + destResult.bytesHashed\n\n if (sourceState.kind === 'unavailable' || destState.kind === 'unavailable') {\n return skipped(preparedPair, unavailableSha1Event(preparedPair), undefined, bytesHashed)\n }\n\n const shouldVerifyB2Bytes = untrustedSha1CouldSuppressTransfer(sourceState, destState)\n const readB2Sha1 = options.readB2Sha1\n if (shouldVerifyB2Bytes && hasB2Path(preparedPair) && readB2Sha1 !== undefined) {\n return verifyB2Sha1Bytes(preparedPair, { ...options, readB2Sha1 }, bytesHashed)\n }\n\n return readyComparePair(preparedPair, bytesHashed)\n}\n\n/**\n * Prepares a list of pairs for the selected compare mode with bounded concurrency.\n *\n * @param pairs - Source/destination pairs from {@link zipFolders}.\n * @param compareMode - The comparison strategy.\n * @param options - Optional hashing dependencies, cancellation signal, and concurrency.\n *\n * @returns Prepared results in the same order as the input pairs.\n */\nexport async function preparePairsForCompare(\n pairs: readonly SyncPair[],\n compareMode: CompareMode,\n options: PreparePairsForCompareOptions = {},\n): Promise<PreparedComparePair[]> {\n assertSupportedCompareMode(compareMode)\n if (compareMode !== 'sha1') {\n return pairs.map((pair) => ({ originalPair: pair, prepared: readyComparePair(pair) }))\n }\n\n const concurrency = normalizeConcurrency(options.concurrency)\n return mapConcurrent(pairs, concurrency, async (pair): Promise<PreparedComparePair> => {\n if (options.signal?.aborted) return { originalPair: pair, prepared: aborted(pair) }\n return {\n originalPair: pair,\n prepared: await preparePairForCompare(pair, compareMode, options),\n }\n })\n}\n\ntype Sha1State =\n | { readonly kind: 'verified'; readonly value: string }\n | { readonly kind: 'untrusted'; readonly value: string | null }\n | { readonly kind: 'unavailable' }\n\ninterface PreparedPath {\n readonly path: SyncPath\n readonly bytesHashed: number\n readonly bytesVerified: number\n readonly event?: SyncEvent\n readonly error?: Error\n readonly aborted: boolean\n}\n\nasync function prepareLocalPathSha1(\n path: SyncPath,\n options: PreparePairForCompareOptions,\n): Promise<PreparedPath> {\n if (!isLocalSyncPath(path)) {\n return { path, bytesHashed: 0, bytesVerified: 0, aborted: false }\n }\n\n if (options.signal?.aborted) return { path, bytesHashed: 0, bytesVerified: 0, aborted: true }\n\n try {\n const state = syncSha1StateOf(path)\n if (state.kind === 'verified') {\n return {\n path: { ...path, contentSha1: state.value },\n bytesHashed: 0,\n bytesVerified: 0,\n aborted: false,\n }\n }\n if (state.kind === 'unavailable') {\n return {\n path: { ...path, contentSha1: null },\n bytesHashed: 0,\n bytesVerified: 0,\n aborted: false,\n }\n }\n\n const readLocalSha1 = options.readLocalSha1\n if (readLocalSha1 === undefined) {\n return {\n path: { ...path, contentSha1: path.contentSha1 ?? null },\n bytesHashed: 0,\n bytesVerified: 0,\n aborted: false,\n }\n }\n const contentSha1 = await readLocalSha1(path, options.signal, {\n ...(options.sha1ReadTimeoutMillis !== undefined\n ? { timeoutMillis: options.sha1ReadTimeoutMillis }\n : {}),\n })\n return {\n path: {\n ...path,\n contentSha1,\n },\n bytesHashed: normalizeVerifiableSha1(contentSha1) === null ? 0 : path.size,\n bytesVerified: 0,\n aborted: false,\n }\n } catch (err) {\n if (isSignalAbortError(options.signal, err)) {\n return { path, bytesHashed: 0, bytesVerified: 0, aborted: true }\n }\n const error = toError(err)\n return {\n path,\n bytesHashed: 0,\n event: {\n type: 'error',\n path: path.relativePath,\n size: 0,\n message: `failed to hash local file for sha1 comparison: ${formatHashError(error)}`,\n },\n error,\n bytesVerified: 0,\n aborted: false,\n }\n }\n}\n\nasync function verifyB2Sha1Bytes(\n pair: SyncPair,\n options: PreparePairForCompareOptions & { readonly readB2Sha1: B2Sha1Reader },\n bytesHashed: number,\n): Promise<ComparePreparationResult> {\n const [source, dest] = pair\n /* v8 ignore next -- callers only verify B2 bytes for paired compare results */\n if (source === null || dest === null) return readyComparePair(pair, bytesHashed)\n\n const sourceResult = await prepareUntrustedB2PathSha1(source, options)\n const sourceBytesVerified = sourceResult.bytesVerified\n if (sourceResult.aborted) return aborted(pair)\n if (sourceResult.event) {\n return skipped(\n [sourceResult.path, dest],\n sourceResult.event,\n sourceResult.error,\n bytesHashed,\n sourceBytesVerified,\n )\n }\n\n const destResult = await prepareUntrustedB2PathSha1(dest, options)\n const bytesVerified = sourceBytesVerified + destResult.bytesVerified\n /* v8 ignore next -- destination abort mirrors the covered source abort path */\n if (destResult.aborted) return aborted([sourceResult.path, destResult.path])\n if (destResult.event) {\n return skipped(\n [sourceResult.path, destResult.path],\n destResult.event,\n destResult.error,\n bytesHashed,\n bytesVerified,\n )\n }\n\n return readyComparePair([sourceResult.path, destResult.path], bytesHashed, bytesVerified)\n}\n\nasync function prepareUntrustedB2PathSha1(\n path: SyncPath,\n options: PreparePairForCompareOptions & { readonly readB2Sha1: B2Sha1Reader },\n): Promise<PreparedPath> {\n if (!isB2SyncPath(path) || comparableSha1(path).kind !== 'untrusted') {\n return { path, bytesHashed: 0, bytesVerified: 0, aborted: false }\n }\n return prepareB2PathSha1(path, options)\n}\n\nasync function prepareB2PathSha1(\n path: B2SyncPath,\n options: PreparePairForCompareOptions & { readonly readB2Sha1: B2Sha1Reader },\n): Promise<PreparedPath> {\n /* v8 ignore next -- pre-aborted B2 reads are covered at pair level */\n if (options.signal?.aborted) return { path, bytesHashed: 0, bytesVerified: 0, aborted: true }\n\n try {\n const result = await options.readB2Sha1(path, options.signal)\n const contentSha1 = typeof result === 'object' && result !== null ? result.contentSha1 : result\n const bytesVerified =\n typeof result === 'object' && result !== null ? Math.max(0, result.bytesRead) : 0\n const preparedPath = {\n ...path,\n contentSha1,\n contentSha1State: syncSha1StateOf({ contentSha1 }),\n }\n if (contentSha1 === null) {\n return {\n path: preparedPath,\n bytesHashed: 0,\n bytesVerified,\n event: unavailableSha1PathEvent(path),\n aborted: false,\n }\n }\n return {\n path: preparedPath,\n bytesHashed: 0,\n bytesVerified,\n aborted: false,\n }\n } catch (err) {\n if (isSignalAbortError(options.signal, err)) {\n return { path, bytesHashed: 0, bytesVerified: 0, aborted: true }\n }\n const error = toError(err)\n return {\n path,\n bytesHashed: 0,\n bytesVerified: 0,\n event: {\n type: 'skip',\n path: path.relativePath,\n size: 0,\n message: `sha1 comparison skipped because B2 verification failed: ${formatHashError(error)}`,\n },\n aborted: false,\n }\n }\n}\n\nfunction comparableSha1(path: SyncPath): Sha1State {\n const state = syncSha1StateOf(path)\n if (state.kind === 'verified') return { kind: 'verified', value: state.value }\n if (state.kind === 'untrusted') return { kind: 'untrusted', value: state.value }\n return { kind: 'unavailable' }\n}\n\nfunction untrustedSha1CouldSuppressTransfer(source: Sha1State, dest: Sha1State): boolean {\n if (source.kind === 'untrusted' && dest.kind === 'verified') return source.value === dest.value\n if (dest.kind === 'untrusted' && source.kind === 'verified') return dest.value === source.value\n if (source.kind === 'untrusted' && dest.kind === 'untrusted') {\n return source.value !== null && source.value === dest.value\n }\n return false\n}\n\nfunction withB2ContentSha1(path: SyncPath): SyncPath {\n if (\n !isB2SyncPath(path) ||\n path.contentSha1 !== undefined ||\n path.contentSha1State !== undefined\n ) {\n return path\n }\n const contentSha1 = selectB2ComparableSha1(path.selectedVersion)\n return { ...path, contentSha1, contentSha1State: syncSha1StateOf({ contentSha1 }) }\n}\n\nfunction hasUnavailableB2Sha1(pair: SyncPair): boolean {\n const [source, dest] = pair\n return (\n (source !== null && isB2SyncPath(source) && comparableSha1(source).kind === 'unavailable') ||\n (dest !== null && isB2SyncPath(dest) && comparableSha1(dest).kind === 'unavailable')\n )\n}\n\nfunction hasUntrustedSha1(pair: SyncPair): boolean {\n const [source, dest] = pair\n return (\n (source !== null && comparableSha1(source).kind === 'untrusted') ||\n (dest !== null && comparableSha1(dest).kind === 'untrusted')\n )\n}\n\nfunction hasVerifiableUntrustedSha1(pair: SyncPair): boolean {\n const [source, dest] = pair\n return (\n (source !== null && verifiableUntrustedSha1(source)) ||\n (dest !== null && verifiableUntrustedSha1(dest))\n )\n}\n\nfunction verifiableUntrustedSha1(path: SyncPath): boolean {\n const state = comparableSha1(path)\n return state.kind === 'untrusted' && state.value !== null\n}\n\nfunction hasB2Path(pair: SyncPair): boolean {\n const [source, dest] = pair\n return (source !== null && isB2SyncPath(source)) || (dest !== null && isB2SyncPath(dest))\n}\n\nfunction isB2SyncPath(path: SyncPath): path is B2SyncPath {\n return 'selectedVersion' in path\n}\n\nfunction isLocalSyncPath(path: SyncPath): path is LocalSyncPath {\n return 'absolutePath' in path\n}\n\n/**\n * Creates a successful no-op compare preparation result for a pair.\n *\n * @param pair - Source/destination pair from {@link zipFolders}.\n * @param bytesHashed - Local file bytes read while preparing the pair.\n * @param bytesVerified - B2 bytes read while verifying untrusted SHA-1 metadata.\n *\n * @returns A ready preparation result that allows action generation.\n */\nexport function readyComparePair(\n pair: SyncPair,\n bytesHashed = 0,\n bytesVerified = 0,\n): ComparePreparationResult {\n return {\n pair,\n events: [],\n errors: [],\n bytesHashed,\n bytesVerified,\n skipActionGeneration: false,\n aborted: false,\n }\n}\n\nfunction skipped(\n pair: SyncPair,\n event: SyncEvent,\n error?: Error,\n bytesHashed = 0,\n bytesVerified = 0,\n): ComparePreparationResult {\n return {\n pair,\n events: [event],\n errors: error !== undefined ? [error] : [],\n bytesHashed,\n bytesVerified,\n skipActionGeneration: true,\n aborted: false,\n }\n}\n\nfunction aborted(pair: SyncPair): ComparePreparationResult {\n return {\n pair,\n events: [],\n errors: [],\n bytesHashed: 0,\n bytesVerified: 0,\n skipActionGeneration: true,\n aborted: true,\n }\n}\n\nfunction unavailableSha1Event(pair: SyncPair): SyncSkipEvent {\n /* v8 ignore next -- unavailable SHA-1 events always have at least one side */\n const path = (pair[0] ?? pair[1])?.relativePath ?? ''\n return unavailableSha1PathEvent({ relativePath: path })\n}\n\nfunction unavailableSha1PathEvent(path: Pick<SyncPath, 'relativePath'>): SyncSkipEvent {\n return {\n type: 'skip',\n path: path.relativePath,\n size: 0,\n message: 'sha1 comparison skipped because a verifiable SHA-1 is unavailable',\n }\n}\n\nfunction normalizeConcurrency(value: number | undefined): number {\n if (value === undefined || !Number.isFinite(value) || value < 1) return 1\n return Math.max(1, Math.floor(value))\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/sync/policies/compare.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/sync/policies/compare.js"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/sync/policies/compare.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/sync/policies/compare.js"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { mapConcurrent } from "../../upload/concurrency.js";
|
|
2
|
+
import { isSignalAbortError } from "../../util/abort.js";
|
|
2
3
|
import { normalizeVerifiableSha1 } from "../../util/sha1.js";
|
|
3
4
|
import { toError } from "../../util/to-error.js";
|
|
4
|
-
import { formatHashError
|
|
5
|
+
import { formatHashError } from "../local-sha1.js";
|
|
5
6
|
import { selectB2ComparableSha1, syncSha1StateOf } from "../sha1-metadata.js";
|
|
6
7
|
//#region src/sync/policies/compare.ts
|
|
7
8
|
/**
|
|
@@ -109,7 +110,8 @@ async function preparePairsForCompare(pairs, compareMode, options = {}) {
|
|
|
109
110
|
originalPair: pair,
|
|
110
111
|
prepared: readyComparePair(pair)
|
|
111
112
|
}));
|
|
112
|
-
|
|
113
|
+
const concurrency = normalizeConcurrency(options.concurrency);
|
|
114
|
+
return mapConcurrent(pairs, concurrency, async (pair) => {
|
|
113
115
|
if (options.signal?.aborted) return {
|
|
114
116
|
originalPair: pair,
|
|
115
117
|
prepared: aborted(pair)
|
|
@@ -174,7 +176,7 @@ async function prepareLocalPathSha1(path, options) {
|
|
|
174
176
|
aborted: false
|
|
175
177
|
};
|
|
176
178
|
} catch (err) {
|
|
177
|
-
if (options.signal
|
|
179
|
+
if (isSignalAbortError(options.signal, err)) return {
|
|
178
180
|
path,
|
|
179
181
|
bytesHashed: 0,
|
|
180
182
|
bytesVerified: 0,
|
|
@@ -251,7 +253,7 @@ async function prepareB2PathSha1(path, options) {
|
|
|
251
253
|
aborted: false
|
|
252
254
|
};
|
|
253
255
|
} catch (err) {
|
|
254
|
-
if (options.signal
|
|
256
|
+
if (isSignalAbortError(options.signal, err)) return {
|
|
255
257
|
path,
|
|
256
258
|
bytesHashed: 0,
|
|
257
259
|
bytesVerified: 0,
|