@finueva/drive 0.6.0 → 0.7.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @finueva/drive
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 77546b2: Use portable S3 Content-MD5 transport with mandatory independent server-side whole-file and part SHA-256 verification for all uploads. Descriptor requests require `contentMd5`; there is no legacy transport or profile selector. `completeUpload` and `uploadFile` may return HTTP 202 with a `verifying` result; callers can inspect read-only progress and retry completion with the original idempotency key, or explicitly abort the retained upload. No automatic unbounded polling is performed.
8
+
3
9
  ## 0.6.0
4
10
 
5
11
  ### Minor Changes
package/README.md CHANGED
@@ -44,6 +44,7 @@ const matches = await drive.searchWorkspaceItems({
44
44
  limit: 50,
45
45
  });
46
46
 
47
+ const completionIdempotencyKey = crypto.randomUUID();
47
48
  const uploaded = await drive.uploadFile({
48
49
  workspaceId: workspace.workspaceId,
49
50
  parentItemId: workspace.rootItemId,
@@ -51,7 +52,7 @@ const uploaded = await drive.uploadFile({
51
52
  displayFilename: file.name,
52
53
  mediaType: file.type || "application/octet-stream",
53
54
  idempotencyKey: crypto.randomUUID(),
54
- completionIdempotencyKey: crypto.randomUUID(),
55
+ completionIdempotencyKey,
55
56
  onProgress: ({ phase, confirmedByteLength, totalByteLength }) => {
56
57
  renderProgress(phase, confirmedByteLength, totalByteLength);
57
58
  },
@@ -126,15 +127,15 @@ Successful calls return `{ data, status, requestId, validators }`. A successful
126
127
 
127
128
  `createDownload` returns a short-lived archive descriptor for the current or an explicit immutable version, one visible `restore-pending` result for cold content, or a no-body `304` operation result whose validators retain the source ETag. Full, closed, open, and suffix ranges use the selected archive object's strong ETag; malformed or multiple ranges are served as full representations, while valid non-overlapping ranges fail with `range_not_satisfiable`. `downloadItem` follows a descriptor with no Drive credential, ambient browser credentials, or referrer and returns the provider body as a backpressured `Response`; it preserves the same `304` and cold-restore results without a provider request. It validates exact status, ETag, identity encoding, length, and `Content-Range`, cancels malformed upstream bodies, and keeps caller cancellation/deadline authority active until the stream closes or is cancelled. It never returns Blob, ArrayBuffer, text, or base64 whole-file convenience values.
128
129
 
129
- The six low-level upload methods map directly to the Native API. `createUpload` accepts `callerDeclaredContentDigest`, an ordinary whole-file `sha256:{64 lowercase hex}` value calculated or supplied by the caller. It is untrusted metadata, not provider verification evidence. `getUploadStatus` returns one bounded confirmed-part page and the current lifecycle/revision. Descriptor issuance accepts one base64 SHA-256 part checksum, `recordUploadPart` records exact provider ETag/checksum evidence and revision, `completeUpload` returns only a server-verified `ready` result, and `abortUpload` returns bodyless `204` success.
130
+ The six low-level upload methods map directly to the Native API. `createUpload` accepts a caller-declared whole-file `sha256:{64 lowercase hex}` digest. Portable S3 is the only supported upload transport, with no profile selector. Descriptor requests require `contentMd5` (canonical base64 MD5), and return a required `content-md5` header. Part SHA-256 declarations and opaque provider ETags remain separate callback fields; MD5 is transport error detection, not content identity.
130
131
 
131
- Provider part checksums and the provider's multipart composite checksum are verified server-side before publication. They are deliberately distinct from `callerDeclaredContentDigest`: multipart composite SHA-256 is not the ordinary SHA-256 of the complete file. Every low-level control obtains one credential, sends one request, validates exact IDs, checksums, ETags, and safe-integer bounds at runtime, and never retries automatically. `upload_recovery_required` is preserved as a canonical `DriveError` code.
132
+ Publication independently verifies archive bytes against both whole-file and part SHA-256 declarations. `getUploadStatus` exposes bounded confirmed-part pages and read-only verification progress once verification is admitted. `completeUpload` and `uploadFile` return `DriveOperationResult<UploadCompletion, 200 | 202>`: inspect `data.state` for `ready` versus `verifying`. A `202` is not publication. Retain its `uploadId` and the original completion idempotency key, inspect status, then call `completeUpload` again with that key when appropriate. The SDK does not start an unbounded polling loop. To cancel after a pending result, call `abortUpload({ workspaceId, uploadId })`, which returns bodyless `204`.
132
133
 
133
134
  `uploadFile` is the browser-safe direct-byte path for a Web `Blob` or `File`. It accepts zero-byte input, hashes the empty input correctly, accepts the server-mediated zero-byte mode, skips part transfer, and completes normally. Nonempty input is incrementally hashed in slices no larger than 32 MiB and is never materialized as a complete `ArrayBuffer`, Blob copy, base64 string, or SDK request body. The fixed policy permits at most 10,000 parts and 312.5 GiB.
134
135
 
135
- Each nonempty slice is sent directly to the exact descriptor URL. The request includes only descriptor-required headers, uses `credentials: "omit"`, `cache: "no-store"`, `redirect: "error"`, and `referrerPolicy: "no-referrer"`, and shares the configured cancellation/deadline bound. The archive CORS policy must expose both `ETag` and `x-amz-checksum-sha256`; missing, malformed, or mismatched values fail closed. Drive authorization, cookies, default headers, and file metadata never enter the archive request.
136
+ Each nonempty slice is sent directly to the exact descriptor URL. The SDK computes MD5 with the maintained Noble public API on the same bounded slice as SHA-256. Requests include only descriptor-required headers and use `credentials: "omit"`, `cache: "no-store"`, `redirect: "error"`, and `referrerPolicy: "no-referrer"`. Archive CORS must allow `content-md5` and expose `ETag`; no provider SHA response header is required, and ETags are never interpreted as hashes. If a Content-MD5 response header is exposed, it must match the request. Drive credentials, cookies and file metadata never enter the archive request.
136
137
 
137
- Repeating `uploadFile` with the same creation and completion idempotency keys explicitly resumes the retained session. After create/replay, the SDK reads status in pages of 100, bounded to 100 pages and 10,000 parts; validates session identity, mode, policy, lifecycle, revision, and pagination; re-hashes the supplied source; compares every confirmed part checksum; skips exact confirmed parts; and continues from the current revision. A matching `ready` status returns its exact ready projection. `completing` and `provider-completed` replay completion. Recovery-required and aborted states fail without pretending to resume.
138
+ Repeating `uploadFile` with the same creation and completion keys explicitly resumes the retained session when replay remains available. Status reads are bounded to 100 pages of 100 parts. The SDK checks session identity, policy, lifecycle, revisions and checksums, skips confirmed parts and never re-uploads a part merely because its callback response was lost. `completing`, `provider-completed` and `verifying` resume completion; failed/aborted/recovery-required states do not pretend to resume. After receiving pending, using its upload ID with low-level status/complete avoids re-hashing the source. Both normal and empty uploads may return pending, and progress observers can receive the `verifying` phase.
138
139
 
139
140
  There is no automatic network or provider retry. If a part-record callback response may have been lost, the SDK performs one bounded status reconciliation before either accepting the confirmed part or recording the same provider evidence once more; it never blindly re-uploads the bytes. If a completion response may have been lost, one status reconciliation returns success only when `ready` is proven. Other transient failures preserve the session for an explicit repeat until server expiry.
140
141
 
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { $ as UpdateItemInput, A as ListItemVersionsInput, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, I as ManagedItemVersionResource, J as RestoreItemInput, K as ReadyUpload, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as TrashItemInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, W as ProtectionClassification, Y as RestoreItemVersionInput, Z as SearchWorkspaceItemsInput, at as UploadFileProgressCallback, c as CurrentWorkspace, ct as UploadSession, d as DriveClient, dt as WorkspaceItemSearchPage, f as DriveClientConfig, it as UploadFileProgress, j as ManagedDownloadDescriptor, l as DeleteItemInput, lt as UploadStatus, m as DriveCredentialProvider, n as CompleteUploadInput, nt as UploadFileInput, o as CreateUploadInput, ot as UploadPartDescriptor, q as RecordUploadPartInput, r as CreateDownloadInput, rt as UploadFilePhase, s as CreateUploadPartDescriptorInput, st as UploadPartResult, t as AbortUploadInput, tt as UploadConfirmedPart, u as DownloadItemResult, ut as WorkspaceItemSearchItem, w as GetCurrentWorkspaceInput } from "./contract.js";
1
+ import { $ as TrashItemInput, A as ListItemVersionsInput, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, G as ProtectionClassification, I as ManagedItemVersionResource, J as RecordUploadPartInput, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as SearchWorkspaceItemsInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, X as RestoreItemVersionInput, Y as RestoreItemInput, at as UploadFilePhase, c as CurrentWorkspace, ct as UploadPartDescriptor, d as DriveClient, dt as UploadStatus, et as UpdateItemInput, f as DriveClientConfig, ft as WorkspaceItemSearchItem, it as UploadFileInput, j as ManagedDownloadDescriptor, l as DeleteItemInput, lt as UploadPartResult, m as DriveCredentialProvider, n as CompleteUploadInput, nt as UploadCompletion, o as CreateUploadInput, ot as UploadFileProgress, pt as WorkspaceItemSearchPage, q as ReadyUpload, r as CreateDownloadInput, rt as UploadConfirmedPart, s as CreateUploadPartDescriptorInput, st as UploadFileProgressCallback, t as AbortUploadInput, u as DownloadItemResult, ut as UploadSession, w as GetCurrentWorkspaceInput, z as PendingUpload } from "./contract.js";
2
2
  //#region src/client.d.ts
3
3
  declare function createDriveClient(config: DriveClientConfig): DriveClient;
4
4
  //#endregion
5
- export { type AbortUploadInput, type CompleteUploadInput, type CreateDownloadInput, type CreateUploadInput, type CreateUploadPartDescriptorInput, type CurrentWorkspace, type DeleteItemInput, type DownloadItemResult, type DriveClient, type DriveClientConfig, type DriveCredentialProvider, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type GetItemInput, type GetItemVersionInput, type GetUploadStatusInput, type ListFolderChildrenInput, type ListItemVersionsInput, type ManagedDownloadDescriptor, type ManagedDownloadRestorePending, type ManagedItemMetadata, type ManagedItemVersion, type ManagedItemVersionPage, type ManagedItemVersionResource, type ManagedItemVersionRestoreResult, type ManagedLifecycleItem, type ProtectionClassification, type ReadyUpload, type RecordUploadPartInput, type RestoreItemInput, type RestoreItemVersionInput, type SearchWorkspaceItemsInput, type TrashItemInput, type UpdateItemInput, type UploadConfirmedPart, type UploadFileInput, type UploadFilePhase, type UploadFileProgress, type UploadFileProgressCallback, type UploadPartDescriptor, type UploadPartResult, type UploadSession, type UploadStatus, type WorkspaceItemSearchItem, type WorkspaceItemSearchPage, createDriveClient };
5
+ export { type AbortUploadInput, type CompleteUploadInput, type CreateDownloadInput, type CreateUploadInput, type CreateUploadPartDescriptorInput, type CurrentWorkspace, type DeleteItemInput, type DownloadItemResult, type DriveClient, type DriveClientConfig, type DriveCredentialProvider, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type GetItemInput, type GetItemVersionInput, type GetUploadStatusInput, type ListFolderChildrenInput, type ListItemVersionsInput, type ManagedDownloadDescriptor, type ManagedDownloadRestorePending, type ManagedItemMetadata, type ManagedItemVersion, type ManagedItemVersionPage, type ManagedItemVersionResource, type ManagedItemVersionRestoreResult, type ManagedLifecycleItem, type PendingUpload, type ProtectionClassification, type ReadyUpload, type RecordUploadPartInput, type RestoreItemInput, type RestoreItemVersionInput, type SearchWorkspaceItemsInput, type TrashItemInput, type UpdateItemInput, type UploadCompletion, type UploadConfirmedPart, type UploadFileInput, type UploadFilePhase, type UploadFileProgress, type UploadFileProgressCallback, type UploadPartDescriptor, type UploadPartResult, type UploadSession, type UploadStatus, type WorkspaceItemSearchItem, type WorkspaceItemSearchPage, createDriveClient };
package/dist/client.js CHANGED
@@ -584,12 +584,14 @@ function isUploadStatus(value, afterPartNumber, limit) {
584
584
  "nextAfterPartNumber",
585
585
  "expiresAtEpochMilliseconds",
586
586
  "ready"
587
- ]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.test(value.versionId) || typeof value.uploadId !== "string" || !UPLOAD_ID$1.test(value.uploadId) || value.mode !== "presigned-multipart" && value.mode !== "server-mediated-zero-byte" || ![
587
+ ], ["verification"]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.test(value.versionId) || typeof value.uploadId !== "string" || !UPLOAD_ID$1.test(value.uploadId) || value.mode !== "presigned-multipart" && value.mode !== "server-mediated-zero-byte" || ![
588
588
  "initiating",
589
589
  "recovery-required",
590
590
  "uploading",
591
591
  "completing",
592
592
  "provider-completed",
593
+ "verifying",
594
+ "failed",
593
595
  "ready",
594
596
  "aborting",
595
597
  "aborted"
@@ -599,18 +601,38 @@ function isUploadStatus(value, afterPartNumber, limit) {
599
601
  "maxParts"
600
602
  ]) || value.partPolicy.partByteLength !== UPLOAD_PART_BYTE_LENGTH$2 || !isSafeInteger$1(value.partPolicy.partCount) || value.partPolicy.partCount > 1e4 || value.partPolicy.maxParts !== 1e4 || (value.mode === "server-mediated-zero-byte" ? value.partPolicy.partCount !== 0 : value.partPolicy.partCount < 1) || !Array.isArray(value.confirmedParts) || value.confirmedParts.length > limit || !isSafeInteger$1(value.expiresAtEpochMilliseconds)) return false;
601
603
  let previousPartNumber = afterPartNumber;
604
+ if (value.verification !== void 0) {
605
+ const progress = value.verification;
606
+ if (!isExactRecord(progress, [
607
+ "state",
608
+ "verifiedByteLength",
609
+ "totalByteLength",
610
+ "revision"
611
+ ]) || ![
612
+ "pending",
613
+ "verified",
614
+ "failed"
615
+ ].includes(String(progress.state)) || !isSafeInteger$1(progress.verifiedByteLength) || !isSafeInteger$1(progress.totalByteLength) || progress.totalByteLength > MAX_UPLOAD_BYTE_LENGTH$1 || progress.verifiedByteLength > progress.totalByteLength || !isSafeInteger$1(progress.revision) || progress.state === "verified" && progress.verifiedByteLength !== progress.totalByteLength) return false;
616
+ Object.freeze(progress);
617
+ }
618
+ if (["verifying", "failed"].includes(String(value.lifecycle)) && value.verification === void 0) return false;
602
619
  for (const part of value.confirmedParts) {
603
620
  if (!isExactRecord(part, ["partNumber", "checksumSha256"]) || !isSafeInteger$1(part.partNumber) || part.partNumber <= previousPartNumber || part.partNumber > value.partPolicy.partCount || !isPartChecksum$1(part.checksumSha256)) return false;
604
621
  previousPartNumber = part.partNumber;
605
622
  }
606
- if (!(value.nextAfterPartNumber === null || isSafeInteger$1(value.nextAfterPartNumber) && value.confirmedParts.length === limit && value.nextAfterPartNumber === previousPartNumber) || value.mode === "server-mediated-zero-byte" && (value.confirmedParts.length !== 0 || value.nextAfterPartNumber !== null) || value.lifecycle === "ready" !== (value.ready !== null) || value.ready !== null && (!isReadyUpload(value.ready, { uploadId: value.uploadId }) || value.ready.itemId !== value.itemId || value.ready.versionId !== value.versionId)) return false;
623
+ if (!(value.nextAfterPartNumber === null || isSafeInteger$1(value.nextAfterPartNumber) && value.confirmedParts.length === limit && value.nextAfterPartNumber === previousPartNumber) || value.mode === "server-mediated-zero-byte" && (value.confirmedParts.length !== 0 || value.nextAfterPartNumber !== null) || value.lifecycle === "ready" !== (value.ready !== null) || value.ready !== null && (!isReadyUpload(value.ready, { uploadId: value.uploadId }) || value.ready.itemId !== value.itemId || value.ready.versionId !== value.versionId || !isExactRecord(value.verification, [
624
+ "state",
625
+ "verifiedByteLength",
626
+ "totalByteLength",
627
+ "revision"
628
+ ]) || value.verification.state !== "verified" || value.verification.totalByteLength !== value.ready.byteLength)) return false;
607
629
  Object.freeze(value.partPolicy);
608
630
  for (const part of value.confirmedParts) Object.freeze(part);
609
631
  Object.freeze(value.confirmedParts);
610
632
  Object.freeze(value);
611
633
  return true;
612
634
  }
613
- function isUploadPartDescriptor(value, expectedPartNumber, checksumSha256, allowInsecureHttp) {
635
+ function isUploadPartDescriptor(value, expectedPartNumber, allowInsecureHttp, contentMd5) {
614
636
  if (!isExactRecord(value, [
615
637
  "url",
616
638
  "method",
@@ -618,7 +640,7 @@ function isUploadPartDescriptor(value, expectedPartNumber, checksumSha256, allow
618
640
  "partNumber",
619
641
  "expectedByteLength",
620
642
  "expiresAtEpochMilliseconds"
621
- ]) || !isSignedTransferUrl(value.url, allowInsecureHttp) || value.method !== "PUT" || !isExactRecord(value.headers, ["x-amz-checksum-sha256"]) || value.headers["x-amz-checksum-sha256"] !== checksumSha256 || value.partNumber !== expectedPartNumber || !isSafeInteger$1(value.expectedByteLength) || value.expectedByteLength < 1 || value.expectedByteLength > UPLOAD_PART_BYTE_LENGTH$2 || !isSafeInteger$1(value.expiresAtEpochMilliseconds) || value.expiresAtEpochMilliseconds <= Date.now()) return false;
643
+ ]) || !isSignedTransferUrl(value.url, allowInsecureHttp) || value.method !== "PUT" || !contentMd5 || !isExactRecord(value.headers, ["content-md5"]) || value.headers["content-md5"] !== contentMd5 || value.partNumber !== expectedPartNumber || !isSafeInteger$1(value.expectedByteLength) || value.expectedByteLength < 1 || value.expectedByteLength > UPLOAD_PART_BYTE_LENGTH$2 || !isSafeInteger$1(value.expiresAtEpochMilliseconds) || value.expiresAtEpochMilliseconds <= Date.now()) return false;
622
644
  Object.freeze(value.headers);
623
645
  Object.freeze(value);
624
646
  return true;
@@ -642,6 +664,19 @@ function isReadyUpload(value, expected) {
642
664
  Object.freeze(value);
643
665
  return true;
644
666
  }
667
+ function isPendingUpload(value, uploadId) {
668
+ if (!isExactRecord(value, [
669
+ "itemId",
670
+ "versionId",
671
+ "uploadId",
672
+ "state",
673
+ "verifiedByteLength",
674
+ "totalByteLength",
675
+ "verificationRevision"
676
+ ]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.test(value.versionId) || value.uploadId !== uploadId || value.state !== "verifying" || !isSafeInteger$1(value.verifiedByteLength) || !isSafeInteger$1(value.totalByteLength) || value.totalByteLength > MAX_UPLOAD_BYTE_LENGTH$1 || value.verifiedByteLength > value.totalByteLength || !isSafeInteger$1(value.verificationRevision)) return false;
677
+ Object.freeze(value);
678
+ return true;
679
+ }
645
680
  function isPartChecksum$1(value) {
646
681
  return typeof value === "string" && /^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/.test(value);
647
682
  }
@@ -781,9 +816,9 @@ function isSafeCapabilityUrl(value) {
781
816
  return false;
782
817
  }
783
818
  }
784
- function isExactRecord(value, keys) {
819
+ function isExactRecord(value, keys, optional = []) {
785
820
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
786
- return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
821
+ return Object.keys(value).every((key) => keys.includes(key) || optional.includes(key)) && keys.every((key) => Object.hasOwn(value, key));
787
822
  }
788
823
  //#endregion
789
824
  //#region src/internal/client/request.ts
@@ -1112,14 +1147,17 @@ function validateCreateUploadPartDescriptorInput(value) {
1112
1147
  "workspaceId",
1113
1148
  "uploadId",
1114
1149
  "partNumber",
1115
- "checksumSha256"
1150
+ "checksumSha256",
1151
+ "contentMd5"
1116
1152
  ], ["signal"]);
1117
1153
  const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
1118
1154
  if (!isPartNumber(input.partNumber) || !isPartChecksum(input.checksumSha256)) throw new DriveError("invalid_input");
1155
+ if (typeof input.contentMd5 !== "string" || !/^[A-Za-z0-9+/]{21}[AQgw]==$/.test(input.contentMd5)) throw new DriveError("invalid_input");
1119
1156
  return {
1120
1157
  ...upload,
1121
1158
  partNumber: input.partNumber,
1122
- checksumSha256: input.checksumSha256
1159
+ checksumSha256: input.checksumSha256,
1160
+ contentMd5: input.contentMd5
1123
1161
  };
1124
1162
  }
1125
1163
  function validateRecordUploadPartInput(value) {
@@ -2437,7 +2475,7 @@ async function getUploadStatus(runtime, input) {
2437
2475
  }
2438
2476
  } }),
2439
2477
  ...requestOptions
2440
- }), [200], (value) => isUploadStatus(value, afterPartNumber, limit), false, STATUS_ERROR_CODES);
2478
+ }), [200], (value) => isUploadStatus(value, afterPartNumber, limit) && value.uploadId === validated.uploadId, false, STATUS_ERROR_CODES);
2441
2479
  }
2442
2480
  async function createUploadPartDescriptor(runtime, input) {
2443
2481
  const validated = validateCreateUploadPartDescriptorInput(input);
@@ -2449,11 +2487,12 @@ async function createUploadPartDescriptor(runtime, input) {
2449
2487
  } },
2450
2488
  body: {
2451
2489
  partNumber: validated.partNumber,
2452
- checksumSha256: validated.checksumSha256
2490
+ checksumSha256: validated.checksumSha256,
2491
+ contentMd5: validated.contentMd5
2453
2492
  }
2454
2493
  }),
2455
2494
  ...requestOptions
2456
- }), [200], (value) => isUploadPartDescriptor(value, validated.partNumber, validated.checksumSha256, new URL(runtime.baseUrl).protocol === "http:"), false, TRANSFER_ERROR_CODES);
2495
+ }), [200], (value) => isUploadPartDescriptor(value, validated.partNumber, new URL(runtime.baseUrl).protocol === "http:", validated.contentMd5), false, TRANSFER_ERROR_CODES);
2457
2496
  }
2458
2497
  async function recordUploadPart(runtime, input) {
2459
2498
  const validated = validateRecordUploadPartInput(input);
@@ -2485,7 +2524,7 @@ async function completeUpload(runtime, input) {
2485
2524
  header: { "Idempotency-Key": validated.idempotencyKey }
2486
2525
  } }),
2487
2526
  ...requestOptions
2488
- }), [200], (value) => isReadyUpload(value, { uploadId: validated.uploadId }), false, COMPLETE_UPLOAD_ERROR_CODES);
2527
+ }), [200, 202], (value, status) => status === 202 ? isPendingUpload(value, validated.uploadId) : isReadyUpload(value, { uploadId: validated.uploadId }), false, COMPLETE_UPLOAD_ERROR_CODES);
2489
2528
  }
2490
2529
  async function abortUpload(runtime, input) {
2491
2530
  const validated = validateAbortUploadInput(input);
@@ -2549,6 +2588,9 @@ function createView(arr) {
2549
2588
  function rotr(word, shift) {
2550
2589
  return word << 32 - shift | word >>> shift;
2551
2590
  }
2591
+ function rotl(word, shift) {
2592
+ return word << shift | word >>> 32 - shift >>> 0;
2593
+ }
2552
2594
  const hasHexBuiltin = (() => typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function")();
2553
2595
  const hexes = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
2554
2596
  function bytesToHex(bytes) {
@@ -2860,6 +2902,115 @@ var _SHA256 = class extends SHA2_32B {
2860
2902
  };
2861
2903
  const sha256 = createHasher(() => new _SHA256(), oidNist(1));
2862
2904
  //#endregion
2905
+ //#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/legacy.js
2906
+ const SHA1_IV = Uint32Array.from([
2907
+ 1732584193,
2908
+ 4023233417,
2909
+ 2562383102,
2910
+ 271733878,
2911
+ 3285377520
2912
+ ]);
2913
+ const p32 = Math.pow(2, 32);
2914
+ const K = Array.from({ length: 64 }, (_, i) => Math.floor(p32 * Math.abs(Math.sin(i + 1))));
2915
+ const MD5_IV = SHA1_IV.slice(0, 4);
2916
+ const MD5_W = new Uint32Array(16);
2917
+ const MD5_SHIFTS = (() => {
2918
+ const S = [
2919
+ [
2920
+ 7,
2921
+ 12,
2922
+ 17,
2923
+ 22
2924
+ ],
2925
+ [
2926
+ 5,
2927
+ 9,
2928
+ 14,
2929
+ 20
2930
+ ],
2931
+ [
2932
+ 4,
2933
+ 11,
2934
+ 16,
2935
+ 23
2936
+ ],
2937
+ [
2938
+ 6,
2939
+ 10,
2940
+ 15,
2941
+ 21
2942
+ ]
2943
+ ];
2944
+ return Uint8Array.from({ length: 64 }, (_, i) => S[Math.floor(i / 16)][i % 4]);
2945
+ })();
2946
+ var _MD5 = class extends HashMD {
2947
+ A = MD5_IV[0] | 0;
2948
+ B = MD5_IV[1] | 0;
2949
+ C = MD5_IV[2] | 0;
2950
+ D = MD5_IV[3] | 0;
2951
+ constructor() {
2952
+ super(64, 16, 8, true);
2953
+ }
2954
+ get() {
2955
+ const { A, B, C, D } = this;
2956
+ return [
2957
+ A,
2958
+ B,
2959
+ C,
2960
+ D
2961
+ ];
2962
+ }
2963
+ set(A, B, C, D) {
2964
+ this.A = A | 0;
2965
+ this.B = B | 0;
2966
+ this.C = C | 0;
2967
+ this.D = D | 0;
2968
+ }
2969
+ _cloneInto(to) {
2970
+ (to ||= new this.constructor()).set(...this.get());
2971
+ return this._cloneIntoMeta(to);
2972
+ }
2973
+ process(view, offset) {
2974
+ for (let i = 0; i < 16; i++, offset += 4) MD5_W[i] = view.getUint32(offset, true);
2975
+ let { A, B, C, D } = this;
2976
+ for (let i = 0; i < 64; i++) {
2977
+ let F, g;
2978
+ if (i < 16) {
2979
+ F = Chi(B, C, D);
2980
+ g = i;
2981
+ } else if (i < 32) {
2982
+ F = Chi(D, B, C);
2983
+ g = (5 * i + 1) % 16;
2984
+ } else if (i < 48) {
2985
+ F = B ^ C ^ D;
2986
+ g = (3 * i + 5) % 16;
2987
+ } else {
2988
+ F = C ^ (B | ~D);
2989
+ g = 7 * i % 16;
2990
+ }
2991
+ F = F + A + K[i] + MD5_W[g];
2992
+ A = D;
2993
+ D = C;
2994
+ C = B;
2995
+ B = B + rotl(F, MD5_SHIFTS[i]);
2996
+ }
2997
+ A = A + this.A | 0;
2998
+ B = B + this.B | 0;
2999
+ C = C + this.C | 0;
3000
+ D = D + this.D | 0;
3001
+ this.set(A, B, C, D);
3002
+ }
3003
+ roundClean() {
3004
+ clean(MD5_W);
3005
+ }
3006
+ destroy() {
3007
+ this.destroyed = true;
3008
+ this.set(0, 0, 0, 0);
3009
+ clean(this.buffer);
3010
+ }
3011
+ };
3012
+ const md5 = createHasher(() => new _MD5());
3013
+ //#endregion
2863
3014
  //#region src/internal/client/upload.ts
2864
3015
  const UPLOAD_PART_BYTE_LENGTH = 32 * 1024 * 1024;
2865
3016
  const STATUS_PAGE_LIMIT = 100;
@@ -2907,6 +3058,7 @@ async function uploadFileInternal(runtime, input, controls) {
2907
3058
  uploadId: session.uploadId,
2908
3059
  partNumber,
2909
3060
  checksumSha256,
3061
+ contentMd5: digests.partMd5s[index],
2910
3062
  ...validated.signal === void 0 ? {} : { signal: validated.signal }
2911
3063
  });
2912
3064
  const descriptor = descriptorResult.data;
@@ -2914,14 +3066,16 @@ async function uploadFileInternal(runtime, input, controls) {
2914
3066
  status: descriptorResult.status,
2915
3067
  requestId: descriptorResult.requestId
2916
3068
  });
2917
- const etag = await putPart(runtime, descriptor, slicePart(validated.source, start, end, expectedByteLength), checksumSha256, validated.signal);
3069
+ const etag = await putPart(runtime, descriptor, slicePart(validated.source, start, end, expectedByteLength), validated.signal);
2918
3070
  revision = await recordPartWithReconciliation(controls, validated, session, partNumber, revision, expectedByteLength, etag, checksumSha256);
2919
3071
  confirmedByteLength += expectedByteLength;
2920
3072
  confirmedPartCount += 1;
2921
3073
  emitProgress(validated.onProgress, "uploading", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
2922
3074
  }
2923
3075
  emitProgress(validated.onProgress, "completing", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
2924
- return await completeWithReconciliation(controls, validated, session, digests);
3076
+ const completed = await completeWithReconciliation(controls, validated, session, digests);
3077
+ if (completed.data.state === "verifying") emitProgress(validated.onProgress, "verifying", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
3078
+ return completed;
2925
3079
  } catch (error) {
2926
3080
  if (validated.signal?.aborted && session) await bestEffortAbort(controls, validated.workspaceId, session.uploadId);
2927
3081
  if (error instanceof DriveError) throw error;
@@ -2977,6 +3131,7 @@ async function readResumeState(controls, input, session, digests) {
2977
3131
  if (session.mode === "presigned-multipart" && [
2978
3132
  "completing",
2979
3133
  "provider-completed",
3134
+ "verifying",
2980
3135
  "ready"
2981
3136
  ].includes(baseline.lifecycle) && confirmedParts.size !== session.partCount) throw new DriveError("invalid_response");
2982
3137
  failForTerminalStatus(baseline.lifecycle, baselineRequestId);
@@ -3033,7 +3188,8 @@ async function completeWithReconciliation(controls, input, session, digests) {
3033
3188
  idempotencyKey: input.completionIdempotencyKey,
3034
3189
  ...input.signal === void 0 ? {} : { signal: input.signal }
3035
3190
  });
3036
- assertReadyMatchesInput(completed.data, session, input, digests, completed.requestId);
3191
+ if (completed.data.state === "ready") assertReadyMatchesInput(completed.data, session, input, digests, completed.requestId);
3192
+ else if (completed.data.itemId !== session.itemId || completed.data.versionId !== session.versionId || completed.data.uploadId !== session.uploadId || completed.data.totalByteLength !== input.byteLength) throw new DriveError("invalid_response");
3037
3193
  return completed;
3038
3194
  } catch (error) {
3039
3195
  if (!isAmbiguousControlFailure(error) || input.signal?.aborted) throw error;
@@ -3054,6 +3210,7 @@ async function completeWithReconciliation(controls, input, session, digests) {
3054
3210
  async function hashSource(source, byteLength, partCount, signal) {
3055
3211
  const fullHash = sha256.create();
3056
3212
  const partChecksums = [];
3213
+ const partMd5s = [];
3057
3214
  for (let index = 0; index < partCount; index += 1) {
3058
3215
  throwIfCallerAborted(signal);
3059
3216
  const start = index * UPLOAD_PART_BYTE_LENGTH;
@@ -3070,13 +3227,15 @@ async function hashSource(source, byteLength, partCount, signal) {
3070
3227
  const bytes = new Uint8Array(buffer);
3071
3228
  fullHash.update(bytes);
3072
3229
  partChecksums.push(toBase64(sha256(bytes)));
3230
+ partMd5s.push(toBase64(md5(bytes)));
3073
3231
  }
3074
3232
  return Object.freeze({
3075
3233
  callerDeclaredContentDigest: `sha256:${bytesToHex(fullHash.digest())}`,
3076
- partChecksums: Object.freeze(partChecksums)
3234
+ partChecksums: Object.freeze(partChecksums),
3235
+ partMd5s: Object.freeze(partMd5s)
3077
3236
  });
3078
3237
  }
3079
- async function putPart(runtime, descriptor, part, checksumSha256, callerSignal) {
3238
+ async function putPart(runtime, descriptor, part, callerSignal) {
3080
3239
  const remainingMilliseconds = descriptor.expiresAtEpochMilliseconds - Date.now();
3081
3240
  if (remainingMilliseconds < 1) throw new DriveError("invalid_response");
3082
3241
  const operation = createOperationSignal(callerSignal, Math.min(runtime.timeoutMilliseconds, remainingMilliseconds));
@@ -3094,8 +3253,9 @@ async function putPart(runtime, descriptor, part, checksumSha256, callerSignal)
3094
3253
  }), operation.signal);
3095
3254
  if (!(response instanceof Response)) throw new DriveError("invalid_response");
3096
3255
  const etag = response.headers.get("etag");
3097
- const responseChecksum = response.headers.get("x-amz-checksum-sha256");
3098
- if (response.status < 200 || response.status > 299 || !isEtag(etag) || responseChecksum !== checksumSha256) throw new DriveError("invalid_response", { status: response.status });
3256
+ const md5Response = response.headers.get("content-md5");
3257
+ const checksumMatches = md5Response === null || md5Response === descriptor.headers["content-md5"];
3258
+ if (response.status < 200 || response.status > 299 || !isEtag(etag) || !checksumMatches) throw new DriveError("invalid_response", { status: response.status });
3099
3259
  return etag;
3100
3260
  } catch (error) {
3101
3261
  if (operation.didTimeout()) throw new DriveError("timeout");
@@ -3131,7 +3291,7 @@ function failForTerminalStatus(lifecycle, requestId) {
3131
3291
  status: 409,
3132
3292
  ...requestId === void 0 ? {} : { requestId }
3133
3293
  });
3134
- if (lifecycle === "aborting" || lifecycle === "aborted") throw new DriveError("precondition_failed", {
3294
+ if (lifecycle === "aborting" || lifecycle === "aborted" || lifecycle === "failed") throw new DriveError("precondition_failed", {
3135
3295
  status: 409,
3136
3296
  ...requestId === void 0 ? {} : { requestId }
3137
3297
  });
@@ -3759,7 +3759,7 @@ interface operations {
3759
3759
  expiresAtEpochMilliseconds: number;
3760
3760
  itemId: string;
3761
3761
  /** @enum {string} */
3762
- lifecycle: "initiating" | "recovery-required" | "uploading" | "completing" | "provider-completed" | "ready" | "aborting" | "aborted";
3762
+ lifecycle: "initiating" | "recovery-required" | "uploading" | "completing" | "provider-completed" | "verifying" | "failed" | "ready" | "aborting" | "aborted";
3763
3763
  /** @enum {string} */
3764
3764
  mode: "presigned-multipart" | "server-mediated-zero-byte";
3765
3765
  nextAfterPartNumber: number | null;
@@ -3772,7 +3772,7 @@ interface operations {
3772
3772
  };
3773
3773
  ready: {
3774
3774
  byteLength: number;
3775
- /** @description Caller-declared whole-file SHA-256 metadata; archive publication is gated by provider checksum evidence. */
3775
+ /** @description Caller-declared whole-file SHA-256. Portable profiles independently verify file bytes before publication; legacy profiles retain provider-checksum semantics. */
3776
3776
  callerDeclaredContentDigest: string;
3777
3777
  displayFilename: string;
3778
3778
  itemId: string;
@@ -3784,6 +3784,13 @@ interface operations {
3784
3784
  } | null;
3785
3785
  revision: number;
3786
3786
  uploadId: string;
3787
+ verification?: {
3788
+ revision: number;
3789
+ /** @enum {string} */
3790
+ state: "pending" | "verified" | "failed";
3791
+ totalByteLength: number;
3792
+ verifiedByteLength: number;
3793
+ };
3787
3794
  versionId: string;
3788
3795
  };
3789
3796
  };
@@ -4058,7 +4065,7 @@ interface operations {
4058
4065
  content: {
4059
4066
  "application/json": {
4060
4067
  byteLength: number;
4061
- /** @description Caller-declared whole-file SHA-256 metadata; archive publication is gated by provider checksum evidence. */
4068
+ /** @description Caller-declared whole-file SHA-256. Portable profiles independently verify file bytes before publication; legacy profiles retain provider-checksum semantics. */
4062
4069
  callerDeclaredContentDigest: string;
4063
4070
  displayFilename: string;
4064
4071
  itemId: string;
@@ -4070,6 +4077,24 @@ interface operations {
4070
4077
  };
4071
4078
  };
4072
4079
  };
4080
+ /** @description Archive verification is pending; retry completion with the same key. */
4081
+ 202: {
4082
+ headers: {
4083
+ [name: string]: unknown;
4084
+ };
4085
+ content: {
4086
+ "application/json": {
4087
+ itemId: string;
4088
+ /** @enum {string} */
4089
+ state: "verifying";
4090
+ totalByteLength: number;
4091
+ uploadId: string;
4092
+ verificationRevision: number;
4093
+ verifiedByteLength: number;
4094
+ versionId: string;
4095
+ };
4096
+ };
4097
+ };
4073
4098
  /** @description Authentication is required. */
4074
4099
  401: {
4075
4100
  headers: {
@@ -4221,6 +4246,7 @@ interface operations {
4221
4246
  content: {
4222
4247
  "application/json": {
4223
4248
  checksumSha256: string;
4249
+ contentMd5: string;
4224
4250
  partNumber: number;
4225
4251
  };
4226
4252
  };
@@ -4236,7 +4262,7 @@ interface operations {
4236
4262
  expectedByteLength: number;
4237
4263
  expiresAtEpochMilliseconds: number;
4238
4264
  headers: {
4239
- "x-amz-checksum-sha256": string;
4265
+ "content-md5": string;
4240
4266
  };
4241
4267
  /** @enum {string} */
4242
4268
  method: "PUT";
@@ -4594,6 +4620,8 @@ type UploadPartDescriptor = Readonly<Omit<JsonResponse<"createUploadPartDescript
4594
4620
  }>;
4595
4621
  type UploadPartResult = Readonly<JsonResponse<"recordUploadPart", 200>>;
4596
4622
  type ReadyUpload = Readonly<JsonResponse<"completeUpload", 200>>;
4623
+ type PendingUpload = Readonly<JsonResponse<"completeUpload", 202>>;
4624
+ type UploadCompletion = ReadyUpload | PendingUpload;
4597
4625
  type ManagedLifecycleItem = Readonly<JsonResponse<"updateItem", 200>>;
4598
4626
  type GeneratedManagedItemMetadata = JsonResponse<"getItem", 200>;
4599
4627
  type ManagedItemMetadata = Readonly<Omit<GeneratedManagedItemMetadata, "currentVersion"> & {
@@ -4620,10 +4648,11 @@ type ManagedDownloadDescriptor = Readonly<Omit<JsonResponse<"createDownload", 20
4620
4648
  type ManagedDownloadRestorePending = Readonly<JsonResponse<"createDownload", 202>>;
4621
4649
  type GeneratedUploadStatus = JsonResponse<"getUploadStatus", 200>;
4622
4650
  type UploadConfirmedPart = Readonly<GeneratedUploadStatus["confirmedParts"][number]>;
4623
- type UploadStatus = Readonly<Omit<GeneratedUploadStatus, "confirmedParts" | "partPolicy" | "ready"> & {
4651
+ type UploadStatus = Readonly<Omit<GeneratedUploadStatus, "confirmedParts" | "partPolicy" | "ready" | "verification"> & {
4624
4652
  readonly confirmedParts: readonly UploadConfirmedPart[];
4625
4653
  readonly partPolicy: Readonly<GeneratedUploadStatus["partPolicy"]>;
4626
4654
  readonly ready: ReadyUpload | null;
4655
+ readonly verification?: Readonly<NonNullable<GeneratedUploadStatus["verification"]>>;
4627
4656
  }>;
4628
4657
  type ProtectionClassification = CreateUploadBody["protectionClassification"];
4629
4658
  type PermissionAction = CreatePermissionBody["actions"][number];
@@ -4763,7 +4792,7 @@ type CreateDownloadInput = Readonly<CreateDownloadPath> & Readonly<CreateDownloa
4763
4792
  readonly signal?: AbortSignal;
4764
4793
  };
4765
4794
  type DownloadItemResult = Response | DriveOperationResult<ManagedDownloadRestorePending, 202> | DriveOperationResult<undefined, 304>;
4766
- type UploadFilePhase = "preparing" | "uploading" | "completing";
4795
+ type UploadFilePhase = "preparing" | "uploading" | "completing" | "verifying";
4767
4796
  interface UploadFileProgress {
4768
4797
  readonly phase: UploadFilePhase;
4769
4798
  readonly confirmedByteLength: number;
@@ -4811,12 +4840,12 @@ interface DriveOperations {
4811
4840
  getUploadStatus(input: GetUploadStatusInput): Promise<DriveOperationResult<UploadStatus, 200>>;
4812
4841
  createUploadPartDescriptor(input: CreateUploadPartDescriptorInput): Promise<DriveOperationResult<UploadPartDescriptor, 200>>;
4813
4842
  recordUploadPart(input: RecordUploadPartInput): Promise<DriveOperationResult<UploadPartResult, 200>>;
4814
- completeUpload(input: CompleteUploadInput): Promise<DriveOperationResult<ReadyUpload, 200>>;
4843
+ completeUpload(input: CompleteUploadInput): Promise<DriveOperationResult<UploadCompletion, 200 | 202>>;
4815
4844
  abortUpload(input: AbortUploadInput): Promise<DriveOperationResult<undefined, 204>>;
4816
4845
  }
4817
4846
  interface DriveServerClient extends DriveOperations {}
4818
4847
  interface DriveClient extends DriveOperations {
4819
- uploadFile(input: UploadFileInput): Promise<DriveOperationResult<ReadyUpload, 200>>;
4848
+ uploadFile(input: UploadFileInput): Promise<DriveOperationResult<UploadCompletion, 200 | 202>>;
4820
4849
  }
4821
4850
  //#endregion
4822
- export { UpdateItemInput as $, ListItemVersionsInput as A, PermissionGrant as B, FolderPage as C, GetUploadStatusInput as D, GetItemVersionInput as E, ManagedItemVersionPage as F, ReadEffectiveItemPermissionsInput as G, PermissionMutation as H, ManagedItemVersionResource as I, RestoreItemInput as J, ReadyUpload as K, ManagedItemVersionRestoreResult as L, ManagedDownloadRestorePending as M, ManagedItemMetadata as N, ListFolderChildrenInput as O, ManagedItemVersion as P, TrashItemInput as Q, ManagedLifecycleItem as R, FolderItem as S, GetItemInput as T, PermissionPage as U, PermissionGrantee as V, ProtectionClassification as W, RevokeItemPermissionInput as X, RestoreItemVersionInput as Y, SearchWorkspaceItemsInput as Z, DriveResponseValidators as _, CreateItemPermissionInput as a, UploadFileProgressCallback as at, EffectivePermissionAction as b, CurrentWorkspace as c, UploadSession as ct, DriveClient as d, WorkspaceItemSearchPage as dt, UpdateItemPermissionInput as et, DriveClientConfig as f, operations as ft, DriveOperations as g, DriveOperationResult as h, CreateFolderInput as i, UploadFileProgress as it, ManagedDownloadDescriptor as j, ListItemPermissionsInput as k, DeleteItemInput as l, UploadStatus as lt, DriveCredentialProvider as m, CompleteUploadInput as n, UploadFileInput as nt, CreateUploadInput as o, UploadPartDescriptor as ot, DriveCredentialContext as p, RecordUploadPartInput as q, CreateDownloadInput as r, UploadFilePhase as rt, CreateUploadPartDescriptorInput as s, UploadPartResult as st, AbortUploadInput as t, UploadConfirmedPart as tt, DownloadItemResult as u, WorkspaceItemSearchItem as ut, DriveServerClient as v, GetCurrentWorkspaceInput as w, EffectivePermissionResponse as x, DriveServerClientConfig as y, PermissionAction as z };
4851
+ export { TrashItemInput as $, ListItemVersionsInput as A, PermissionAction as B, FolderPage as C, GetUploadStatusInput as D, GetItemVersionInput as E, ManagedItemVersionPage as F, ProtectionClassification as G, PermissionGrantee as H, ManagedItemVersionResource as I, RecordUploadPartInput as J, ReadEffectiveItemPermissionsInput as K, ManagedItemVersionRestoreResult as L, ManagedDownloadRestorePending as M, ManagedItemMetadata as N, ListFolderChildrenInput as O, ManagedItemVersion as P, SearchWorkspaceItemsInput as Q, ManagedLifecycleItem as R, FolderItem as S, GetItemInput as T, PermissionMutation as U, PermissionGrant as V, PermissionPage as W, RestoreItemVersionInput as X, RestoreItemInput as Y, RevokeItemPermissionInput as Z, DriveResponseValidators as _, CreateItemPermissionInput as a, UploadFilePhase as at, EffectivePermissionAction as b, CurrentWorkspace as c, UploadPartDescriptor as ct, DriveClient as d, UploadStatus as dt, UpdateItemInput as et, DriveClientConfig as f, WorkspaceItemSearchItem as ft, DriveOperations as g, DriveOperationResult as h, CreateFolderInput as i, UploadFileInput as it, ManagedDownloadDescriptor as j, ListItemPermissionsInput as k, DeleteItemInput as l, UploadPartResult as lt, DriveCredentialProvider as m, operations as mt, CompleteUploadInput as n, UploadCompletion as nt, CreateUploadInput as o, UploadFileProgress as ot, DriveCredentialContext as p, WorkspaceItemSearchPage as pt, ReadyUpload as q, CreateDownloadInput as r, UploadConfirmedPart as rt, CreateUploadPartDescriptorInput as s, UploadFileProgressCallback as st, AbortUploadInput as t, UpdateItemPermissionInput as tt, DownloadItemResult as u, UploadSession as ut, DriveServerClient as v, GetCurrentWorkspaceInput as w, EffectivePermissionResponse as x, DriveServerClientConfig as y, PendingUpload as z };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as UpdateItemInput, A as ListItemVersionsInput, B as PermissionGrant, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, G as ReadEffectiveItemPermissionsInput, H as PermissionMutation, I as ManagedItemVersionResource, J as RestoreItemInput, K as ReadyUpload, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as TrashItemInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, V as PermissionGrantee, W as ProtectionClassification, X as RevokeItemPermissionInput, Y as RestoreItemVersionInput, Z as SearchWorkspaceItemsInput, _ as DriveResponseValidators, a as CreateItemPermissionInput, at as UploadFileProgressCallback, b as EffectivePermissionAction, c as CurrentWorkspace, ct as UploadSession, d as DriveClient, dt as WorkspaceItemSearchPage, et as UpdateItemPermissionInput, f as DriveClientConfig, g as DriveOperations, h as DriveOperationResult, i as CreateFolderInput, it as UploadFileProgress, j as ManagedDownloadDescriptor, k as ListItemPermissionsInput, l as DeleteItemInput, lt as UploadStatus, m as DriveCredentialProvider, n as CompleteUploadInput, nt as UploadFileInput, o as CreateUploadInput, ot as UploadPartDescriptor, q as RecordUploadPartInput, r as CreateDownloadInput, rt as UploadFilePhase, s as CreateUploadPartDescriptorInput, st as UploadPartResult, t as AbortUploadInput, tt as UploadConfirmedPart, u as DownloadItemResult, ut as WorkspaceItemSearchItem, w as GetCurrentWorkspaceInput, z as PermissionAction } from "./contract.js";
1
+ import { $ as TrashItemInput, A as ListItemVersionsInput, B as PermissionAction, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, G as ProtectionClassification, H as PermissionGrantee, I as ManagedItemVersionResource, J as RecordUploadPartInput, K as ReadEffectiveItemPermissionsInput, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as SearchWorkspaceItemsInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, U as PermissionMutation, V as PermissionGrant, X as RestoreItemVersionInput, Y as RestoreItemInput, Z as RevokeItemPermissionInput, _ as DriveResponseValidators, a as CreateItemPermissionInput, at as UploadFilePhase, b as EffectivePermissionAction, c as CurrentWorkspace, ct as UploadPartDescriptor, d as DriveClient, dt as UploadStatus, et as UpdateItemInput, f as DriveClientConfig, ft as WorkspaceItemSearchItem, g as DriveOperations, h as DriveOperationResult, i as CreateFolderInput, it as UploadFileInput, j as ManagedDownloadDescriptor, k as ListItemPermissionsInput, l as DeleteItemInput, lt as UploadPartResult, m as DriveCredentialProvider, n as CompleteUploadInput, nt as UploadCompletion, o as CreateUploadInput, ot as UploadFileProgress, pt as WorkspaceItemSearchPage, q as ReadyUpload, r as CreateDownloadInput, rt as UploadConfirmedPart, s as CreateUploadPartDescriptorInput, st as UploadFileProgressCallback, t as AbortUploadInput, tt as UpdateItemPermissionInput, u as DownloadItemResult, ut as UploadSession, w as GetCurrentWorkspaceInput, z as PendingUpload } from "./contract.js";
2
2
  import { createDriveClient } from "./client.js";
3
3
  import { DRIVE_API_ERROR_CODES, DRIVE_API_ERROR_MESSAGES, DriveApiErrorCode, DriveError, DriveErrorCode, DriveSdkErrorCode } from "./core.js";
4
- export { type AbortUploadInput, type CompleteUploadInput, type CreateDownloadInput, type CreateFolderInput, type CreateItemPermissionInput, type CreateUploadInput, type CreateUploadPartDescriptorInput, type CurrentWorkspace, DRIVE_API_ERROR_CODES, DRIVE_API_ERROR_MESSAGES, type DeleteItemInput, type DownloadItemResult, type DriveApiErrorCode, type DriveClient, type DriveClientConfig, type DriveCredentialProvider, DriveError, type DriveErrorCode, type DriveOperationResult, type DriveOperations, type DriveResponseValidators, type DriveSdkErrorCode, type EffectivePermissionAction, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type GetItemInput, type GetItemVersionInput, type GetUploadStatusInput, type ListFolderChildrenInput, type ListItemPermissionsInput, type ListItemVersionsInput, type ManagedDownloadDescriptor, type ManagedDownloadRestorePending, type ManagedItemMetadata, type ManagedItemVersion, type ManagedItemVersionPage, type ManagedItemVersionResource, type ManagedItemVersionRestoreResult, type ManagedLifecycleItem, type PermissionAction, type PermissionGrant, type PermissionGrantee, type PermissionMutation, type ProtectionClassification, type ReadEffectiveItemPermissionsInput, type ReadyUpload, type RecordUploadPartInput, type RestoreItemInput, type RestoreItemVersionInput, type RevokeItemPermissionInput, type SearchWorkspaceItemsInput, type TrashItemInput, type UpdateItemInput, type UpdateItemPermissionInput, type UploadConfirmedPart, type UploadFileInput, type UploadFilePhase, type UploadFileProgress, type UploadFileProgressCallback, type UploadPartDescriptor, type UploadPartResult, type UploadSession, type UploadStatus, type WorkspaceItemSearchItem, type WorkspaceItemSearchPage, createDriveClient };
4
+ export { type AbortUploadInput, type CompleteUploadInput, type CreateDownloadInput, type CreateFolderInput, type CreateItemPermissionInput, type CreateUploadInput, type CreateUploadPartDescriptorInput, type CurrentWorkspace, DRIVE_API_ERROR_CODES, DRIVE_API_ERROR_MESSAGES, type DeleteItemInput, type DownloadItemResult, type DriveApiErrorCode, type DriveClient, type DriveClientConfig, type DriveCredentialProvider, DriveError, type DriveErrorCode, type DriveOperationResult, type DriveOperations, type DriveResponseValidators, type DriveSdkErrorCode, type EffectivePermissionAction, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type GetItemInput, type GetItemVersionInput, type GetUploadStatusInput, type ListFolderChildrenInput, type ListItemPermissionsInput, type ListItemVersionsInput, type ManagedDownloadDescriptor, type ManagedDownloadRestorePending, type ManagedItemMetadata, type ManagedItemVersion, type ManagedItemVersionPage, type ManagedItemVersionResource, type ManagedItemVersionRestoreResult, type ManagedLifecycleItem, type PendingUpload, type PermissionAction, type PermissionGrant, type PermissionGrantee, type PermissionMutation, type ProtectionClassification, type ReadEffectiveItemPermissionsInput, type ReadyUpload, type RecordUploadPartInput, type RestoreItemInput, type RestoreItemVersionInput, type RevokeItemPermissionInput, type SearchWorkspaceItemsInput, type TrashItemInput, type UpdateItemInput, type UpdateItemPermissionInput, type UploadCompletion, type UploadConfirmedPart, type UploadFileInput, type UploadFilePhase, type UploadFileProgress, type UploadFileProgressCallback, type UploadPartDescriptor, type UploadPartResult, type UploadSession, type UploadStatus, type WorkspaceItemSearchItem, type WorkspaceItemSearchPage, createDriveClient };
package/dist/index.js CHANGED
@@ -584,12 +584,14 @@ function isUploadStatus(value, afterPartNumber, limit) {
584
584
  "nextAfterPartNumber",
585
585
  "expiresAtEpochMilliseconds",
586
586
  "ready"
587
- ]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.test(value.versionId) || typeof value.uploadId !== "string" || !UPLOAD_ID$1.test(value.uploadId) || value.mode !== "presigned-multipart" && value.mode !== "server-mediated-zero-byte" || ![
587
+ ], ["verification"]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.test(value.versionId) || typeof value.uploadId !== "string" || !UPLOAD_ID$1.test(value.uploadId) || value.mode !== "presigned-multipart" && value.mode !== "server-mediated-zero-byte" || ![
588
588
  "initiating",
589
589
  "recovery-required",
590
590
  "uploading",
591
591
  "completing",
592
592
  "provider-completed",
593
+ "verifying",
594
+ "failed",
593
595
  "ready",
594
596
  "aborting",
595
597
  "aborted"
@@ -599,18 +601,38 @@ function isUploadStatus(value, afterPartNumber, limit) {
599
601
  "maxParts"
600
602
  ]) || value.partPolicy.partByteLength !== UPLOAD_PART_BYTE_LENGTH$2 || !isSafeInteger$1(value.partPolicy.partCount) || value.partPolicy.partCount > 1e4 || value.partPolicy.maxParts !== 1e4 || (value.mode === "server-mediated-zero-byte" ? value.partPolicy.partCount !== 0 : value.partPolicy.partCount < 1) || !Array.isArray(value.confirmedParts) || value.confirmedParts.length > limit || !isSafeInteger$1(value.expiresAtEpochMilliseconds)) return false;
601
603
  let previousPartNumber = afterPartNumber;
604
+ if (value.verification !== void 0) {
605
+ const progress = value.verification;
606
+ if (!isExactRecord(progress, [
607
+ "state",
608
+ "verifiedByteLength",
609
+ "totalByteLength",
610
+ "revision"
611
+ ]) || ![
612
+ "pending",
613
+ "verified",
614
+ "failed"
615
+ ].includes(String(progress.state)) || !isSafeInteger$1(progress.verifiedByteLength) || !isSafeInteger$1(progress.totalByteLength) || progress.totalByteLength > MAX_UPLOAD_BYTE_LENGTH$1 || progress.verifiedByteLength > progress.totalByteLength || !isSafeInteger$1(progress.revision) || progress.state === "verified" && progress.verifiedByteLength !== progress.totalByteLength) return false;
616
+ Object.freeze(progress);
617
+ }
618
+ if (["verifying", "failed"].includes(String(value.lifecycle)) && value.verification === void 0) return false;
602
619
  for (const part of value.confirmedParts) {
603
620
  if (!isExactRecord(part, ["partNumber", "checksumSha256"]) || !isSafeInteger$1(part.partNumber) || part.partNumber <= previousPartNumber || part.partNumber > value.partPolicy.partCount || !isPartChecksum$1(part.checksumSha256)) return false;
604
621
  previousPartNumber = part.partNumber;
605
622
  }
606
- if (!(value.nextAfterPartNumber === null || isSafeInteger$1(value.nextAfterPartNumber) && value.confirmedParts.length === limit && value.nextAfterPartNumber === previousPartNumber) || value.mode === "server-mediated-zero-byte" && (value.confirmedParts.length !== 0 || value.nextAfterPartNumber !== null) || value.lifecycle === "ready" !== (value.ready !== null) || value.ready !== null && (!isReadyUpload(value.ready, { uploadId: value.uploadId }) || value.ready.itemId !== value.itemId || value.ready.versionId !== value.versionId)) return false;
623
+ if (!(value.nextAfterPartNumber === null || isSafeInteger$1(value.nextAfterPartNumber) && value.confirmedParts.length === limit && value.nextAfterPartNumber === previousPartNumber) || value.mode === "server-mediated-zero-byte" && (value.confirmedParts.length !== 0 || value.nextAfterPartNumber !== null) || value.lifecycle === "ready" !== (value.ready !== null) || value.ready !== null && (!isReadyUpload(value.ready, { uploadId: value.uploadId }) || value.ready.itemId !== value.itemId || value.ready.versionId !== value.versionId || !isExactRecord(value.verification, [
624
+ "state",
625
+ "verifiedByteLength",
626
+ "totalByteLength",
627
+ "revision"
628
+ ]) || value.verification.state !== "verified" || value.verification.totalByteLength !== value.ready.byteLength)) return false;
607
629
  Object.freeze(value.partPolicy);
608
630
  for (const part of value.confirmedParts) Object.freeze(part);
609
631
  Object.freeze(value.confirmedParts);
610
632
  Object.freeze(value);
611
633
  return true;
612
634
  }
613
- function isUploadPartDescriptor(value, expectedPartNumber, checksumSha256, allowInsecureHttp) {
635
+ function isUploadPartDescriptor(value, expectedPartNumber, allowInsecureHttp, contentMd5) {
614
636
  if (!isExactRecord(value, [
615
637
  "url",
616
638
  "method",
@@ -618,7 +640,7 @@ function isUploadPartDescriptor(value, expectedPartNumber, checksumSha256, allow
618
640
  "partNumber",
619
641
  "expectedByteLength",
620
642
  "expiresAtEpochMilliseconds"
621
- ]) || !isSignedTransferUrl(value.url, allowInsecureHttp) || value.method !== "PUT" || !isExactRecord(value.headers, ["x-amz-checksum-sha256"]) || value.headers["x-amz-checksum-sha256"] !== checksumSha256 || value.partNumber !== expectedPartNumber || !isSafeInteger$1(value.expectedByteLength) || value.expectedByteLength < 1 || value.expectedByteLength > UPLOAD_PART_BYTE_LENGTH$2 || !isSafeInteger$1(value.expiresAtEpochMilliseconds) || value.expiresAtEpochMilliseconds <= Date.now()) return false;
643
+ ]) || !isSignedTransferUrl(value.url, allowInsecureHttp) || value.method !== "PUT" || !contentMd5 || !isExactRecord(value.headers, ["content-md5"]) || value.headers["content-md5"] !== contentMd5 || value.partNumber !== expectedPartNumber || !isSafeInteger$1(value.expectedByteLength) || value.expectedByteLength < 1 || value.expectedByteLength > UPLOAD_PART_BYTE_LENGTH$2 || !isSafeInteger$1(value.expiresAtEpochMilliseconds) || value.expiresAtEpochMilliseconds <= Date.now()) return false;
622
644
  Object.freeze(value.headers);
623
645
  Object.freeze(value);
624
646
  return true;
@@ -642,6 +664,19 @@ function isReadyUpload(value, expected) {
642
664
  Object.freeze(value);
643
665
  return true;
644
666
  }
667
+ function isPendingUpload(value, uploadId) {
668
+ if (!isExactRecord(value, [
669
+ "itemId",
670
+ "versionId",
671
+ "uploadId",
672
+ "state",
673
+ "verifiedByteLength",
674
+ "totalByteLength",
675
+ "verificationRevision"
676
+ ]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.test(value.versionId) || value.uploadId !== uploadId || value.state !== "verifying" || !isSafeInteger$1(value.verifiedByteLength) || !isSafeInteger$1(value.totalByteLength) || value.totalByteLength > MAX_UPLOAD_BYTE_LENGTH$1 || value.verifiedByteLength > value.totalByteLength || !isSafeInteger$1(value.verificationRevision)) return false;
677
+ Object.freeze(value);
678
+ return true;
679
+ }
645
680
  function isPartChecksum$1(value) {
646
681
  return typeof value === "string" && /^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/.test(value);
647
682
  }
@@ -781,9 +816,9 @@ function isSafeCapabilityUrl(value) {
781
816
  return false;
782
817
  }
783
818
  }
784
- function isExactRecord(value, keys) {
819
+ function isExactRecord(value, keys, optional = []) {
785
820
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
786
- return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
821
+ return Object.keys(value).every((key) => keys.includes(key) || optional.includes(key)) && keys.every((key) => Object.hasOwn(value, key));
787
822
  }
788
823
  //#endregion
789
824
  //#region src/internal/client/request.ts
@@ -1112,14 +1147,17 @@ function validateCreateUploadPartDescriptorInput(value) {
1112
1147
  "workspaceId",
1113
1148
  "uploadId",
1114
1149
  "partNumber",
1115
- "checksumSha256"
1150
+ "checksumSha256",
1151
+ "contentMd5"
1116
1152
  ], ["signal"]);
1117
1153
  const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
1118
1154
  if (!isPartNumber(input.partNumber) || !isPartChecksum(input.checksumSha256)) throw new DriveError("invalid_input");
1155
+ if (typeof input.contentMd5 !== "string" || !/^[A-Za-z0-9+/]{21}[AQgw]==$/.test(input.contentMd5)) throw new DriveError("invalid_input");
1119
1156
  return {
1120
1157
  ...upload,
1121
1158
  partNumber: input.partNumber,
1122
- checksumSha256: input.checksumSha256
1159
+ checksumSha256: input.checksumSha256,
1160
+ contentMd5: input.contentMd5
1123
1161
  };
1124
1162
  }
1125
1163
  function validateRecordUploadPartInput(value) {
@@ -2437,7 +2475,7 @@ async function getUploadStatus(runtime, input) {
2437
2475
  }
2438
2476
  } }),
2439
2477
  ...requestOptions
2440
- }), [200], (value) => isUploadStatus(value, afterPartNumber, limit), false, STATUS_ERROR_CODES);
2478
+ }), [200], (value) => isUploadStatus(value, afterPartNumber, limit) && value.uploadId === validated.uploadId, false, STATUS_ERROR_CODES);
2441
2479
  }
2442
2480
  async function createUploadPartDescriptor(runtime, input) {
2443
2481
  const validated = validateCreateUploadPartDescriptorInput(input);
@@ -2449,11 +2487,12 @@ async function createUploadPartDescriptor(runtime, input) {
2449
2487
  } },
2450
2488
  body: {
2451
2489
  partNumber: validated.partNumber,
2452
- checksumSha256: validated.checksumSha256
2490
+ checksumSha256: validated.checksumSha256,
2491
+ contentMd5: validated.contentMd5
2453
2492
  }
2454
2493
  }),
2455
2494
  ...requestOptions
2456
- }), [200], (value) => isUploadPartDescriptor(value, validated.partNumber, validated.checksumSha256, new URL(runtime.baseUrl).protocol === "http:"), false, TRANSFER_ERROR_CODES);
2495
+ }), [200], (value) => isUploadPartDescriptor(value, validated.partNumber, new URL(runtime.baseUrl).protocol === "http:", validated.contentMd5), false, TRANSFER_ERROR_CODES);
2457
2496
  }
2458
2497
  async function recordUploadPart(runtime, input) {
2459
2498
  const validated = validateRecordUploadPartInput(input);
@@ -2485,7 +2524,7 @@ async function completeUpload(runtime, input) {
2485
2524
  header: { "Idempotency-Key": validated.idempotencyKey }
2486
2525
  } }),
2487
2526
  ...requestOptions
2488
- }), [200], (value) => isReadyUpload(value, { uploadId: validated.uploadId }), false, COMPLETE_UPLOAD_ERROR_CODES);
2527
+ }), [200, 202], (value, status) => status === 202 ? isPendingUpload(value, validated.uploadId) : isReadyUpload(value, { uploadId: validated.uploadId }), false, COMPLETE_UPLOAD_ERROR_CODES);
2489
2528
  }
2490
2529
  async function abortUpload(runtime, input) {
2491
2530
  const validated = validateAbortUploadInput(input);
@@ -2549,6 +2588,9 @@ function createView(arr) {
2549
2588
  function rotr(word, shift) {
2550
2589
  return word << 32 - shift | word >>> shift;
2551
2590
  }
2591
+ function rotl(word, shift) {
2592
+ return word << shift | word >>> 32 - shift >>> 0;
2593
+ }
2552
2594
  const hasHexBuiltin = (() => typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function")();
2553
2595
  const hexes = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
2554
2596
  function bytesToHex(bytes) {
@@ -2860,6 +2902,115 @@ var _SHA256 = class extends SHA2_32B {
2860
2902
  };
2861
2903
  const sha256 = createHasher(() => new _SHA256(), oidNist(1));
2862
2904
  //#endregion
2905
+ //#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/legacy.js
2906
+ const SHA1_IV = Uint32Array.from([
2907
+ 1732584193,
2908
+ 4023233417,
2909
+ 2562383102,
2910
+ 271733878,
2911
+ 3285377520
2912
+ ]);
2913
+ const p32 = Math.pow(2, 32);
2914
+ const K = Array.from({ length: 64 }, (_, i) => Math.floor(p32 * Math.abs(Math.sin(i + 1))));
2915
+ const MD5_IV = SHA1_IV.slice(0, 4);
2916
+ const MD5_W = new Uint32Array(16);
2917
+ const MD5_SHIFTS = (() => {
2918
+ const S = [
2919
+ [
2920
+ 7,
2921
+ 12,
2922
+ 17,
2923
+ 22
2924
+ ],
2925
+ [
2926
+ 5,
2927
+ 9,
2928
+ 14,
2929
+ 20
2930
+ ],
2931
+ [
2932
+ 4,
2933
+ 11,
2934
+ 16,
2935
+ 23
2936
+ ],
2937
+ [
2938
+ 6,
2939
+ 10,
2940
+ 15,
2941
+ 21
2942
+ ]
2943
+ ];
2944
+ return Uint8Array.from({ length: 64 }, (_, i) => S[Math.floor(i / 16)][i % 4]);
2945
+ })();
2946
+ var _MD5 = class extends HashMD {
2947
+ A = MD5_IV[0] | 0;
2948
+ B = MD5_IV[1] | 0;
2949
+ C = MD5_IV[2] | 0;
2950
+ D = MD5_IV[3] | 0;
2951
+ constructor() {
2952
+ super(64, 16, 8, true);
2953
+ }
2954
+ get() {
2955
+ const { A, B, C, D } = this;
2956
+ return [
2957
+ A,
2958
+ B,
2959
+ C,
2960
+ D
2961
+ ];
2962
+ }
2963
+ set(A, B, C, D) {
2964
+ this.A = A | 0;
2965
+ this.B = B | 0;
2966
+ this.C = C | 0;
2967
+ this.D = D | 0;
2968
+ }
2969
+ _cloneInto(to) {
2970
+ (to ||= new this.constructor()).set(...this.get());
2971
+ return this._cloneIntoMeta(to);
2972
+ }
2973
+ process(view, offset) {
2974
+ for (let i = 0; i < 16; i++, offset += 4) MD5_W[i] = view.getUint32(offset, true);
2975
+ let { A, B, C, D } = this;
2976
+ for (let i = 0; i < 64; i++) {
2977
+ let F, g;
2978
+ if (i < 16) {
2979
+ F = Chi(B, C, D);
2980
+ g = i;
2981
+ } else if (i < 32) {
2982
+ F = Chi(D, B, C);
2983
+ g = (5 * i + 1) % 16;
2984
+ } else if (i < 48) {
2985
+ F = B ^ C ^ D;
2986
+ g = (3 * i + 5) % 16;
2987
+ } else {
2988
+ F = C ^ (B | ~D);
2989
+ g = 7 * i % 16;
2990
+ }
2991
+ F = F + A + K[i] + MD5_W[g];
2992
+ A = D;
2993
+ D = C;
2994
+ C = B;
2995
+ B = B + rotl(F, MD5_SHIFTS[i]);
2996
+ }
2997
+ A = A + this.A | 0;
2998
+ B = B + this.B | 0;
2999
+ C = C + this.C | 0;
3000
+ D = D + this.D | 0;
3001
+ this.set(A, B, C, D);
3002
+ }
3003
+ roundClean() {
3004
+ clean(MD5_W);
3005
+ }
3006
+ destroy() {
3007
+ this.destroyed = true;
3008
+ this.set(0, 0, 0, 0);
3009
+ clean(this.buffer);
3010
+ }
3011
+ };
3012
+ const md5 = createHasher(() => new _MD5());
3013
+ //#endregion
2863
3014
  //#region src/internal/client/upload.ts
2864
3015
  const UPLOAD_PART_BYTE_LENGTH = 32 * 1024 * 1024;
2865
3016
  const STATUS_PAGE_LIMIT = 100;
@@ -2907,6 +3058,7 @@ async function uploadFileInternal(runtime, input, controls) {
2907
3058
  uploadId: session.uploadId,
2908
3059
  partNumber,
2909
3060
  checksumSha256,
3061
+ contentMd5: digests.partMd5s[index],
2910
3062
  ...validated.signal === void 0 ? {} : { signal: validated.signal }
2911
3063
  });
2912
3064
  const descriptor = descriptorResult.data;
@@ -2914,14 +3066,16 @@ async function uploadFileInternal(runtime, input, controls) {
2914
3066
  status: descriptorResult.status,
2915
3067
  requestId: descriptorResult.requestId
2916
3068
  });
2917
- const etag = await putPart(runtime, descriptor, slicePart(validated.source, start, end, expectedByteLength), checksumSha256, validated.signal);
3069
+ const etag = await putPart(runtime, descriptor, slicePart(validated.source, start, end, expectedByteLength), validated.signal);
2918
3070
  revision = await recordPartWithReconciliation(controls, validated, session, partNumber, revision, expectedByteLength, etag, checksumSha256);
2919
3071
  confirmedByteLength += expectedByteLength;
2920
3072
  confirmedPartCount += 1;
2921
3073
  emitProgress(validated.onProgress, "uploading", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
2922
3074
  }
2923
3075
  emitProgress(validated.onProgress, "completing", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
2924
- return await completeWithReconciliation(controls, validated, session, digests);
3076
+ const completed = await completeWithReconciliation(controls, validated, session, digests);
3077
+ if (completed.data.state === "verifying") emitProgress(validated.onProgress, "verifying", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
3078
+ return completed;
2925
3079
  } catch (error) {
2926
3080
  if (validated.signal?.aborted && session) await bestEffortAbort(controls, validated.workspaceId, session.uploadId);
2927
3081
  if (error instanceof DriveError) throw error;
@@ -2977,6 +3131,7 @@ async function readResumeState(controls, input, session, digests) {
2977
3131
  if (session.mode === "presigned-multipart" && [
2978
3132
  "completing",
2979
3133
  "provider-completed",
3134
+ "verifying",
2980
3135
  "ready"
2981
3136
  ].includes(baseline.lifecycle) && confirmedParts.size !== session.partCount) throw new DriveError("invalid_response");
2982
3137
  failForTerminalStatus(baseline.lifecycle, baselineRequestId);
@@ -3033,7 +3188,8 @@ async function completeWithReconciliation(controls, input, session, digests) {
3033
3188
  idempotencyKey: input.completionIdempotencyKey,
3034
3189
  ...input.signal === void 0 ? {} : { signal: input.signal }
3035
3190
  });
3036
- assertReadyMatchesInput(completed.data, session, input, digests, completed.requestId);
3191
+ if (completed.data.state === "ready") assertReadyMatchesInput(completed.data, session, input, digests, completed.requestId);
3192
+ else if (completed.data.itemId !== session.itemId || completed.data.versionId !== session.versionId || completed.data.uploadId !== session.uploadId || completed.data.totalByteLength !== input.byteLength) throw new DriveError("invalid_response");
3037
3193
  return completed;
3038
3194
  } catch (error) {
3039
3195
  if (!isAmbiguousControlFailure(error) || input.signal?.aborted) throw error;
@@ -3054,6 +3210,7 @@ async function completeWithReconciliation(controls, input, session, digests) {
3054
3210
  async function hashSource(source, byteLength, partCount, signal) {
3055
3211
  const fullHash = sha256.create();
3056
3212
  const partChecksums = [];
3213
+ const partMd5s = [];
3057
3214
  for (let index = 0; index < partCount; index += 1) {
3058
3215
  throwIfCallerAborted(signal);
3059
3216
  const start = index * UPLOAD_PART_BYTE_LENGTH;
@@ -3070,13 +3227,15 @@ async function hashSource(source, byteLength, partCount, signal) {
3070
3227
  const bytes = new Uint8Array(buffer);
3071
3228
  fullHash.update(bytes);
3072
3229
  partChecksums.push(toBase64(sha256(bytes)));
3230
+ partMd5s.push(toBase64(md5(bytes)));
3073
3231
  }
3074
3232
  return Object.freeze({
3075
3233
  callerDeclaredContentDigest: `sha256:${bytesToHex(fullHash.digest())}`,
3076
- partChecksums: Object.freeze(partChecksums)
3234
+ partChecksums: Object.freeze(partChecksums),
3235
+ partMd5s: Object.freeze(partMd5s)
3077
3236
  });
3078
3237
  }
3079
- async function putPart(runtime, descriptor, part, checksumSha256, callerSignal) {
3238
+ async function putPart(runtime, descriptor, part, callerSignal) {
3080
3239
  const remainingMilliseconds = descriptor.expiresAtEpochMilliseconds - Date.now();
3081
3240
  if (remainingMilliseconds < 1) throw new DriveError("invalid_response");
3082
3241
  const operation = createOperationSignal(callerSignal, Math.min(runtime.timeoutMilliseconds, remainingMilliseconds));
@@ -3094,8 +3253,9 @@ async function putPart(runtime, descriptor, part, checksumSha256, callerSignal)
3094
3253
  }), operation.signal);
3095
3254
  if (!(response instanceof Response)) throw new DriveError("invalid_response");
3096
3255
  const etag = response.headers.get("etag");
3097
- const responseChecksum = response.headers.get("x-amz-checksum-sha256");
3098
- if (response.status < 200 || response.status > 299 || !isEtag(etag) || responseChecksum !== checksumSha256) throw new DriveError("invalid_response", { status: response.status });
3256
+ const md5Response = response.headers.get("content-md5");
3257
+ const checksumMatches = md5Response === null || md5Response === descriptor.headers["content-md5"];
3258
+ if (response.status < 200 || response.status > 299 || !isEtag(etag) || !checksumMatches) throw new DriveError("invalid_response", { status: response.status });
3099
3259
  return etag;
3100
3260
  } catch (error) {
3101
3261
  if (operation.didTimeout()) throw new DriveError("timeout");
@@ -3131,7 +3291,7 @@ function failForTerminalStatus(lifecycle, requestId) {
3131
3291
  status: 409,
3132
3292
  ...requestId === void 0 ? {} : { requestId }
3133
3293
  });
3134
- if (lifecycle === "aborting" || lifecycle === "aborted") throw new DriveError("precondition_failed", {
3294
+ if (lifecycle === "aborting" || lifecycle === "aborted" || lifecycle === "failed") throw new DriveError("precondition_failed", {
3135
3295
  status: 409,
3136
3296
  ...requestId === void 0 ? {} : { requestId }
3137
3297
  });
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as UpdateItemInput, A as ListItemVersionsInput, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, I as ManagedItemVersionResource, J as RestoreItemInput, K as ReadyUpload, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as TrashItemInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, W as ProtectionClassification, Y as RestoreItemVersionInput, Z as SearchWorkspaceItemsInput, c as CurrentWorkspace, ct as UploadSession, dt as WorkspaceItemSearchPage, ft as operations, h as DriveOperationResult, j as ManagedDownloadDescriptor, l as DeleteItemInput, lt as UploadStatus, m as DriveCredentialProvider, n as CompleteUploadInput, o as CreateUploadInput, ot as UploadPartDescriptor, q as RecordUploadPartInput, r as CreateDownloadInput, s as CreateUploadPartDescriptorInput, st as UploadPartResult, t as AbortUploadInput, tt as UploadConfirmedPart, u as DownloadItemResult, ut as WorkspaceItemSearchItem, v as DriveServerClient, w as GetCurrentWorkspaceInput, y as DriveServerClientConfig } from "./contract.js";
1
+ import { $ as TrashItemInput, A as ListItemVersionsInput, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, G as ProtectionClassification, I as ManagedItemVersionResource, J as RecordUploadPartInput, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as SearchWorkspaceItemsInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, X as RestoreItemVersionInput, Y as RestoreItemInput, c as CurrentWorkspace, ct as UploadPartDescriptor, dt as UploadStatus, et as UpdateItemInput, ft as WorkspaceItemSearchItem, h as DriveOperationResult, j as ManagedDownloadDescriptor, l as DeleteItemInput, lt as UploadPartResult, m as DriveCredentialProvider, mt as operations, n as CompleteUploadInput, nt as UploadCompletion, o as CreateUploadInput, pt as WorkspaceItemSearchPage, q as ReadyUpload, r as CreateDownloadInput, rt as UploadConfirmedPart, s as CreateUploadPartDescriptorInput, t as AbortUploadInput, u as DownloadItemResult, ut as UploadSession, v as DriveServerClient, w as GetCurrentWorkspaceInput, y as DriveServerClientConfig, z as PendingUpload } from "./contract.js";
2
2
  //#region src/internal/provisioning.d.ts
3
3
  type Operation = operations["provisionManagedWorkspace"];
4
4
  type ProvisionWorkspaceCommand = Operation["requestBody"]["content"]["application/json"];
@@ -20,4 +20,4 @@ declare function createDriveProvisioningClient(config: DriveProvisioningClientCo
20
20
  //#region src/server.d.ts
21
21
  declare function createDriveServerClient(config: DriveServerClientConfig): DriveServerClient;
22
22
  //#endregion
23
- export { type AbortUploadInput, type CompleteUploadInput, type CreateDownloadInput, type CreateUploadInput, type CreateUploadPartDescriptorInput, type CurrentWorkspace, type DeleteItemInput, type DownloadItemResult, type DriveProvisioningClient, type DriveProvisioningClientConfig, type DriveServerClient, type DriveServerClientConfig, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type GetItemInput, type GetItemVersionInput, type GetUploadStatusInput, type ListFolderChildrenInput, type ListItemVersionsInput, type ManagedDownloadDescriptor, type ManagedDownloadRestorePending, type ManagedItemMetadata, type ManagedItemVersion, type ManagedItemVersionPage, type ManagedItemVersionResource, type ManagedItemVersionRestoreResult, type ManagedLifecycleItem, type ProtectionClassification, type ProvisionWorkspaceCommand, type ProvisionWorkspaceResult, type ReadyUpload, type RecordUploadPartInput, type RestoreItemInput, type RestoreItemVersionInput, type SearchWorkspaceItemsInput, type TrashItemInput, type UpdateItemInput, type UploadConfirmedPart, type UploadPartDescriptor, type UploadPartResult, type UploadSession, type UploadStatus, type WorkspaceItemSearchItem, type WorkspaceItemSearchPage, createDriveProvisioningClient, createDriveServerClient };
23
+ export { type AbortUploadInput, type CompleteUploadInput, type CreateDownloadInput, type CreateUploadInput, type CreateUploadPartDescriptorInput, type CurrentWorkspace, type DeleteItemInput, type DownloadItemResult, type DriveProvisioningClient, type DriveProvisioningClientConfig, type DriveServerClient, type DriveServerClientConfig, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type GetItemInput, type GetItemVersionInput, type GetUploadStatusInput, type ListFolderChildrenInput, type ListItemVersionsInput, type ManagedDownloadDescriptor, type ManagedDownloadRestorePending, type ManagedItemMetadata, type ManagedItemVersion, type ManagedItemVersionPage, type ManagedItemVersionResource, type ManagedItemVersionRestoreResult, type ManagedLifecycleItem, type PendingUpload, type ProtectionClassification, type ProvisionWorkspaceCommand, type ProvisionWorkspaceResult, type ReadyUpload, type RecordUploadPartInput, type RestoreItemInput, type RestoreItemVersionInput, type SearchWorkspaceItemsInput, type TrashItemInput, type UpdateItemInput, type UploadCompletion, type UploadConfirmedPart, type UploadPartDescriptor, type UploadPartResult, type UploadSession, type UploadStatus, type WorkspaceItemSearchItem, type WorkspaceItemSearchPage, createDriveProvisioningClient, createDriveServerClient };
package/dist/server.js CHANGED
@@ -584,12 +584,14 @@ function isUploadStatus(value, afterPartNumber, limit) {
584
584
  "nextAfterPartNumber",
585
585
  "expiresAtEpochMilliseconds",
586
586
  "ready"
587
- ]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.test(value.versionId) || typeof value.uploadId !== "string" || !UPLOAD_ID$1.test(value.uploadId) || value.mode !== "presigned-multipart" && value.mode !== "server-mediated-zero-byte" || ![
587
+ ], ["verification"]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.test(value.versionId) || typeof value.uploadId !== "string" || !UPLOAD_ID$1.test(value.uploadId) || value.mode !== "presigned-multipart" && value.mode !== "server-mediated-zero-byte" || ![
588
588
  "initiating",
589
589
  "recovery-required",
590
590
  "uploading",
591
591
  "completing",
592
592
  "provider-completed",
593
+ "verifying",
594
+ "failed",
593
595
  "ready",
594
596
  "aborting",
595
597
  "aborted"
@@ -599,18 +601,38 @@ function isUploadStatus(value, afterPartNumber, limit) {
599
601
  "maxParts"
600
602
  ]) || value.partPolicy.partByteLength !== UPLOAD_PART_BYTE_LENGTH$1 || !isSafeInteger$1(value.partPolicy.partCount) || value.partPolicy.partCount > 1e4 || value.partPolicy.maxParts !== 1e4 || (value.mode === "server-mediated-zero-byte" ? value.partPolicy.partCount !== 0 : value.partPolicy.partCount < 1) || !Array.isArray(value.confirmedParts) || value.confirmedParts.length > limit || !isSafeInteger$1(value.expiresAtEpochMilliseconds)) return false;
601
603
  let previousPartNumber = afterPartNumber;
604
+ if (value.verification !== void 0) {
605
+ const progress = value.verification;
606
+ if (!isExactRecord(progress, [
607
+ "state",
608
+ "verifiedByteLength",
609
+ "totalByteLength",
610
+ "revision"
611
+ ]) || ![
612
+ "pending",
613
+ "verified",
614
+ "failed"
615
+ ].includes(String(progress.state)) || !isSafeInteger$1(progress.verifiedByteLength) || !isSafeInteger$1(progress.totalByteLength) || progress.totalByteLength > MAX_UPLOAD_BYTE_LENGTH$1 || progress.verifiedByteLength > progress.totalByteLength || !isSafeInteger$1(progress.revision) || progress.state === "verified" && progress.verifiedByteLength !== progress.totalByteLength) return false;
616
+ Object.freeze(progress);
617
+ }
618
+ if (["verifying", "failed"].includes(String(value.lifecycle)) && value.verification === void 0) return false;
602
619
  for (const part of value.confirmedParts) {
603
620
  if (!isExactRecord(part, ["partNumber", "checksumSha256"]) || !isSafeInteger$1(part.partNumber) || part.partNumber <= previousPartNumber || part.partNumber > value.partPolicy.partCount || !isPartChecksum$1(part.checksumSha256)) return false;
604
621
  previousPartNumber = part.partNumber;
605
622
  }
606
- if (!(value.nextAfterPartNumber === null || isSafeInteger$1(value.nextAfterPartNumber) && value.confirmedParts.length === limit && value.nextAfterPartNumber === previousPartNumber) || value.mode === "server-mediated-zero-byte" && (value.confirmedParts.length !== 0 || value.nextAfterPartNumber !== null) || value.lifecycle === "ready" !== (value.ready !== null) || value.ready !== null && (!isReadyUpload(value.ready, { uploadId: value.uploadId }) || value.ready.itemId !== value.itemId || value.ready.versionId !== value.versionId)) return false;
623
+ if (!(value.nextAfterPartNumber === null || isSafeInteger$1(value.nextAfterPartNumber) && value.confirmedParts.length === limit && value.nextAfterPartNumber === previousPartNumber) || value.mode === "server-mediated-zero-byte" && (value.confirmedParts.length !== 0 || value.nextAfterPartNumber !== null) || value.lifecycle === "ready" !== (value.ready !== null) || value.ready !== null && (!isReadyUpload(value.ready, { uploadId: value.uploadId }) || value.ready.itemId !== value.itemId || value.ready.versionId !== value.versionId || !isExactRecord(value.verification, [
624
+ "state",
625
+ "verifiedByteLength",
626
+ "totalByteLength",
627
+ "revision"
628
+ ]) || value.verification.state !== "verified" || value.verification.totalByteLength !== value.ready.byteLength)) return false;
607
629
  Object.freeze(value.partPolicy);
608
630
  for (const part of value.confirmedParts) Object.freeze(part);
609
631
  Object.freeze(value.confirmedParts);
610
632
  Object.freeze(value);
611
633
  return true;
612
634
  }
613
- function isUploadPartDescriptor(value, expectedPartNumber, checksumSha256, allowInsecureHttp) {
635
+ function isUploadPartDescriptor(value, expectedPartNumber, allowInsecureHttp, contentMd5) {
614
636
  if (!isExactRecord(value, [
615
637
  "url",
616
638
  "method",
@@ -618,7 +640,7 @@ function isUploadPartDescriptor(value, expectedPartNumber, checksumSha256, allow
618
640
  "partNumber",
619
641
  "expectedByteLength",
620
642
  "expiresAtEpochMilliseconds"
621
- ]) || !isSignedTransferUrl(value.url, allowInsecureHttp) || value.method !== "PUT" || !isExactRecord(value.headers, ["x-amz-checksum-sha256"]) || value.headers["x-amz-checksum-sha256"] !== checksumSha256 || value.partNumber !== expectedPartNumber || !isSafeInteger$1(value.expectedByteLength) || value.expectedByteLength < 1 || value.expectedByteLength > UPLOAD_PART_BYTE_LENGTH$1 || !isSafeInteger$1(value.expiresAtEpochMilliseconds) || value.expiresAtEpochMilliseconds <= Date.now()) return false;
643
+ ]) || !isSignedTransferUrl(value.url, allowInsecureHttp) || value.method !== "PUT" || !contentMd5 || !isExactRecord(value.headers, ["content-md5"]) || value.headers["content-md5"] !== contentMd5 || value.partNumber !== expectedPartNumber || !isSafeInteger$1(value.expectedByteLength) || value.expectedByteLength < 1 || value.expectedByteLength > UPLOAD_PART_BYTE_LENGTH$1 || !isSafeInteger$1(value.expiresAtEpochMilliseconds) || value.expiresAtEpochMilliseconds <= Date.now()) return false;
622
644
  Object.freeze(value.headers);
623
645
  Object.freeze(value);
624
646
  return true;
@@ -642,6 +664,19 @@ function isReadyUpload(value, expected) {
642
664
  Object.freeze(value);
643
665
  return true;
644
666
  }
667
+ function isPendingUpload(value, uploadId) {
668
+ if (!isExactRecord(value, [
669
+ "itemId",
670
+ "versionId",
671
+ "uploadId",
672
+ "state",
673
+ "verifiedByteLength",
674
+ "totalByteLength",
675
+ "verificationRevision"
676
+ ]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.test(value.versionId) || value.uploadId !== uploadId || value.state !== "verifying" || !isSafeInteger$1(value.verifiedByteLength) || !isSafeInteger$1(value.totalByteLength) || value.totalByteLength > MAX_UPLOAD_BYTE_LENGTH$1 || value.verifiedByteLength > value.totalByteLength || !isSafeInteger$1(value.verificationRevision)) return false;
677
+ Object.freeze(value);
678
+ return true;
679
+ }
645
680
  function isPartChecksum$1(value) {
646
681
  return typeof value === "string" && /^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/.test(value);
647
682
  }
@@ -781,9 +816,9 @@ function isSafeCapabilityUrl(value) {
781
816
  return false;
782
817
  }
783
818
  }
784
- function isExactRecord(value, keys) {
819
+ function isExactRecord(value, keys, optional = []) {
785
820
  if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
786
- return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
821
+ return Object.keys(value).every((key) => keys.includes(key) || optional.includes(key)) && keys.every((key) => Object.hasOwn(value, key));
787
822
  }
788
823
  //#endregion
789
824
  //#region src/internal/client/request.ts
@@ -1112,14 +1147,17 @@ function validateCreateUploadPartDescriptorInput(value) {
1112
1147
  "workspaceId",
1113
1148
  "uploadId",
1114
1149
  "partNumber",
1115
- "checksumSha256"
1150
+ "checksumSha256",
1151
+ "contentMd5"
1116
1152
  ], ["signal"]);
1117
1153
  const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
1118
1154
  if (!isPartNumber(input.partNumber) || !isPartChecksum(input.checksumSha256)) throw new DriveError("invalid_input");
1155
+ if (typeof input.contentMd5 !== "string" || !/^[A-Za-z0-9+/]{21}[AQgw]==$/.test(input.contentMd5)) throw new DriveError("invalid_input");
1119
1156
  return {
1120
1157
  ...upload,
1121
1158
  partNumber: input.partNumber,
1122
- checksumSha256: input.checksumSha256
1159
+ checksumSha256: input.checksumSha256,
1160
+ contentMd5: input.contentMd5
1123
1161
  };
1124
1162
  }
1125
1163
  function validateRecordUploadPartInput(value) {
@@ -2398,7 +2436,7 @@ async function getUploadStatus(runtime, input) {
2398
2436
  }
2399
2437
  } }),
2400
2438
  ...requestOptions
2401
- }), [200], (value) => isUploadStatus(value, afterPartNumber, limit), false, STATUS_ERROR_CODES);
2439
+ }), [200], (value) => isUploadStatus(value, afterPartNumber, limit) && value.uploadId === validated.uploadId, false, STATUS_ERROR_CODES);
2402
2440
  }
2403
2441
  async function createUploadPartDescriptor(runtime, input) {
2404
2442
  const validated = validateCreateUploadPartDescriptorInput(input);
@@ -2410,11 +2448,12 @@ async function createUploadPartDescriptor(runtime, input) {
2410
2448
  } },
2411
2449
  body: {
2412
2450
  partNumber: validated.partNumber,
2413
- checksumSha256: validated.checksumSha256
2451
+ checksumSha256: validated.checksumSha256,
2452
+ contentMd5: validated.contentMd5
2414
2453
  }
2415
2454
  }),
2416
2455
  ...requestOptions
2417
- }), [200], (value) => isUploadPartDescriptor(value, validated.partNumber, validated.checksumSha256, new URL(runtime.baseUrl).protocol === "http:"), false, TRANSFER_ERROR_CODES);
2456
+ }), [200], (value) => isUploadPartDescriptor(value, validated.partNumber, new URL(runtime.baseUrl).protocol === "http:", validated.contentMd5), false, TRANSFER_ERROR_CODES);
2418
2457
  }
2419
2458
  async function recordUploadPart(runtime, input) {
2420
2459
  const validated = validateRecordUploadPartInput(input);
@@ -2446,7 +2485,7 @@ async function completeUpload(runtime, input) {
2446
2485
  header: { "Idempotency-Key": validated.idempotencyKey }
2447
2486
  } }),
2448
2487
  ...requestOptions
2449
- }), [200], (value) => isReadyUpload(value, { uploadId: validated.uploadId }), false, COMPLETE_UPLOAD_ERROR_CODES);
2488
+ }), [200, 202], (value, status) => status === 202 ? isPendingUpload(value, validated.uploadId) : isReadyUpload(value, { uploadId: validated.uploadId }), false, COMPLETE_UPLOAD_ERROR_CODES);
2450
2489
  }
2451
2490
  async function abortUpload(runtime, input) {
2452
2491
  const validated = validateAbortUploadInput(input);
package/dist/types.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { $ as UpdateItemInput, A as ListItemVersionsInput, B as PermissionGrant, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, G as ReadEffectiveItemPermissionsInput, H as PermissionMutation, I as ManagedItemVersionResource, J as RestoreItemInput, K as ReadyUpload, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as TrashItemInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, U as PermissionPage, V as PermissionGrantee, W as ProtectionClassification, X as RevokeItemPermissionInput, Y as RestoreItemVersionInput, Z as SearchWorkspaceItemsInput, _ as DriveResponseValidators, a as CreateItemPermissionInput, at as UploadFileProgressCallback, b as EffectivePermissionAction, c as CurrentWorkspace, ct as UploadSession, d as DriveClient, dt as WorkspaceItemSearchPage, et as UpdateItemPermissionInput, f as DriveClientConfig, g as DriveOperations, h as DriveOperationResult, i as CreateFolderInput, it as UploadFileProgress, j as ManagedDownloadDescriptor, k as ListItemPermissionsInput, l as DeleteItemInput, lt as UploadStatus, m as DriveCredentialProvider, n as CompleteUploadInput, nt as UploadFileInput, o as CreateUploadInput, ot as UploadPartDescriptor, p as DriveCredentialContext, q as RecordUploadPartInput, r as CreateDownloadInput, rt as UploadFilePhase, s as CreateUploadPartDescriptorInput, st as UploadPartResult, t as AbortUploadInput, tt as UploadConfirmedPart, u as DownloadItemResult, ut as WorkspaceItemSearchItem, v as DriveServerClient, w as GetCurrentWorkspaceInput, x as EffectivePermissionResponse, y as DriveServerClientConfig, z as PermissionAction } from "./contract.js";
2
- export { AbortUploadInput, CompleteUploadInput, CreateDownloadInput, CreateFolderInput, CreateItemPermissionInput, CreateUploadInput, CreateUploadPartDescriptorInput, CurrentWorkspace, DeleteItemInput, DownloadItemResult, DriveClient, DriveClientConfig, DriveCredentialContext, DriveCredentialProvider, DriveOperationResult, DriveOperations, DriveResponseValidators, DriveServerClient, DriveServerClientConfig, EffectivePermissionAction, EffectivePermissionResponse, FolderItem, FolderPage, GetCurrentWorkspaceInput, GetItemInput, GetItemVersionInput, GetUploadStatusInput, ListFolderChildrenInput, ListItemPermissionsInput, ListItemVersionsInput, ManagedDownloadDescriptor, ManagedDownloadRestorePending, ManagedItemMetadata, ManagedItemVersion, ManagedItemVersionPage, ManagedItemVersionResource, ManagedItemVersionRestoreResult, ManagedLifecycleItem, PermissionAction, PermissionGrant, PermissionGrantee, PermissionMutation, PermissionPage, ProtectionClassification, ReadEffectiveItemPermissionsInput, ReadyUpload, RecordUploadPartInput, RestoreItemInput, RestoreItemVersionInput, RevokeItemPermissionInput, SearchWorkspaceItemsInput, TrashItemInput, UpdateItemInput, UpdateItemPermissionInput, UploadConfirmedPart, UploadFileInput, UploadFilePhase, UploadFileProgress, UploadFileProgressCallback, UploadPartDescriptor, UploadPartResult, UploadSession, UploadStatus, WorkspaceItemSearchItem, WorkspaceItemSearchPage };
1
+ import { $ as TrashItemInput, A as ListItemVersionsInput, B as PermissionAction, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, G as ProtectionClassification, H as PermissionGrantee, I as ManagedItemVersionResource, J as RecordUploadPartInput, K as ReadEffectiveItemPermissionsInput, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as SearchWorkspaceItemsInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, U as PermissionMutation, V as PermissionGrant, W as PermissionPage, X as RestoreItemVersionInput, Y as RestoreItemInput, Z as RevokeItemPermissionInput, _ as DriveResponseValidators, a as CreateItemPermissionInput, at as UploadFilePhase, b as EffectivePermissionAction, c as CurrentWorkspace, ct as UploadPartDescriptor, d as DriveClient, dt as UploadStatus, et as UpdateItemInput, f as DriveClientConfig, ft as WorkspaceItemSearchItem, g as DriveOperations, h as DriveOperationResult, i as CreateFolderInput, it as UploadFileInput, j as ManagedDownloadDescriptor, k as ListItemPermissionsInput, l as DeleteItemInput, lt as UploadPartResult, m as DriveCredentialProvider, n as CompleteUploadInput, nt as UploadCompletion, o as CreateUploadInput, ot as UploadFileProgress, p as DriveCredentialContext, pt as WorkspaceItemSearchPage, q as ReadyUpload, r as CreateDownloadInput, rt as UploadConfirmedPart, s as CreateUploadPartDescriptorInput, st as UploadFileProgressCallback, t as AbortUploadInput, tt as UpdateItemPermissionInput, u as DownloadItemResult, ut as UploadSession, v as DriveServerClient, w as GetCurrentWorkspaceInput, x as EffectivePermissionResponse, y as DriveServerClientConfig, z as PendingUpload } from "./contract.js";
2
+ export { AbortUploadInput, CompleteUploadInput, CreateDownloadInput, CreateFolderInput, CreateItemPermissionInput, CreateUploadInput, CreateUploadPartDescriptorInput, CurrentWorkspace, DeleteItemInput, DownloadItemResult, DriveClient, DriveClientConfig, DriveCredentialContext, DriveCredentialProvider, DriveOperationResult, DriveOperations, DriveResponseValidators, DriveServerClient, DriveServerClientConfig, EffectivePermissionAction, EffectivePermissionResponse, FolderItem, FolderPage, GetCurrentWorkspaceInput, GetItemInput, GetItemVersionInput, GetUploadStatusInput, ListFolderChildrenInput, ListItemPermissionsInput, ListItemVersionsInput, ManagedDownloadDescriptor, ManagedDownloadRestorePending, ManagedItemMetadata, ManagedItemVersion, ManagedItemVersionPage, ManagedItemVersionResource, ManagedItemVersionRestoreResult, ManagedLifecycleItem, PendingUpload, PermissionAction, PermissionGrant, PermissionGrantee, PermissionMutation, PermissionPage, ProtectionClassification, ReadEffectiveItemPermissionsInput, ReadyUpload, RecordUploadPartInput, RestoreItemInput, RestoreItemVersionInput, RevokeItemPermissionInput, SearchWorkspaceItemsInput, TrashItemInput, UpdateItemInput, UpdateItemPermissionInput, UploadCompletion, UploadConfirmedPart, UploadFileInput, UploadFilePhase, UploadFileProgress, UploadFileProgressCallback, UploadPartDescriptor, UploadPartResult, UploadSession, UploadStatus, WorkspaceItemSearchItem, WorkspaceItemSearchPage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finueva/drive",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Public browser, Worker, and Node client for Finueva Drive",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",