@finueva/drive 0.1.1 → 0.3.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/dist/index.js CHANGED
@@ -10,6 +10,7 @@ const DRIVE_API_ERROR_CODES = Object.freeze([
10
10
  "precondition_failed",
11
11
  "idempotency_conflict",
12
12
  "quota_exceeded",
13
+ "upload_recovery_required",
13
14
  "service_unavailable",
14
15
  "internal_error"
15
16
  ]);
@@ -24,6 +25,7 @@ const DRIVE_API_ERROR_MESSAGES = Object.freeze({
24
25
  precondition_failed: "The request precondition failed.",
25
26
  idempotency_conflict: "The idempotency key conflicts with an earlier request.",
26
27
  quota_exceeded: "The workspace storage quota would be exceeded.",
28
+ upload_recovery_required: "The upload requires recovery before it can continue.",
27
29
  service_unavailable: "The service is temporarily unavailable.",
28
30
  internal_error: "The request could not be completed."
29
31
  });
@@ -59,13 +61,13 @@ const REQUEST_ID = /^[A-Za-z0-9_-]{16,128}$/;
59
61
  const COLLECTION_ETAG = /^"drive\.permission-collection\.v1\.(0|[1-9][0-9]*)"$/;
60
62
  const GRANT_ETAG$1 = /^"drive\.permission-grant\.v1\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"$/;
61
63
  const LIST_ETAG$1 = /^"drive\.permission-list\.v1\.[0-9a-f]{64}"$/;
62
- async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded) {
64
+ async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes) {
63
65
  const requestId = safeRequestId(response.headers.get("x-request-id"));
64
66
  if (requestId === null) {
65
67
  cancelResponse(response);
66
68
  throw new DriveError("invalid_response", { status: response.status });
67
69
  }
68
- if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded);
70
+ if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes);
69
71
  const { value } = await parseBoundedJson(response, SUCCESS_BODY_LIMIT, response.status, requestId, operationSignal);
70
72
  const status = response.status;
71
73
  if (!guard(value, status, response.headers)) throw new DriveError("invalid_response", {
@@ -79,6 +81,28 @@ async function parseResponse(response, operationSignal, preconditionStatus, succ
79
81
  validators: readValidators(response.headers)
80
82
  });
81
83
  }
84
+ async function parseNoContentResponse(response, operationSignal, preconditionStatus, successStatuses, allowedErrorCodes) {
85
+ const requestId = safeRequestId(response.headers.get("x-request-id"));
86
+ if (requestId === null) {
87
+ cancelResponse(response);
88
+ throw new DriveError("invalid_response", { status: response.status });
89
+ }
90
+ if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, false, allowedErrorCodes);
91
+ const contentLength = response.headers.get("content-length");
92
+ if (response.body !== null || contentLength !== null && contentLength !== "0" || response.headers.has("content-type")) {
93
+ cancelResponse(response);
94
+ throw new DriveError("invalid_response", {
95
+ status: response.status,
96
+ requestId
97
+ });
98
+ }
99
+ return Object.freeze({
100
+ data: void 0,
101
+ status: response.status,
102
+ requestId,
103
+ validators: Object.freeze({})
104
+ });
105
+ }
82
106
  function parseCollectionEtag(value) {
83
107
  const match = COLLECTION_ETAG.exec(value);
84
108
  if (!match) return void 0;
@@ -92,7 +116,7 @@ function parseGrantEtag(value) {
92
116
  const grantRevision = Number(match[2]);
93
117
  return Number.isSafeInteger(collectionRevision) && Number.isSafeInteger(grantRevision) ? [collectionRevision, grantRevision] : void 0;
94
118
  }
95
- async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded) {
119
+ async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
96
120
  let parsed;
97
121
  try {
98
122
  parsed = await parseBoundedJson(response, ERROR_BODY_LIMIT, response.status, headerRequestId, signal);
@@ -114,7 +138,7 @@ async function normalizeError(response, headerRequestId, signal, preconditionSta
114
138
  requestId: headerRequestId
115
139
  });
116
140
  const envelope = value.error;
117
- if (typeof envelope.code !== "string" || !DRIVE_API_ERROR_CODES.includes(envelope.code) || envelope.message !== DRIVE_API_ERROR_MESSAGES[envelope.code] || !REQUEST_ID.test(String(envelope.requestId)) || envelope.requestId !== headerRequestId || !isExactRecord$1(envelope.details, []) || !errorStatusMatches(envelope.code, response.status, preconditionStatus, allowsQuotaExceeded) || parsed.text !== JSON.stringify(value)) return new DriveError("invalid_response", {
141
+ if (typeof envelope.code !== "string" || !DRIVE_API_ERROR_CODES.includes(envelope.code) || envelope.message !== DRIVE_API_ERROR_MESSAGES[envelope.code] || !REQUEST_ID.test(String(envelope.requestId)) || envelope.requestId !== headerRequestId || !isExactRecord$1(envelope.details, []) || !errorStatusMatches(envelope.code, response.status, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) || parsed.text !== JSON.stringify(value)) return new DriveError("invalid_response", {
118
142
  status: response.status,
119
143
  requestId: headerRequestId
120
144
  });
@@ -123,7 +147,8 @@ async function normalizeError(response, headerRequestId, signal, preconditionSta
123
147
  requestId: envelope.requestId
124
148
  });
125
149
  }
126
- function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded) {
150
+ function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
151
+ if (allowedErrorCodes && !allowedErrorCodes.includes(code)) return false;
127
152
  if (code === "quota_exceeded" && !allowsQuotaExceeded) return false;
128
153
  return {
129
154
  authentication_required: [401],
@@ -133,9 +158,10 @@ function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceede
133
158
  invalid_request: [422],
134
159
  invalid_pagination_cursor: [422],
135
160
  invalid_idempotency_key: [422],
136
- precondition_failed: [preconditionStatus],
161
+ precondition_failed: preconditionStatus === null ? [] : [preconditionStatus],
137
162
  idempotency_conflict: [409],
138
163
  quota_exceeded: [409],
164
+ upload_recovery_required: [409],
139
165
  service_unavailable: [503],
140
166
  internal_error: [500]
141
167
  }[code].includes(status);
@@ -246,6 +272,7 @@ const WORKSPACE_ID$1 = /^drive\.workspace\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-
246
272
  const VOLUME_ID = /^drive\.volume\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
247
273
  const GRANT_ID$1 = /^drive\.grant\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
248
274
  const UPLOAD_ID$1 = /^drive\.upload\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
275
+ const VERSION_ID = /^drive\.version\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
249
276
  const CURSOR$1 = /^drive\.cursor\.v1\.[A-Za-z0-9_-]+$/;
250
277
  const AUTH_ID$1 = /^[A-Za-z0-9_-]{1,128}$/;
251
278
  const GRANT_ETAG = /^"drive\.permission-grant\.v1\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"$/;
@@ -268,7 +295,18 @@ const EFFECTIVE_ACTIONS = Object.freeze([
268
295
  "items:update"
269
296
  ]);
270
297
  const MAX_UPLOAD_BYTE_LENGTH$1 = 33554432e4;
271
- const UPLOAD_QUOTA_EXPIRY_MILLISECONDS = 864e5;
298
+ const UPLOAD_PART_BYTE_LENGTH$2 = 32 * 1024 * 1024;
299
+ const CONTENT_DIGEST$1 = /^sha256:[0-9a-f]{64}$/;
300
+ function isCurrentWorkspace(value) {
301
+ if (!isExactRecord(value, [
302
+ "workspaceId",
303
+ "rootVolumeId",
304
+ "rootItemId",
305
+ "workspaceReference"
306
+ ]) || typeof value.workspaceId !== "string" || !WORKSPACE_ID$1.test(value.workspaceId) || typeof value.rootVolumeId !== "string" || !VOLUME_ID.test(value.rootVolumeId) || typeof value.rootItemId !== "string" || !ITEM_ID$1.test(value.rootItemId)) return false;
307
+ const reference = value.workspaceReference;
308
+ return isExactRecord(reference, ["type", "userId"]) && reference.type === "personal" && typeof reference.userId === "string" && AUTH_ID$1.test(reference.userId) || isExactRecord(reference, ["type", "organizationId"]) && reference.type === "organization" && typeof reference.organizationId === "string" && AUTH_ID$1.test(reference.organizationId);
309
+ }
272
310
  function isFolderPage(value, workspaceId, parentItemId) {
273
311
  if (!(isExactRecord(value, ["items", "nextCursor"]) && Array.isArray(value.items) && value.items.length <= 50 && value.items.every(isFolderItem) && (value.nextCursor === null || typeof value.nextCursor === "string" && value.nextCursor.length <= 699 && CURSOR$1.test(value.nextCursor)))) return false;
274
312
  return value.items.every((item) => item.workspaceId === workspaceId && item.parentItemId === parentItemId) && isStrictlyOrdered(value.items, (item) => item.itemId);
@@ -339,18 +377,93 @@ function isEffectivePermissionResponse(value, targetItemId) {
339
377
  }
340
378
  return true;
341
379
  }
342
- function isUploadQuotaReservation(value) {
343
- return isExactRecord(value, [
344
- "workspaceId",
380
+ function isUploadSession(value, expectedByteLength) {
381
+ if (!isExactRecord(value, [
382
+ "itemId",
383
+ "versionId",
345
384
  "uploadId",
346
- "parentItemId",
347
- "expectedByteLength",
348
- "state",
349
- "terminalReason",
350
- "createdAtEpochMilliseconds",
385
+ "mode",
386
+ "partByteLength",
387
+ "partCount",
388
+ "revision",
389
+ "expiresAtEpochMilliseconds"
390
+ ]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID.test(value.versionId) || typeof value.uploadId !== "string" || !UPLOAD_ID$1.test(value.uploadId) || value.mode !== "presigned-multipart" && value.mode !== "server-mediated-zero-byte" || value.partByteLength !== UPLOAD_PART_BYTE_LENGTH$2 || !isSafeInteger$1(value.partCount) || value.partCount > 1e4 || value.partCount !== Math.ceil(expectedByteLength / UPLOAD_PART_BYTE_LENGTH$2) || (expectedByteLength === 0 ? value.mode !== "server-mediated-zero-byte" : value.mode !== "presigned-multipart") || !isSafeInteger$1(value.revision) || !isSafeInteger$1(value.expiresAtEpochMilliseconds) || value.expiresAtEpochMilliseconds <= Date.now()) return false;
391
+ Object.freeze(value);
392
+ return true;
393
+ }
394
+ function isUploadStatus(value, afterPartNumber, limit) {
395
+ if (!isExactRecord(value, [
396
+ "itemId",
397
+ "versionId",
398
+ "uploadId",
399
+ "mode",
400
+ "lifecycle",
401
+ "revision",
402
+ "partPolicy",
403
+ "confirmedParts",
404
+ "nextAfterPartNumber",
351
405
  "expiresAtEpochMilliseconds",
352
- "terminalAtEpochMilliseconds"
353
- ]) && typeof value.workspaceId === "string" && WORKSPACE_ID$1.test(value.workspaceId) && typeof value.uploadId === "string" && UPLOAD_ID$1.test(value.uploadId) && typeof value.parentItemId === "string" && ITEM_ID$1.test(value.parentItemId) && typeof value.expectedByteLength === "number" && Number.isSafeInteger(value.expectedByteLength) && value.expectedByteLength >= 0 && value.expectedByteLength <= MAX_UPLOAD_BYTE_LENGTH$1 && (value.state === "reserved" || value.state === "converted" || value.state === "released") && (value.terminalReason === null || value.terminalReason === "completed" || value.terminalReason === "aborted" || value.terminalReason === "failed" || value.terminalReason === "expired") && isSafeInteger$1(value.createdAtEpochMilliseconds) && isSafeInteger$1(value.expiresAtEpochMilliseconds) && value.expiresAtEpochMilliseconds - value.createdAtEpochMilliseconds === UPLOAD_QUOTA_EXPIRY_MILLISECONDS && (value.terminalAtEpochMilliseconds === null || isSafeInteger$1(value.terminalAtEpochMilliseconds) && value.terminalAtEpochMilliseconds >= value.createdAtEpochMilliseconds);
406
+ "ready"
407
+ ]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID.test(value.versionId) || typeof value.uploadId !== "string" || !UPLOAD_ID$1.test(value.uploadId) || value.mode !== "presigned-multipart" && value.mode !== "server-mediated-zero-byte" || ![
408
+ "initiating",
409
+ "recovery-required",
410
+ "uploading",
411
+ "completing",
412
+ "provider-completed",
413
+ "ready",
414
+ "aborting",
415
+ "aborted"
416
+ ].includes(String(value.lifecycle)) || !isSafeInteger$1(value.revision) || !isExactRecord(value.partPolicy, [
417
+ "partByteLength",
418
+ "partCount",
419
+ "maxParts"
420
+ ]) || 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;
421
+ let previousPartNumber = afterPartNumber;
422
+ for (const part of value.confirmedParts) {
423
+ if (!isExactRecord(part, ["partNumber", "checksumSha256"]) || !isSafeInteger$1(part.partNumber) || part.partNumber <= previousPartNumber || part.partNumber > value.partPolicy.partCount || !isPartChecksum$1(part.checksumSha256)) return false;
424
+ previousPartNumber = part.partNumber;
425
+ }
426
+ 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;
427
+ Object.freeze(value.partPolicy);
428
+ for (const part of value.confirmedParts) Object.freeze(part);
429
+ Object.freeze(value.confirmedParts);
430
+ Object.freeze(value);
431
+ return true;
432
+ }
433
+ function isUploadPartDescriptor(value, expectedPartNumber, checksumSha256, allowInsecureHttp) {
434
+ if (!isExactRecord(value, [
435
+ "url",
436
+ "method",
437
+ "headers",
438
+ "partNumber",
439
+ "expectedByteLength",
440
+ "expiresAtEpochMilliseconds"
441
+ ]) || !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;
442
+ Object.freeze(value.headers);
443
+ Object.freeze(value);
444
+ return true;
445
+ }
446
+ function isUploadPartResult(value, expectedPartNumber, expectedUploadRevision) {
447
+ if (!isExactRecord(value, ["partNumber", "revision"]) || value.partNumber !== expectedPartNumber || value.revision !== expectedUploadRevision + 1 || !isSafeInteger$1(value.revision)) return false;
448
+ Object.freeze(value);
449
+ return true;
450
+ }
451
+ function isReadyUpload(value, expected) {
452
+ if (!isExactRecord(value, [
453
+ "itemId",
454
+ "versionId",
455
+ "uploadId",
456
+ "byteLength",
457
+ "callerDeclaredContentDigest",
458
+ "displayFilename",
459
+ "mediaType",
460
+ "state"
461
+ ]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID.test(value.versionId) || value.uploadId !== expected.uploadId || !isSafeInteger$1(value.byteLength) || value.byteLength < 0 || value.byteLength > MAX_UPLOAD_BYTE_LENGTH$1 || typeof value.callerDeclaredContentDigest !== "string" || !CONTENT_DIGEST$1.test(value.callerDeclaredContentDigest) || !isSafeFilename$1(value.displayFilename) || !isMediaType$1(value.mediaType) || value.state !== "ready" || expected.byteLength !== void 0 && value.byteLength !== expected.byteLength || expected.callerDeclaredContentDigest !== void 0 && value.callerDeclaredContentDigest !== expected.callerDeclaredContentDigest || expected.displayFilename !== void 0 && value.displayFilename !== expected.displayFilename || expected.mediaType !== void 0 && value.mediaType !== expected.mediaType) return false;
462
+ Object.freeze(value);
463
+ return true;
464
+ }
465
+ function isPartChecksum$1(value) {
466
+ return typeof value === "string" && /^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/.test(value);
354
467
  }
355
468
  function mutationValidatorsAreCoherent(headers) {
356
469
  const collection = headers.get("drive-permission-collection-etag");
@@ -407,6 +520,19 @@ function isSafeFilename$1(value) {
407
520
  }
408
521
  return true;
409
522
  }
523
+ function isMediaType$1(value) {
524
+ return typeof value === "string" && value.length <= 255 && /^[a-z0-9](?:[a-z0-9!#$&^_.+-]{0,125}[a-z0-9])?\/[a-z0-9](?:[a-z0-9!#$&^_.+-]{0,125}[a-z0-9])?$/.test(value);
525
+ }
526
+ function isSignedTransferUrl(value, allowInsecureHttp) {
527
+ if (typeof value !== "string" || value.length < 1 || value.length > 8192 || value !== value.trim()) return false;
528
+ try {
529
+ const url = new URL(value);
530
+ const loopbackHost = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
531
+ return (url.protocol === "https:" || url.protocol === "http:" && allowInsecureHttp && loopbackHost) && url.username === "" && url.password === "" && url.hash === "" && url.host !== "";
532
+ } catch {
533
+ return false;
534
+ }
535
+ }
410
536
  function filenameIsReserved$1(value) {
411
537
  const base = value.split(".", 1)[0].toUpperCase();
412
538
  return value === "." || value === ".." || [
@@ -446,7 +572,14 @@ const PERMISSION_ACTIONS = Object.freeze([
446
572
  "items:update"
447
573
  ]);
448
574
  const IDEMPOTENCY_KEY = /^[A-Za-z0-9_-]{16,128}$/;
575
+ const CONTENT_DIGEST = /^sha256:[0-9a-f]{64}$/;
576
+ const PART_CHECKSUM = /^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/;
449
577
  const MAX_UPLOAD_BYTE_LENGTH = 33554432e4;
578
+ const UPLOAD_PART_BYTE_LENGTH$1 = 32 * 1024 * 1024;
579
+ function validateCurrentWorkspaceInput(value) {
580
+ const signal = validateSignal(captureRecord(value === void 0 ? {} : value, [], ["signal"]).signal);
581
+ return signal === void 0 ? {} : { signal };
582
+ }
450
583
  function validateResourceInput(value) {
451
584
  const input = captureRecord(value, ["workspaceId", "itemId"], ["signal"]);
452
585
  const workspaceId = input.workspaceId;
@@ -581,26 +714,133 @@ function validateCreateUploadInput(value) {
581
714
  "workspaceId",
582
715
  "parentItemId",
583
716
  "expectedByteLength",
717
+ "displayFilename",
718
+ "mediaType",
719
+ "callerDeclaredContentDigest",
720
+ "protectionClassification",
584
721
  "idempotencyKey"
585
722
  ], ["signal"]);
586
723
  const signal = validateSignal(input.signal);
587
- if (typeof input.workspaceId !== "string" || !WORKSPACE_ID.test(input.workspaceId) || typeof input.parentItemId !== "string" || !ITEM_ID.test(input.parentItemId) || typeof input.expectedByteLength !== "number" || !Number.isSafeInteger(input.expectedByteLength) || input.expectedByteLength < 0 || input.expectedByteLength > MAX_UPLOAD_BYTE_LENGTH || !isIdempotencyKey(input.idempotencyKey)) throw new DriveError("invalid_input");
724
+ if (typeof input.workspaceId !== "string" || !WORKSPACE_ID.test(input.workspaceId) || typeof input.parentItemId !== "string" || !ITEM_ID.test(input.parentItemId) || typeof input.expectedByteLength !== "number" || !Number.isSafeInteger(input.expectedByteLength) || input.expectedByteLength < 0 || input.expectedByteLength > MAX_UPLOAD_BYTE_LENGTH || !isSafeFilename(input.displayFilename) || !isMediaType(input.mediaType) || typeof input.callerDeclaredContentDigest !== "string" || !CONTENT_DIGEST.test(input.callerDeclaredContentDigest) || input.protectionClassification !== "ordinary" && input.protectionClassification !== "opaque-encrypted" || !isIdempotencyKey(input.idempotencyKey)) throw new DriveError("invalid_input");
588
725
  return {
589
726
  workspaceId: input.workspaceId,
590
727
  parentItemId: input.parentItemId,
591
728
  expectedByteLength: input.expectedByteLength,
729
+ displayFilename: input.displayFilename,
730
+ mediaType: input.mediaType,
731
+ callerDeclaredContentDigest: input.callerDeclaredContentDigest,
732
+ protectionClassification: input.protectionClassification,
592
733
  idempotencyKey: input.idempotencyKey,
593
734
  ...signal === void 0 ? {} : { signal }
594
735
  };
595
736
  }
737
+ function validateGetUploadStatusInput(value) {
738
+ const input = captureRecord(value, ["workspaceId", "uploadId"], [
739
+ "afterPartNumber",
740
+ "limit",
741
+ "signal"
742
+ ]);
743
+ const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
744
+ if (input.afterPartNumber !== void 0 && (!isSafeInteger(input.afterPartNumber) || input.afterPartNumber > 1e4) || input.limit !== void 0 && (!isSafeInteger(input.limit) || input.limit < 1 || input.limit > 100)) throw new DriveError("invalid_input");
745
+ return {
746
+ ...upload,
747
+ ...input.afterPartNumber === void 0 ? {} : { afterPartNumber: input.afterPartNumber },
748
+ ...input.limit === void 0 ? {} : { limit: input.limit }
749
+ };
750
+ }
751
+ function validateCreateUploadPartDescriptorInput(value) {
752
+ const input = captureRecord(value, [
753
+ "workspaceId",
754
+ "uploadId",
755
+ "partNumber",
756
+ "checksumSha256"
757
+ ], ["signal"]);
758
+ const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
759
+ if (!isPartNumber(input.partNumber) || !isPartChecksum(input.checksumSha256)) throw new DriveError("invalid_input");
760
+ return {
761
+ ...upload,
762
+ partNumber: input.partNumber,
763
+ checksumSha256: input.checksumSha256
764
+ };
765
+ }
766
+ function validateRecordUploadPartInput(value) {
767
+ const input = captureRecord(value, [
768
+ "workspaceId",
769
+ "uploadId",
770
+ "partNumber",
771
+ "expectedUploadRevision",
772
+ "byteLength",
773
+ "etag",
774
+ "checksumSha256"
775
+ ], ["signal"]);
776
+ const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
777
+ if (!isPartNumber(input.partNumber) || !isSafeInteger(input.expectedUploadRevision) || input.expectedUploadRevision >= Number.MAX_SAFE_INTEGER || !isSafeInteger(input.byteLength) || input.byteLength < 1 || input.byteLength > UPLOAD_PART_BYTE_LENGTH$1 || !isEtag$1(input.etag) || !isPartChecksum(input.checksumSha256)) throw new DriveError("invalid_input");
778
+ return {
779
+ ...upload,
780
+ partNumber: input.partNumber,
781
+ expectedUploadRevision: input.expectedUploadRevision,
782
+ byteLength: input.byteLength,
783
+ etag: input.etag,
784
+ checksumSha256: input.checksumSha256
785
+ };
786
+ }
787
+ function validateCompleteUploadInput(value) {
788
+ const input = captureRecord(value, [
789
+ "workspaceId",
790
+ "uploadId",
791
+ "idempotencyKey"
792
+ ], ["signal"]);
793
+ const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
794
+ if (!isIdempotencyKey(input.idempotencyKey)) throw new DriveError("invalid_input");
795
+ return {
796
+ ...upload,
797
+ idempotencyKey: input.idempotencyKey
798
+ };
799
+ }
596
800
  function validateAbortUploadInput(value) {
597
801
  const input = captureRecord(value, ["workspaceId", "uploadId"], ["signal"]);
802
+ return validateUploadPath(input.workspaceId, input.uploadId, input.signal);
803
+ }
804
+ function validateUploadFileInput(value) {
805
+ const input = captureRecord(value, [
806
+ "workspaceId",
807
+ "parentItemId",
808
+ "source",
809
+ "displayFilename",
810
+ "idempotencyKey",
811
+ "completionIdempotencyKey"
812
+ ], [
813
+ "mediaType",
814
+ "protectionClassification",
815
+ "signal",
816
+ "onProgress"
817
+ ]);
598
818
  const signal = validateSignal(input.signal);
599
- if (typeof input.workspaceId !== "string" || !WORKSPACE_ID.test(input.workspaceId) || typeof input.uploadId !== "string" || !UPLOAD_ID.test(input.uploadId)) throw new DriveError("invalid_input");
819
+ const mediaType = input.mediaType ?? "application/octet-stream";
820
+ const protectionClassification = input.protectionClassification ?? "ordinary";
821
+ let source;
822
+ let byteLength;
823
+ try {
824
+ if (!(input.source instanceof Blob)) throw new DriveError("invalid_input");
825
+ source = input.source;
826
+ byteLength = source.size;
827
+ } catch (error) {
828
+ if (error instanceof DriveError) throw error;
829
+ throw new DriveError("invalid_input");
830
+ }
831
+ if (typeof input.workspaceId !== "string" || !WORKSPACE_ID.test(input.workspaceId) || typeof input.parentItemId !== "string" || !ITEM_ID.test(input.parentItemId) || !Number.isSafeInteger(byteLength) || byteLength < 0 || byteLength > MAX_UPLOAD_BYTE_LENGTH || !isSafeFilename(input.displayFilename) || !isMediaType(mediaType) || protectionClassification !== "ordinary" && protectionClassification !== "opaque-encrypted" || !isIdempotencyKey(input.idempotencyKey) || !isIdempotencyKey(input.completionIdempotencyKey) || input.onProgress !== void 0 && typeof input.onProgress !== "function") throw new DriveError("invalid_input");
600
832
  return {
601
833
  workspaceId: input.workspaceId,
602
- uploadId: input.uploadId,
603
- ...signal === void 0 ? {} : { signal }
834
+ parentItemId: input.parentItemId,
835
+ source,
836
+ byteLength,
837
+ displayFilename: input.displayFilename,
838
+ mediaType,
839
+ protectionClassification,
840
+ idempotencyKey: input.idempotencyKey,
841
+ completionIdempotencyKey: input.completionIdempotencyKey,
842
+ ...signal === void 0 ? {} : { signal },
843
+ ...input.onProgress === void 0 ? {} : { onProgress: input.onProgress }
604
844
  };
605
845
  }
606
846
  function resourcePath(input) {
@@ -687,6 +927,27 @@ function captureArray(value) {
687
927
  function isIdempotencyKey(value) {
688
928
  return typeof value === "string" && IDEMPOTENCY_KEY.test(value);
689
929
  }
930
+ function validateUploadPath(workspaceId, uploadId, signalValue) {
931
+ const signal = validateSignal(signalValue);
932
+ if (typeof workspaceId !== "string" || !WORKSPACE_ID.test(workspaceId) || typeof uploadId !== "string" || !UPLOAD_ID.test(uploadId)) throw new DriveError("invalid_input");
933
+ return {
934
+ workspaceId,
935
+ uploadId,
936
+ ...signal === void 0 ? {} : { signal }
937
+ };
938
+ }
939
+ function isPartNumber(value) {
940
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 1 && value <= 1e4;
941
+ }
942
+ function isPartChecksum(value) {
943
+ return typeof value === "string" && PART_CHECKSUM.test(value);
944
+ }
945
+ function isEtag$1(value) {
946
+ return typeof value === "string" && value.length >= 1 && value.length <= 1024 && /^[\x20-\x7e]+$/.test(value);
947
+ }
948
+ function isMediaType(value) {
949
+ return typeof value === "string" && value.length <= 255 && /^[a-z0-9](?:[a-z0-9!#$&^_.+-]{0,125}[a-z0-9])?\/[a-z0-9](?:[a-z0-9!#$&^_.+-]{0,125}[a-z0-9])?$/.test(value);
950
+ }
690
951
  function isExpiry(value) {
691
952
  return value === null || isSafeInteger(value);
692
953
  }
@@ -1146,7 +1407,7 @@ function createClientRuntime(config) {
1146
1407
  if (typeof runtime.fetchImplementation !== "function" || typeof runtime.getCredential !== "function") throw new DriveError("invalid_input");
1147
1408
  return runtime;
1148
1409
  }
1149
- async function execute(runtime, signal, preconditionStatus, send, successStatuses, guard, allowsQuotaExceeded = false) {
1410
+ async function execute(runtime, signal, preconditionStatus, send, successStatuses, guard, allowsQuotaExceeded = false, allowedErrorCodes) {
1150
1411
  const operation = createOperationSignal(signal, runtime.timeoutMilliseconds);
1151
1412
  try {
1152
1413
  const operationSignal = operation.signal;
@@ -1173,7 +1434,7 @@ async function execute(runtime, signal, preconditionStatus, send, successStatuse
1173
1434
  signal: operationSignal
1174
1435
  });
1175
1436
  if (!capturedResponse) throw new DriveError("network_error");
1176
- return await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded);
1437
+ return guard === null ? await parseNoContentResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, allowedErrorCodes) : await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes);
1177
1438
  } catch (error) {
1178
1439
  if (operation.didTimeout()) throw new DriveError("timeout");
1179
1440
  if (error instanceof DriveError) throw error;
@@ -1253,9 +1514,42 @@ async function raceWithAbort(promise, signal) {
1253
1514
  }
1254
1515
  //#endregion
1255
1516
  //#region src/internal/client/operations.ts
1256
- function createDriveClientInternal(config) {
1257
- const runtime = createClientRuntime(config);
1517
+ const CURRENT_WORKSPACE_ERROR_CODES = Object.freeze([
1518
+ "authentication_required",
1519
+ "identity_authority_unavailable",
1520
+ "permission_denied",
1521
+ "resource_not_found",
1522
+ "invalid_request",
1523
+ "service_unavailable"
1524
+ ]);
1525
+ const TRANSFER_ERROR_CODES = Object.freeze([
1526
+ "authentication_required",
1527
+ "identity_authority_unavailable",
1528
+ "permission_denied",
1529
+ "resource_not_found",
1530
+ "invalid_request",
1531
+ "precondition_failed",
1532
+ "upload_recovery_required",
1533
+ "service_unavailable"
1534
+ ]);
1535
+ const STATUS_ERROR_CODES = Object.freeze([
1536
+ "authentication_required",
1537
+ "identity_authority_unavailable",
1538
+ "permission_denied",
1539
+ "resource_not_found",
1540
+ "invalid_request",
1541
+ "service_unavailable"
1542
+ ]);
1543
+ const CREATE_UPLOAD_ERROR_CODES = Object.freeze([
1544
+ ...TRANSFER_ERROR_CODES,
1545
+ "invalid_idempotency_key",
1546
+ "idempotency_conflict",
1547
+ "quota_exceeded"
1548
+ ]);
1549
+ const COMPLETE_UPLOAD_ERROR_CODES = Object.freeze([...TRANSFER_ERROR_CODES, "invalid_idempotency_key"]);
1550
+ function createDriveOperations(runtime) {
1258
1551
  return Object.freeze({
1552
+ getCurrentWorkspace: (input) => getCurrentWorkspace(runtime, input),
1259
1553
  listFolderChildren: (input) => listFolderChildren(runtime, input),
1260
1554
  createFolder: (input) => createFolder(runtime, input),
1261
1555
  listItemPermissions: (input) => listItemPermissions(runtime, input),
@@ -1264,9 +1558,19 @@ function createDriveClientInternal(config) {
1264
1558
  updateItemPermission: (input) => updateItemPermission(runtime, input),
1265
1559
  revokeItemPermission: (input) => revokeItemPermission(runtime, input),
1266
1560
  createUpload: (input) => createUpload(runtime, input),
1561
+ getUploadStatus: (input) => getUploadStatus(runtime, input),
1562
+ createUploadPartDescriptor: (input) => createUploadPartDescriptor(runtime, input),
1563
+ recordUploadPart: (input) => recordUploadPart(runtime, input),
1564
+ completeUpload: (input) => completeUpload(runtime, input),
1267
1565
  abortUpload: (input) => abortUpload(runtime, input)
1268
1566
  });
1269
1567
  }
1568
+ async function getCurrentWorkspace(runtime, input) {
1569
+ return execute(runtime, validateCurrentWorkspaceInput(input).signal, null, (api, requestOptions) => api.GET("/api/v1/workspaces/current", {
1570
+ ...operationOptions("getCurrentWorkspace", { params: {} }),
1571
+ ...requestOptions
1572
+ }), [200], isCurrentWorkspace, false, CURRENT_WORKSPACE_ERROR_CODES);
1573
+ }
1270
1574
  async function listFolderChildren(runtime, input) {
1271
1575
  const validated = validatePageInput(input);
1272
1576
  return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/children", {
@@ -1375,11 +1679,81 @@ async function createUpload(runtime, input) {
1375
1679
  },
1376
1680
  body: {
1377
1681
  parentItemId: validated.parentItemId,
1378
- expectedByteLength: validated.expectedByteLength
1682
+ expectedByteLength: validated.expectedByteLength,
1683
+ displayFilename: validated.displayFilename,
1684
+ mediaType: validated.mediaType,
1685
+ callerDeclaredContentDigest: validated.callerDeclaredContentDigest,
1686
+ protectionClassification: validated.protectionClassification
1379
1687
  }
1380
1688
  }),
1381
1689
  ...requestOptions
1382
- }), [200, 201], (value) => isUploadQuotaReservation(value) && value.workspaceId === validated.workspaceId && value.parentItemId === validated.parentItemId && value.expectedByteLength === validated.expectedByteLength && value.state === "reserved" && value.terminalReason === null && value.terminalAtEpochMilliseconds === null, true);
1690
+ }), [200, 201], (value) => isUploadSession(value, validated.expectedByteLength), true, CREATE_UPLOAD_ERROR_CODES);
1691
+ }
1692
+ async function getUploadStatus(runtime, input) {
1693
+ const validated = validateGetUploadStatusInput(input);
1694
+ const afterPartNumber = validated.afterPartNumber ?? 0;
1695
+ const limit = validated.limit ?? 100;
1696
+ return execute(runtime, validated.signal, null, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}", {
1697
+ ...operationOptions("getUploadStatus", { params: {
1698
+ path: {
1699
+ workspaceId: validated.workspaceId,
1700
+ uploadId: validated.uploadId
1701
+ },
1702
+ query: {
1703
+ ...validated.afterPartNumber === void 0 ? {} : { afterPartNumber: String(validated.afterPartNumber) },
1704
+ ...validated.limit === void 0 ? {} : { limit: String(validated.limit) }
1705
+ }
1706
+ } }),
1707
+ ...requestOptions
1708
+ }), [200], (value) => isUploadStatus(value, afterPartNumber, limit), false, STATUS_ERROR_CODES);
1709
+ }
1710
+ async function createUploadPartDescriptor(runtime, input) {
1711
+ const validated = validateCreateUploadPartDescriptorInput(input);
1712
+ return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}/parts", {
1713
+ ...operationOptions("createUploadPartDescriptor", {
1714
+ params: { path: {
1715
+ workspaceId: validated.workspaceId,
1716
+ uploadId: validated.uploadId
1717
+ } },
1718
+ body: {
1719
+ partNumber: validated.partNumber,
1720
+ checksumSha256: validated.checksumSha256
1721
+ }
1722
+ }),
1723
+ ...requestOptions
1724
+ }), [200], (value) => isUploadPartDescriptor(value, validated.partNumber, validated.checksumSha256, new URL(runtime.baseUrl).protocol === "http:"), false, TRANSFER_ERROR_CODES);
1725
+ }
1726
+ async function recordUploadPart(runtime, input) {
1727
+ const validated = validateRecordUploadPartInput(input);
1728
+ return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}/parts/{partNumber}", {
1729
+ ...operationOptions("recordUploadPart", {
1730
+ params: { path: {
1731
+ workspaceId: validated.workspaceId,
1732
+ uploadId: validated.uploadId,
1733
+ partNumber: String(validated.partNumber)
1734
+ } },
1735
+ body: {
1736
+ expectedUploadRevision: validated.expectedUploadRevision,
1737
+ byteLength: validated.byteLength,
1738
+ etag: validated.etag,
1739
+ checksumSha256: validated.checksumSha256
1740
+ }
1741
+ }),
1742
+ ...requestOptions
1743
+ }), [200], (value) => isUploadPartResult(value, validated.partNumber, validated.expectedUploadRevision), false, TRANSFER_ERROR_CODES);
1744
+ }
1745
+ async function completeUpload(runtime, input) {
1746
+ const validated = validateCompleteUploadInput(input);
1747
+ return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}/complete", {
1748
+ ...operationOptions("completeUpload", { params: {
1749
+ path: {
1750
+ workspaceId: validated.workspaceId,
1751
+ uploadId: validated.uploadId
1752
+ },
1753
+ header: { "Idempotency-Key": validated.idempotencyKey }
1754
+ } }),
1755
+ ...requestOptions
1756
+ }), [200], (value) => isReadyUpload(value, { uploadId: validated.uploadId }), false, COMPLETE_UPLOAD_ERROR_CODES);
1383
1757
  }
1384
1758
  async function abortUpload(runtime, input) {
1385
1759
  const validated = validateAbortUploadInput(input);
@@ -1389,12 +1763,717 @@ async function abortUpload(runtime, input) {
1389
1763
  uploadId: validated.uploadId
1390
1764
  } } }),
1391
1765
  ...requestOptions
1392
- }), [200], (value) => isUploadQuotaReservation(value) && value.workspaceId === validated.workspaceId && value.uploadId === validated.uploadId && value.state === "released" && value.terminalReason === "aborted" && value.terminalAtEpochMilliseconds !== null);
1766
+ }), [204], null, false, TRANSFER_ERROR_CODES);
1767
+ }
1768
+ //#endregion
1769
+ //#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/_u64.js
1770
+ const fromNumH = (n) => n / 2 ** 32 | 0;
1771
+ const fromNumL = (n) => n >>> 0;
1772
+ function setU64FromNum(view, byteOffset, n, isLE) {
1773
+ const h = fromNumH(n);
1774
+ const l = fromNumL(n);
1775
+ view.setUint32(byteOffset, isLE ? l : h, isLE);
1776
+ view.setUint32(byteOffset + 4, isLE ? h : l, isLE);
1777
+ }
1778
+ //#endregion
1779
+ //#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/utils.js
1780
+ function isBytes(a) {
1781
+ return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
1782
+ }
1783
+ const atitle = (title) => title ? `"${title}" ` : "";
1784
+ function anumber(n, title = "") {
1785
+ if (typeof n !== "number") throw new TypeError(atitle(title) + "expected number, got " + typeof n);
1786
+ if (!Number.isSafeInteger(n) || n < 0) throw new RangeError(atitle(title) + "expected integer >= 0, got " + n);
1787
+ return n;
1788
+ }
1789
+ function abytes(value, length, title = "") {
1790
+ if (isBytes(value) && (length === void 0 || value.length === length)) return value;
1791
+ if (length !== void 0) anumber(length, "length");
1792
+ const bytes = isBytes(value);
1793
+ const ofLen = length !== void 0 ? ` of length ${length}` : "";
1794
+ const got = bytes ? `length=${value.length}` : `type=${typeof value}`;
1795
+ const message = atitle(title) + "expected Uint8Array" + ofLen + ", got " + got;
1796
+ if (!bytes) throw new TypeError(message);
1797
+ throw new RangeError(message);
1798
+ }
1799
+ const aobject = (value, label) => {
1800
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new TypeError((label === "object" ? "" : `"${label}" `) + "expected object, got type=" + typeof value);
1801
+ };
1802
+ function aexists(instance, checkFinished = true) {
1803
+ if (instance.destroyed) throw new Error("hash was destroyed");
1804
+ if (checkFinished && instance.finished) throw new Error("digest() was already called");
1805
+ }
1806
+ function aoutput(out, instance) {
1807
+ abytes(out, void 0, "output");
1808
+ const min = instance.outputLen;
1809
+ if (!(out.length >= min)) throw new RangeError("\"output\" expected length >= " + min);
1810
+ }
1811
+ function clean(...arrays) {
1812
+ for (let i = 0; i < arrays.length; i++) arrays[i].fill(0);
1813
+ }
1814
+ function createView(arr) {
1815
+ return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
1816
+ }
1817
+ function rotr(word, shift) {
1818
+ return word << 32 - shift | word >>> shift;
1819
+ }
1820
+ const hasHexBuiltin = (() => typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function")();
1821
+ const hexes = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
1822
+ function bytesToHex(bytes) {
1823
+ abytes(bytes);
1824
+ if (hasHexBuiltin) return bytes.toHex();
1825
+ let hex = "";
1826
+ for (let i = 0; i < bytes.length; i++) hex += hexes[bytes[i]];
1827
+ return hex;
1828
+ }
1829
+ function checkOpts(defaults, opts, title = "opts") {
1830
+ aobject(defaults, "defaults");
1831
+ if (opts !== void 0) aobject(opts, title);
1832
+ return Object.assign(defaults, opts);
1833
+ }
1834
+ function createHasher(hashCons, info = {}) {
1835
+ if (typeof hashCons !== "function") throw new TypeError("\"hashCons\" expected function, got type=" + typeof hashCons);
1836
+ info = checkOpts({}, info, "info");
1837
+ const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
1838
+ const tmp = hashCons(void 0);
1839
+ hashC.outputLen = tmp.outputLen;
1840
+ hashC.blockLen = tmp.blockLen;
1841
+ hashC.canXOF = tmp.canXOF;
1842
+ hashC.create = (opts) => hashCons(opts);
1843
+ Object.assign(hashC, info);
1844
+ return Object.freeze(hashC);
1845
+ }
1846
+ const oidNist = (suffix) => ({ oid: Uint8Array.from([
1847
+ 6,
1848
+ 9,
1849
+ 96,
1850
+ 134,
1851
+ 72,
1852
+ 1,
1853
+ 101,
1854
+ 3,
1855
+ 4,
1856
+ 2,
1857
+ suffix
1858
+ ]) });
1859
+ //#endregion
1860
+ //#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/_md.js
1861
+ function Chi(a, b, c) {
1862
+ return a & b ^ ~a & c;
1863
+ }
1864
+ function Maj(a, b, c) {
1865
+ return a & b ^ a & c ^ b & c;
1866
+ }
1867
+ var HashMD = class {
1868
+ blockLen;
1869
+ outputLen;
1870
+ canXOF = false;
1871
+ padOffset;
1872
+ isLE;
1873
+ buffer;
1874
+ view;
1875
+ finished = false;
1876
+ length = 0;
1877
+ pos = 0;
1878
+ destroyed = false;
1879
+ constructor(blockLen, outputLen, padOffset, isLE) {
1880
+ this.blockLen = blockLen;
1881
+ this.outputLen = outputLen;
1882
+ this.padOffset = padOffset;
1883
+ this.isLE = isLE;
1884
+ this.buffer = new Uint8Array(blockLen);
1885
+ this.view = createView(this.buffer);
1886
+ }
1887
+ update(data) {
1888
+ aexists(this);
1889
+ abytes(data);
1890
+ const { view, buffer, blockLen } = this;
1891
+ const len = data.length;
1892
+ let processed = false;
1893
+ for (let pos = 0; pos < len;) {
1894
+ const take = Math.min(blockLen - this.pos, len - pos);
1895
+ if (take === blockLen) {
1896
+ const dataView = createView(data);
1897
+ for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos);
1898
+ processed = true;
1899
+ continue;
1900
+ }
1901
+ buffer.set(pos === 0 && take === len ? data : data.subarray(pos, pos + take), this.pos);
1902
+ this.pos += take;
1903
+ pos += take;
1904
+ if (this.pos === blockLen) {
1905
+ this.process(view, 0);
1906
+ this.pos = 0;
1907
+ processed = true;
1908
+ }
1909
+ }
1910
+ this.length += data.length;
1911
+ if (processed) this.roundClean();
1912
+ return this;
1913
+ }
1914
+ digestInto(out) {
1915
+ aexists(this);
1916
+ aoutput(out, this);
1917
+ this.finished = true;
1918
+ const { buffer, view, blockLen, isLE } = this;
1919
+ let { pos } = this;
1920
+ buffer[pos++] = 128;
1921
+ buffer.fill(0, pos);
1922
+ if (this.padOffset > blockLen - pos) {
1923
+ this.process(view, 0);
1924
+ buffer.fill(0);
1925
+ }
1926
+ setU64FromNum(view, blockLen - 8, this.length * 8, isLE);
1927
+ this.process(view, 0);
1928
+ this.roundClean();
1929
+ const oview = out === buffer ? view : createView(out);
1930
+ const len = this.outputLen;
1931
+ const outLen = len / 4;
1932
+ const state = this.get();
1933
+ if (len % 4 || outLen > state.length) throw new Error("invalid outputLen");
1934
+ for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE);
1935
+ }
1936
+ digest() {
1937
+ const { buffer, outputLen } = this;
1938
+ this.digestInto(buffer);
1939
+ const res = buffer.slice(0, outputLen);
1940
+ this.destroy();
1941
+ return res;
1942
+ }
1943
+ _cloneIntoMeta(to) {
1944
+ const { buffer, length, finished, destroyed, pos } = this;
1945
+ to.destroyed = destroyed;
1946
+ to.finished = finished;
1947
+ to.length = length;
1948
+ to.pos = pos;
1949
+ if (pos) to.buffer.set(buffer);
1950
+ return to;
1951
+ }
1952
+ clone() {
1953
+ return this._cloneInto();
1954
+ }
1955
+ };
1956
+ const SHA256_IV = Uint32Array.from([
1957
+ 1779033703,
1958
+ 3144134277,
1959
+ 1013904242,
1960
+ 2773480762,
1961
+ 1359893119,
1962
+ 2600822924,
1963
+ 528734635,
1964
+ 1541459225
1965
+ ]);
1966
+ //#endregion
1967
+ //#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/sha2.js
1968
+ const SHA256_K = Uint32Array.from([
1969
+ 1116352408,
1970
+ 1899447441,
1971
+ 3049323471,
1972
+ 3921009573,
1973
+ 961987163,
1974
+ 1508970993,
1975
+ 2453635748,
1976
+ 2870763221,
1977
+ 3624381080,
1978
+ 310598401,
1979
+ 607225278,
1980
+ 1426881987,
1981
+ 1925078388,
1982
+ 2162078206,
1983
+ 2614888103,
1984
+ 3248222580,
1985
+ 3835390401,
1986
+ 4022224774,
1987
+ 264347078,
1988
+ 604807628,
1989
+ 770255983,
1990
+ 1249150122,
1991
+ 1555081692,
1992
+ 1996064986,
1993
+ 2554220882,
1994
+ 2821834349,
1995
+ 2952996808,
1996
+ 3210313671,
1997
+ 3336571891,
1998
+ 3584528711,
1999
+ 113926993,
2000
+ 338241895,
2001
+ 666307205,
2002
+ 773529912,
2003
+ 1294757372,
2004
+ 1396182291,
2005
+ 1695183700,
2006
+ 1986661051,
2007
+ 2177026350,
2008
+ 2456956037,
2009
+ 2730485921,
2010
+ 2820302411,
2011
+ 3259730800,
2012
+ 3345764771,
2013
+ 3516065817,
2014
+ 3600352804,
2015
+ 4094571909,
2016
+ 275423344,
2017
+ 430227734,
2018
+ 506948616,
2019
+ 659060556,
2020
+ 883997877,
2021
+ 958139571,
2022
+ 1322822218,
2023
+ 1537002063,
2024
+ 1747873779,
2025
+ 1955562222,
2026
+ 2024104815,
2027
+ 2227730452,
2028
+ 2361852424,
2029
+ 2428436474,
2030
+ 2756734187,
2031
+ 3204031479,
2032
+ 3329325298
2033
+ ]);
2034
+ const SHA256_W = new Uint32Array(64);
2035
+ var SHA2_32B = class extends HashMD {
2036
+ A = 0;
2037
+ B = 0;
2038
+ C = 0;
2039
+ D = 0;
2040
+ E = 0;
2041
+ F = 0;
2042
+ G = 0;
2043
+ H = 0;
2044
+ constructor(outputLen, IV) {
2045
+ super(64, outputLen, 8, false);
2046
+ this.A = IV[0] | 0;
2047
+ this.B = IV[1] | 0;
2048
+ this.C = IV[2] | 0;
2049
+ this.D = IV[3] | 0;
2050
+ this.E = IV[4] | 0;
2051
+ this.F = IV[5] | 0;
2052
+ this.G = IV[6] | 0;
2053
+ this.H = IV[7] | 0;
2054
+ }
2055
+ get() {
2056
+ const { A, B, C, D, E, F, G, H } = this;
2057
+ return [
2058
+ A,
2059
+ B,
2060
+ C,
2061
+ D,
2062
+ E,
2063
+ F,
2064
+ G,
2065
+ H
2066
+ ];
2067
+ }
2068
+ set(A, B, C, D, E, F, G, H) {
2069
+ this.A = A | 0;
2070
+ this.B = B | 0;
2071
+ this.C = C | 0;
2072
+ this.D = D | 0;
2073
+ this.E = E | 0;
2074
+ this.F = F | 0;
2075
+ this.G = G | 0;
2076
+ this.H = H | 0;
2077
+ }
2078
+ _cloneInto(to) {
2079
+ (to ||= new this.constructor()).set(...this.get());
2080
+ return this._cloneIntoMeta(to);
2081
+ }
2082
+ process(view, offset) {
2083
+ for (let i = 0; i < 16; i++, offset += 4) SHA256_W[i] = view.getUint32(offset, false);
2084
+ for (let i = 16; i < 64; i++) {
2085
+ const W15 = SHA256_W[i - 15];
2086
+ const W2 = SHA256_W[i - 2];
2087
+ const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
2088
+ const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
2089
+ SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
2090
+ }
2091
+ let { A, B, C, D, E, F, G, H } = this;
2092
+ for (let i = 0; i < 64; i++) {
2093
+ const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
2094
+ const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
2095
+ const T2 = (rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22)) + Maj(A, B, C) | 0;
2096
+ H = G;
2097
+ G = F;
2098
+ F = E;
2099
+ E = D + T1 | 0;
2100
+ D = C;
2101
+ C = B;
2102
+ B = A;
2103
+ A = T1 + T2 | 0;
2104
+ }
2105
+ A = A + this.A | 0;
2106
+ B = B + this.B | 0;
2107
+ C = C + this.C | 0;
2108
+ D = D + this.D | 0;
2109
+ E = E + this.E | 0;
2110
+ F = F + this.F | 0;
2111
+ G = G + this.G | 0;
2112
+ H = H + this.H | 0;
2113
+ this.set(A, B, C, D, E, F, G, H);
2114
+ }
2115
+ roundClean() {
2116
+ clean(SHA256_W);
2117
+ }
2118
+ destroy() {
2119
+ this.destroyed = true;
2120
+ this.set(0, 0, 0, 0, 0, 0, 0, 0);
2121
+ clean(this.buffer);
2122
+ }
2123
+ };
2124
+ var _SHA256 = class extends SHA2_32B {
2125
+ constructor() {
2126
+ super(32, SHA256_IV);
2127
+ }
2128
+ };
2129
+ const sha256 = createHasher(() => new _SHA256(), oidNist(1));
2130
+ //#endregion
2131
+ //#region src/internal/client/upload.ts
2132
+ const UPLOAD_PART_BYTE_LENGTH = 32 * 1024 * 1024;
2133
+ const STATUS_PAGE_LIMIT = 100;
2134
+ const STATUS_PAGE_MAXIMUM = 100;
2135
+ const ABORT_DEADLINE_MILLISECONDS = 5e3;
2136
+ async function uploadFileInternal(runtime, input, controls) {
2137
+ const validated = validateUploadFileInput(input);
2138
+ const totalPartCount = Math.ceil(validated.byteLength / UPLOAD_PART_BYTE_LENGTH);
2139
+ emitProgress(validated.onProgress, "preparing", 0, validated.byteLength, 0, totalPartCount);
2140
+ let session;
2141
+ try {
2142
+ const digests = await hashSource(validated.source, validated.byteLength, totalPartCount, validated.signal);
2143
+ const created = await controls.createUpload({
2144
+ workspaceId: validated.workspaceId,
2145
+ parentItemId: validated.parentItemId,
2146
+ expectedByteLength: validated.byteLength,
2147
+ displayFilename: validated.displayFilename,
2148
+ mediaType: validated.mediaType,
2149
+ callerDeclaredContentDigest: digests.callerDeclaredContentDigest,
2150
+ protectionClassification: validated.protectionClassification,
2151
+ idempotencyKey: validated.idempotencyKey,
2152
+ ...validated.signal === void 0 ? {} : { signal: validated.signal }
2153
+ });
2154
+ session = created.data;
2155
+ assertSessionPolicy(session, validated.byteLength, totalPartCount, created.status, created.requestId);
2156
+ const resumed = await readResumeState(controls, validated, session, digests);
2157
+ emitProgress(validated.onProgress, "uploading", resumed.confirmedByteLength, validated.byteLength, resumed.confirmedParts.size, totalPartCount);
2158
+ if (resumed.readyResult) {
2159
+ emitProgress(validated.onProgress, "completing", resumed.confirmedByteLength, validated.byteLength, resumed.confirmedParts.size, totalPartCount);
2160
+ return resumed.readyResult;
2161
+ }
2162
+ let revision = resumed.revision;
2163
+ let confirmedByteLength = resumed.confirmedByteLength;
2164
+ let confirmedPartCount = resumed.confirmedParts.size;
2165
+ if (resumed.lifecycle === "uploading") for (const partNumber of pendingUploadPartNumbers(session.partCount, resumed.confirmedParts)) {
2166
+ const index = partNumber - 1;
2167
+ throwIfCallerAborted(validated.signal);
2168
+ const start = index * session.partByteLength;
2169
+ const end = Math.min(start + session.partByteLength, validated.byteLength);
2170
+ const expectedByteLength = end - start;
2171
+ const checksumSha256 = digests.partChecksums[index];
2172
+ if (!checksumSha256) throw new DriveError("invalid_response");
2173
+ const descriptorResult = await controls.createUploadPartDescriptor({
2174
+ workspaceId: validated.workspaceId,
2175
+ uploadId: session.uploadId,
2176
+ partNumber,
2177
+ checksumSha256,
2178
+ ...validated.signal === void 0 ? {} : { signal: validated.signal }
2179
+ });
2180
+ const descriptor = descriptorResult.data;
2181
+ if (descriptor.expectedByteLength !== expectedByteLength || descriptor.expiresAtEpochMilliseconds > session.expiresAtEpochMilliseconds) throw new DriveError("invalid_response", {
2182
+ status: descriptorResult.status,
2183
+ requestId: descriptorResult.requestId
2184
+ });
2185
+ const etag = await putPart(runtime, descriptor, slicePart(validated.source, start, end, expectedByteLength), checksumSha256, validated.signal);
2186
+ revision = await recordPartWithReconciliation(controls, validated, session, partNumber, revision, expectedByteLength, etag, checksumSha256);
2187
+ confirmedByteLength += expectedByteLength;
2188
+ confirmedPartCount += 1;
2189
+ emitProgress(validated.onProgress, "uploading", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
2190
+ }
2191
+ emitProgress(validated.onProgress, "completing", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
2192
+ return await completeWithReconciliation(controls, validated, session, digests);
2193
+ } catch (error) {
2194
+ if (validated.signal?.aborted && session) await bestEffortAbort(controls, validated.workspaceId, session.uploadId);
2195
+ if (error instanceof DriveError) throw error;
2196
+ throw validated.signal?.aborted ? new DriveError("aborted") : new DriveError("invalid_input");
2197
+ }
2198
+ }
2199
+ function* pendingUploadPartNumbers(partCount, confirmedParts) {
2200
+ for (let partNumber = 1; partNumber <= partCount; partNumber += 1) if (!confirmedParts.has(partNumber)) yield partNumber;
2201
+ }
2202
+ async function readResumeState(controls, input, session, digests) {
2203
+ const confirmedParts = new Set();
2204
+ let confirmedByteLength = 0;
2205
+ let afterPartNumber = 0;
2206
+ let baseline;
2207
+ let baselineRequestId;
2208
+ let readyResult;
2209
+ for (let pageNumber = 0; pageNumber < STATUS_PAGE_MAXIMUM; pageNumber += 1) {
2210
+ const result = await controls.getUploadStatus({
2211
+ workspaceId: input.workspaceId,
2212
+ uploadId: session.uploadId,
2213
+ afterPartNumber,
2214
+ limit: STATUS_PAGE_LIMIT,
2215
+ ...input.signal === void 0 ? {} : { signal: input.signal }
2216
+ });
2217
+ const status = result.data;
2218
+ assertStatusMatchesSession(status, session);
2219
+ if (baseline) assertSameStatusSnapshot(status, baseline);
2220
+ else {
2221
+ baseline = status;
2222
+ baselineRequestId = result.requestId;
2223
+ }
2224
+ for (const part of status.confirmedParts) {
2225
+ const expectedChecksum = digests.partChecksums[part.partNumber - 1];
2226
+ if (!expectedChecksum || part.checksumSha256 !== expectedChecksum || confirmedParts.has(part.partNumber)) throw new DriveError("invalid_response", {
2227
+ status: result.status,
2228
+ requestId: result.requestId
2229
+ });
2230
+ confirmedParts.add(part.partNumber);
2231
+ confirmedByteLength += expectedPartByteLength(input.byteLength, part.partNumber);
2232
+ }
2233
+ if (status.lifecycle === "ready" && status.ready) {
2234
+ assertReadyMatchesInput(status.ready, session, input, digests, result.requestId);
2235
+ readyResult = resultFromStatus(result, status.ready);
2236
+ }
2237
+ if (status.nextAfterPartNumber === null) break;
2238
+ if (pageNumber === STATUS_PAGE_MAXIMUM - 1) throw new DriveError("invalid_response", {
2239
+ status: result.status,
2240
+ requestId: result.requestId
2241
+ });
2242
+ afterPartNumber = status.nextAfterPartNumber;
2243
+ }
2244
+ if (!baseline) throw new DriveError("invalid_response");
2245
+ if (session.mode === "presigned-multipart" && [
2246
+ "completing",
2247
+ "provider-completed",
2248
+ "ready"
2249
+ ].includes(baseline.lifecycle) && confirmedParts.size !== session.partCount) throw new DriveError("invalid_response");
2250
+ failForTerminalStatus(baseline.lifecycle, baselineRequestId);
2251
+ return Object.freeze({
2252
+ revision: baseline.revision,
2253
+ confirmedParts,
2254
+ confirmedByteLength,
2255
+ lifecycle: baseline.lifecycle,
2256
+ ...readyResult === void 0 ? {} : { readyResult }
2257
+ });
2258
+ }
2259
+ async function recordPartWithReconciliation(controls, input, session, partNumber, expectedUploadRevision, byteLength, etag, checksumSha256) {
2260
+ const record = (revision) => controls.recordUploadPart({
2261
+ workspaceId: input.workspaceId,
2262
+ uploadId: session.uploadId,
2263
+ partNumber,
2264
+ expectedUploadRevision: revision,
2265
+ byteLength,
2266
+ etag,
2267
+ checksumSha256,
2268
+ ...input.signal === void 0 ? {} : { signal: input.signal }
2269
+ });
2270
+ try {
2271
+ return (await record(expectedUploadRevision)).data.revision;
2272
+ } catch (error) {
2273
+ if (!isAmbiguousControlFailure(error) || input.signal?.aborted) throw error;
2274
+ const statusResult = await controls.getUploadStatus({
2275
+ workspaceId: input.workspaceId,
2276
+ uploadId: session.uploadId,
2277
+ afterPartNumber: partNumber - 1,
2278
+ limit: 1,
2279
+ ...input.signal === void 0 ? {} : { signal: input.signal }
2280
+ });
2281
+ const status = statusResult.data;
2282
+ assertStatusMatchesSession(status, session);
2283
+ failForTerminalStatus(status.lifecycle, statusResult.requestId);
2284
+ const confirmed = status.confirmedParts.find((part) => part.partNumber === partNumber);
2285
+ if (confirmed) {
2286
+ if (confirmed.checksumSha256 !== checksumSha256) throw new DriveError("invalid_response", {
2287
+ status: statusResult.status,
2288
+ requestId: statusResult.requestId
2289
+ });
2290
+ return status.revision;
2291
+ }
2292
+ if (status.lifecycle !== "uploading") throw new DriveError("precondition_failed");
2293
+ return (await record(status.revision)).data.revision;
2294
+ }
2295
+ }
2296
+ async function completeWithReconciliation(controls, input, session, digests) {
2297
+ try {
2298
+ const completed = await controls.completeUpload({
2299
+ workspaceId: input.workspaceId,
2300
+ uploadId: session.uploadId,
2301
+ idempotencyKey: input.completionIdempotencyKey,
2302
+ ...input.signal === void 0 ? {} : { signal: input.signal }
2303
+ });
2304
+ assertReadyMatchesInput(completed.data, session, input, digests, completed.requestId);
2305
+ return completed;
2306
+ } catch (error) {
2307
+ if (!isAmbiguousControlFailure(error) || input.signal?.aborted) throw error;
2308
+ const statusResult = await controls.getUploadStatus({
2309
+ workspaceId: input.workspaceId,
2310
+ uploadId: session.uploadId,
2311
+ afterPartNumber: 0,
2312
+ limit: 1,
2313
+ ...input.signal === void 0 ? {} : { signal: input.signal }
2314
+ });
2315
+ const status = statusResult.data;
2316
+ assertStatusMatchesSession(status, session);
2317
+ if (status.lifecycle !== "ready" || !status.ready) throw error;
2318
+ assertReadyMatchesInput(status.ready, session, input, digests, statusResult.requestId);
2319
+ return resultFromStatus(statusResult, status.ready);
2320
+ }
2321
+ }
2322
+ async function hashSource(source, byteLength, partCount, signal) {
2323
+ const fullHash = sha256.create();
2324
+ const partChecksums = [];
2325
+ for (let index = 0; index < partCount; index += 1) {
2326
+ throwIfCallerAborted(signal);
2327
+ const start = index * UPLOAD_PART_BYTE_LENGTH;
2328
+ const end = Math.min(start + UPLOAD_PART_BYTE_LENGTH, byteLength);
2329
+ const part = slicePart(source, start, end, end - start);
2330
+ let buffer;
2331
+ try {
2332
+ buffer = signal ? await raceWithAbort(part.arrayBuffer(), signal) : await part.arrayBuffer();
2333
+ } catch (error) {
2334
+ if (error instanceof DriveError) throw error;
2335
+ throw signal?.aborted ? new DriveError("aborted") : new DriveError("invalid_input");
2336
+ }
2337
+ if (buffer.byteLength !== end - start) throw new DriveError("invalid_input");
2338
+ const bytes = new Uint8Array(buffer);
2339
+ fullHash.update(bytes);
2340
+ partChecksums.push(toBase64(sha256(bytes)));
2341
+ }
2342
+ return Object.freeze({
2343
+ callerDeclaredContentDigest: `sha256:${bytesToHex(fullHash.digest())}`,
2344
+ partChecksums: Object.freeze(partChecksums)
2345
+ });
2346
+ }
2347
+ async function putPart(runtime, descriptor, part, checksumSha256, callerSignal) {
2348
+ const remainingMilliseconds = descriptor.expiresAtEpochMilliseconds - Date.now();
2349
+ if (remainingMilliseconds < 1) throw new DriveError("invalid_response");
2350
+ const operation = createOperationSignal(callerSignal, Math.min(runtime.timeoutMilliseconds, remainingMilliseconds));
2351
+ let response;
2352
+ try {
2353
+ response = await raceWithAbort(runtime.fetchImplementation(descriptor.url, {
2354
+ method: descriptor.method,
2355
+ body: part,
2356
+ headers: descriptor.headers,
2357
+ credentials: "omit",
2358
+ cache: "no-store",
2359
+ redirect: "error",
2360
+ referrerPolicy: "no-referrer",
2361
+ signal: operation.signal
2362
+ }), operation.signal);
2363
+ if (!(response instanceof Response)) throw new DriveError("invalid_response");
2364
+ const etag = response.headers.get("etag");
2365
+ const responseChecksum = response.headers.get("x-amz-checksum-sha256");
2366
+ if (response.status < 200 || response.status > 299 || !isEtag(etag) || responseChecksum !== checksumSha256) throw new DriveError("invalid_response", { status: response.status });
2367
+ return etag;
2368
+ } catch (error) {
2369
+ if (operation.didTimeout()) throw new DriveError("timeout");
2370
+ if (callerSignal?.aborted) throw new DriveError("aborted");
2371
+ if (error instanceof DriveError) throw error;
2372
+ throw new DriveError("network_error");
2373
+ } finally {
2374
+ operation.dispose();
2375
+ response?.body?.cancel().catch(() => {});
2376
+ }
2377
+ }
2378
+ function assertSessionPolicy(session, byteLength, partCount, status, requestId) {
2379
+ const expectedMode = byteLength === 0 ? "server-mediated-zero-byte" : "presigned-multipart";
2380
+ if (session.mode !== expectedMode || session.partByteLength !== UPLOAD_PART_BYTE_LENGTH || session.partCount !== partCount || session.expiresAtEpochMilliseconds <= Date.now()) throw new DriveError("invalid_response", {
2381
+ status,
2382
+ requestId
2383
+ });
2384
+ }
2385
+ function assertStatusMatchesSession(status, session) {
2386
+ if (status.itemId !== session.itemId || status.versionId !== session.versionId || status.uploadId !== session.uploadId || status.mode !== session.mode || status.revision < session.revision || status.partPolicy.partByteLength !== session.partByteLength || status.partPolicy.partCount !== session.partCount || status.partPolicy.maxParts !== 1e4 || status.expiresAtEpochMilliseconds !== session.expiresAtEpochMilliseconds) throw new DriveError("invalid_response");
2387
+ }
2388
+ function assertSameStatusSnapshot(status, baseline) {
2389
+ if (status.itemId !== baseline.itemId || status.versionId !== baseline.versionId || status.uploadId !== baseline.uploadId || status.mode !== baseline.mode || status.lifecycle !== baseline.lifecycle || status.revision !== baseline.revision || status.partPolicy.partByteLength !== baseline.partPolicy.partByteLength || status.partPolicy.partCount !== baseline.partPolicy.partCount || status.partPolicy.maxParts !== baseline.partPolicy.maxParts || status.expiresAtEpochMilliseconds !== baseline.expiresAtEpochMilliseconds || JSON.stringify(status.ready) !== JSON.stringify(baseline.ready)) throw new DriveError("invalid_response");
2390
+ }
2391
+ function assertReadyMatchesInput(ready, session, input, digests, requestId) {
2392
+ if (ready.itemId !== session.itemId || ready.versionId !== session.versionId || ready.uploadId !== session.uploadId || ready.byteLength !== input.byteLength || ready.callerDeclaredContentDigest !== digests.callerDeclaredContentDigest || ready.displayFilename !== input.displayFilename || ready.mediaType !== input.mediaType) throw new DriveError("invalid_response", {
2393
+ status: 200,
2394
+ requestId
2395
+ });
2396
+ }
2397
+ function failForTerminalStatus(lifecycle, requestId) {
2398
+ if (lifecycle === "initiating" || lifecycle === "recovery-required") throw new DriveError("upload_recovery_required", {
2399
+ status: 409,
2400
+ ...requestId === void 0 ? {} : { requestId }
2401
+ });
2402
+ if (lifecycle === "aborting" || lifecycle === "aborted") throw new DriveError("precondition_failed", {
2403
+ status: 409,
2404
+ ...requestId === void 0 ? {} : { requestId }
2405
+ });
2406
+ }
2407
+ function resultFromStatus(status, ready) {
2408
+ return Object.freeze({
2409
+ data: ready,
2410
+ status: status.status,
2411
+ requestId: status.requestId,
2412
+ validators: status.validators
2413
+ });
2414
+ }
2415
+ function expectedPartByteLength(byteLength, partNumber) {
2416
+ return Math.min(UPLOAD_PART_BYTE_LENGTH, byteLength - (partNumber - 1) * UPLOAD_PART_BYTE_LENGTH);
2417
+ }
2418
+ function slicePart(source, start, end, expectedByteLength) {
2419
+ try {
2420
+ const part = source.slice(start, end);
2421
+ if (!(part instanceof Blob) || part.size !== expectedByteLength) throw new DriveError("invalid_input");
2422
+ return part;
2423
+ } catch (error) {
2424
+ if (error instanceof DriveError) throw error;
2425
+ throw new DriveError("invalid_input");
2426
+ }
2427
+ }
2428
+ function emitProgress(callback, phase, confirmedByteLength, totalByteLength, confirmedPartCount, totalPartCount) {
2429
+ if (!callback) return;
2430
+ const progress = Object.freeze({
2431
+ phase,
2432
+ confirmedByteLength,
2433
+ totalByteLength,
2434
+ confirmedPartCount,
2435
+ totalPartCount
2436
+ });
2437
+ try {
2438
+ callback(progress);
2439
+ } catch {}
2440
+ }
2441
+ async function bestEffortAbort(controls, workspaceId, uploadId) {
2442
+ const controller = new AbortController();
2443
+ const timeout = setTimeout(() => controller.abort(), ABORT_DEADLINE_MILLISECONDS);
2444
+ try {
2445
+ await controls.abortUpload({
2446
+ workspaceId,
2447
+ uploadId,
2448
+ signal: controller.signal
2449
+ });
2450
+ } catch {} finally {
2451
+ clearTimeout(timeout);
2452
+ }
2453
+ }
2454
+ function isAmbiguousControlFailure(value) {
2455
+ return value instanceof DriveError && (value.code === "network_error" || value.code === "timeout" || value.code === "invalid_response");
2456
+ }
2457
+ function throwIfCallerAborted(signal) {
2458
+ if (signal?.aborted) throw new DriveError("aborted");
2459
+ }
2460
+ function toBase64(bytes) {
2461
+ let binary = "";
2462
+ for (const byte of bytes) binary += String.fromCharCode(byte);
2463
+ return btoa(binary);
2464
+ }
2465
+ function isEtag(value) {
2466
+ return value !== null && value.length >= 1 && value.length <= 1024 && /^[\x20-\x7e]+$/.test(value);
1393
2467
  }
1394
2468
  //#endregion
1395
2469
  //#region src/client.ts
1396
2470
  function createDriveClient(config) {
1397
- return createDriveClientInternal(config);
2471
+ const runtime = createClientRuntime(config);
2472
+ const operations = createDriveOperations(runtime);
2473
+ return Object.freeze({
2474
+ ...operations,
2475
+ uploadFile: (input) => uploadFileInternal(runtime, input, operations)
2476
+ });
1398
2477
  }
1399
2478
  //#endregion
1400
2479
  export { DRIVE_API_ERROR_CODES, DRIVE_API_ERROR_MESSAGES, DriveError, createDriveClient };