@finueva/drive 0.2.0 → 0.5.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 +21 -0
- package/README.md +67 -9
- package/THIRD_PARTY_NOTICES.md +26 -0
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1809 -28
- package/dist/contract.d.ts +3046 -443
- package/dist/core.d.ts +3 -1
- package/dist/core.js +4 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1809 -28
- package/dist/server.d.ts +3 -3
- package/dist/server.js +1062 -25
- package/dist/types.d.ts +2 -2
- package/package.json +6 -2
package/dist/client.js
CHANGED
|
@@ -8,8 +8,10 @@ const DRIVE_API_ERROR_CODES = Object.freeze([
|
|
|
8
8
|
"invalid_pagination_cursor",
|
|
9
9
|
"invalid_idempotency_key",
|
|
10
10
|
"precondition_failed",
|
|
11
|
+
"range_not_satisfiable",
|
|
11
12
|
"idempotency_conflict",
|
|
12
13
|
"quota_exceeded",
|
|
14
|
+
"upload_recovery_required",
|
|
13
15
|
"service_unavailable",
|
|
14
16
|
"internal_error"
|
|
15
17
|
]);
|
|
@@ -22,8 +24,10 @@ const DRIVE_API_ERROR_MESSAGES = Object.freeze({
|
|
|
22
24
|
invalid_pagination_cursor: "The pagination cursor is invalid.",
|
|
23
25
|
invalid_idempotency_key: "The idempotency key is invalid.",
|
|
24
26
|
precondition_failed: "The request precondition failed.",
|
|
27
|
+
range_not_satisfiable: "The requested byte range is not satisfiable.",
|
|
25
28
|
idempotency_conflict: "The idempotency key conflicts with an earlier request.",
|
|
26
29
|
quota_exceeded: "The workspace storage quota would be exceeded.",
|
|
30
|
+
upload_recovery_required: "The upload requires recovery before it can continue.",
|
|
27
31
|
service_unavailable: "The service is temporarily unavailable.",
|
|
28
32
|
internal_error: "The request could not be completed."
|
|
29
33
|
});
|
|
@@ -59,6 +63,7 @@ const REQUEST_ID = /^[A-Za-z0-9_-]{16,128}$/;
|
|
|
59
63
|
const COLLECTION_ETAG = /^"drive\.permission-collection\.v1\.(0|[1-9][0-9]*)"$/;
|
|
60
64
|
const GRANT_ETAG$1 = /^"drive\.permission-grant\.v1\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"$/;
|
|
61
65
|
const LIST_ETAG$1 = /^"drive\.permission-list\.v1\.[0-9a-f]{64}"$/;
|
|
66
|
+
const ITEM_ETAG = /^"drive\.item\.v1\.(0|[1-9][0-9]*)"$/;
|
|
62
67
|
async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes) {
|
|
63
68
|
const requestId = safeRequestId(response.headers.get("x-request-id"));
|
|
64
69
|
if (requestId === null) {
|
|
@@ -66,6 +71,24 @@ async function parseResponse(response, operationSignal, preconditionStatus, succ
|
|
|
66
71
|
throw new DriveError("invalid_response", { status: response.status });
|
|
67
72
|
}
|
|
68
73
|
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes);
|
|
74
|
+
if (response.status === 304) {
|
|
75
|
+
const contentLength = response.headers.get("content-length");
|
|
76
|
+
const etag = response.headers.get("etag");
|
|
77
|
+
const status = response.status;
|
|
78
|
+
if (response.body !== null || contentLength !== null && contentLength !== "0" || response.headers.has("content-type") || etag === null || !/^"[\x21\x23-\x7e]{1,1022}"$/.test(etag) || !guard(void 0, status, response.headers)) {
|
|
79
|
+
cancelResponse(response);
|
|
80
|
+
throw new DriveError("invalid_response", {
|
|
81
|
+
status,
|
|
82
|
+
requestId
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return Object.freeze({
|
|
86
|
+
data: void 0,
|
|
87
|
+
status,
|
|
88
|
+
requestId,
|
|
89
|
+
validators: Object.freeze({ etag })
|
|
90
|
+
});
|
|
91
|
+
}
|
|
69
92
|
const { value } = await parseBoundedJson(response, SUCCESS_BODY_LIMIT, response.status, requestId, operationSignal);
|
|
70
93
|
const status = response.status;
|
|
71
94
|
if (!guard(value, status, response.headers)) throw new DriveError("invalid_response", {
|
|
@@ -79,6 +102,28 @@ async function parseResponse(response, operationSignal, preconditionStatus, succ
|
|
|
79
102
|
validators: readValidators(response.headers)
|
|
80
103
|
});
|
|
81
104
|
}
|
|
105
|
+
async function parseNoContentResponse(response, operationSignal, preconditionStatus, successStatuses, allowedErrorCodes) {
|
|
106
|
+
const requestId = safeRequestId(response.headers.get("x-request-id"));
|
|
107
|
+
if (requestId === null) {
|
|
108
|
+
cancelResponse(response);
|
|
109
|
+
throw new DriveError("invalid_response", { status: response.status });
|
|
110
|
+
}
|
|
111
|
+
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, false, allowedErrorCodes);
|
|
112
|
+
const contentLength = response.headers.get("content-length");
|
|
113
|
+
if (response.body !== null || contentLength !== null && contentLength !== "0" || response.headers.has("content-type")) {
|
|
114
|
+
cancelResponse(response);
|
|
115
|
+
throw new DriveError("invalid_response", {
|
|
116
|
+
status: response.status,
|
|
117
|
+
requestId
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return Object.freeze({
|
|
121
|
+
data: void 0,
|
|
122
|
+
status: response.status,
|
|
123
|
+
requestId,
|
|
124
|
+
validators: Object.freeze({})
|
|
125
|
+
});
|
|
126
|
+
}
|
|
82
127
|
function parseCollectionEtag(value) {
|
|
83
128
|
const match = COLLECTION_ETAG.exec(value);
|
|
84
129
|
if (!match) return void 0;
|
|
@@ -92,6 +137,12 @@ function parseGrantEtag(value) {
|
|
|
92
137
|
const grantRevision = Number(match[2]);
|
|
93
138
|
return Number.isSafeInteger(collectionRevision) && Number.isSafeInteger(grantRevision) ? [collectionRevision, grantRevision] : void 0;
|
|
94
139
|
}
|
|
140
|
+
function parseItemEtag(value) {
|
|
141
|
+
const match = ITEM_ETAG.exec(value);
|
|
142
|
+
if (!match) return void 0;
|
|
143
|
+
const revision = Number(match[1]);
|
|
144
|
+
return Number.isSafeInteger(revision) ? revision : void 0;
|
|
145
|
+
}
|
|
95
146
|
async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
|
|
96
147
|
let parsed;
|
|
97
148
|
try {
|
|
@@ -135,8 +186,10 @@ function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceede
|
|
|
135
186
|
invalid_pagination_cursor: [422],
|
|
136
187
|
invalid_idempotency_key: [422],
|
|
137
188
|
precondition_failed: preconditionStatus === null ? [] : [preconditionStatus],
|
|
189
|
+
range_not_satisfiable: [416],
|
|
138
190
|
idempotency_conflict: [409],
|
|
139
191
|
quota_exceeded: [409],
|
|
192
|
+
upload_recovery_required: [409],
|
|
140
193
|
service_unavailable: [503],
|
|
141
194
|
internal_error: [500]
|
|
142
195
|
}[code].includes(status);
|
|
@@ -231,7 +284,7 @@ function readValidators(headers) {
|
|
|
231
284
|
const permissionCollectionEtag = headers.get("drive-permission-collection-etag");
|
|
232
285
|
const permissionGrantEtag = headers.get("drive-permission-grant-etag");
|
|
233
286
|
return Object.freeze({
|
|
234
|
-
...etag !== null && LIST_ETAG$1.test(etag) ? { etag } : {},
|
|
287
|
+
...etag !== null && (LIST_ETAG$1.test(etag) || parseItemEtag(etag) !== void 0) ? { etag } : {},
|
|
235
288
|
...permissionCollectionEtag !== null && parseCollectionEtag(permissionCollectionEtag) !== void 0 ? { permissionCollectionEtag } : {},
|
|
236
289
|
...permissionGrantEtag !== null && parseGrantEtag(permissionGrantEtag) !== void 0 ? { permissionGrantEtag } : {}
|
|
237
290
|
});
|
|
@@ -247,6 +300,8 @@ const WORKSPACE_ID$1 = /^drive\.workspace\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-
|
|
|
247
300
|
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}$/;
|
|
248
301
|
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}$/;
|
|
249
302
|
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}$/;
|
|
303
|
+
const VERSION_ID$1 = /^drive\.version\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
304
|
+
const RETRIEVAL_ID = /^drive\.retrieval\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
250
305
|
const CURSOR$1 = /^drive\.cursor\.v1\.[A-Za-z0-9_-]+$/;
|
|
251
306
|
const AUTH_ID$1 = /^[A-Za-z0-9_-]{1,128}$/;
|
|
252
307
|
const GRANT_ETAG = /^"drive\.permission-grant\.v1\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"$/;
|
|
@@ -269,7 +324,9 @@ const EFFECTIVE_ACTIONS = Object.freeze([
|
|
|
269
324
|
"items:update"
|
|
270
325
|
]);
|
|
271
326
|
const MAX_UPLOAD_BYTE_LENGTH$1 = 33554432e4;
|
|
272
|
-
const
|
|
327
|
+
const UPLOAD_PART_BYTE_LENGTH$2 = 32 * 1024 * 1024;
|
|
328
|
+
const CONTENT_DIGEST$1 = /^sha256:[0-9a-f]{64}$/;
|
|
329
|
+
const UTF8 = new TextEncoder();
|
|
273
330
|
function isCurrentWorkspace(value) {
|
|
274
331
|
if (!isExactRecord(value, [
|
|
275
332
|
"workspaceId",
|
|
@@ -280,6 +337,61 @@ function isCurrentWorkspace(value) {
|
|
|
280
337
|
const reference = value.workspaceReference;
|
|
281
338
|
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);
|
|
282
339
|
}
|
|
340
|
+
function isManagedDownloadDescriptor(value) {
|
|
341
|
+
if (!isExactRecord(value, [
|
|
342
|
+
"mode",
|
|
343
|
+
"method",
|
|
344
|
+
"url",
|
|
345
|
+
"headers",
|
|
346
|
+
"expiresAtEpochMilliseconds",
|
|
347
|
+
"response"
|
|
348
|
+
]) || value.mode !== "presigned-single" || value.method !== "GET" && value.method !== "HEAD" || typeof value.url !== "string" || !isSafeCapabilityUrl(value.url) || !isSafeInteger$1(value.expiresAtEpochMilliseconds) || !isExactRecord(value.headers, ["if-match"]) && !isExactRecord(value.headers, ["if-match", "range"]) || typeof value.headers["if-match"] !== "string" || !isStrongEtag(value.headers["if-match"]) || value.headers.range !== void 0 && (typeof value.headers.range !== "string" || !/^bytes=(?:0|[1-9][0-9]*)-(?:0|[1-9][0-9]*)$/.test(value.headers.range)) || !isExactRecord(value.response, [
|
|
349
|
+
"status",
|
|
350
|
+
"versionId",
|
|
351
|
+
"byteLength",
|
|
352
|
+
"contentLength",
|
|
353
|
+
"contentType",
|
|
354
|
+
"contentDisposition",
|
|
355
|
+
"etag",
|
|
356
|
+
"acceptRanges",
|
|
357
|
+
"contentRange"
|
|
358
|
+
]) || value.response.status !== 200 && value.response.status !== 206 || typeof value.response.versionId !== "string" || !VERSION_ID$1.test(value.response.versionId) || !isSafeInteger$1(value.response.byteLength) || !isSafeInteger$1(value.response.contentLength) || typeof value.response.contentType !== "string" || !/^[a-z0-9](?:[a-z0-9!#$&^_.+-]{0,125}[a-z0-9])?\/[a-z0-9](?:[a-z0-9!#$&^_.+-]{0,125}[a-z0-9])?$/.test(value.response.contentType) || typeof value.response.contentDisposition !== "string" || value.response.contentDisposition.length > 2048 || !/^[\x20-\x7e]+$/.test(value.response.contentDisposition) || value.response.etag !== value.headers["if-match"] || value.response.acceptRanges !== "bytes" || value.response.contentRange !== null && typeof value.response.contentRange !== "string") return false;
|
|
359
|
+
if (!downloadDescriptorIsCoherent(value)) return false;
|
|
360
|
+
Object.freeze(value.headers);
|
|
361
|
+
Object.freeze(value.response);
|
|
362
|
+
Object.freeze(value);
|
|
363
|
+
return true;
|
|
364
|
+
}
|
|
365
|
+
function downloadDescriptorIsCoherent(value) {
|
|
366
|
+
const response = value.response;
|
|
367
|
+
if (response.contentLength > response.byteLength || value.method === "HEAD" && response.status !== 200 || !response.contentDisposition.startsWith("attachment; filename=\"")) return false;
|
|
368
|
+
if (response.status === 200) return value.headers.range === void 0 && response.contentRange === null && response.contentLength === response.byteLength;
|
|
369
|
+
if (value.method !== "GET" || value.headers.range === void 0 || response.contentRange === null) return false;
|
|
370
|
+
const range = /^bytes=(0|[1-9][0-9]*)-(0|[1-9][0-9]*)$/.exec(value.headers.range);
|
|
371
|
+
const contentRange = /^bytes (0|[1-9][0-9]*)-(0|[1-9][0-9]*)\/(0|[1-9][0-9]*)$/.exec(response.contentRange);
|
|
372
|
+
if (!range || !contentRange) return false;
|
|
373
|
+
const start = Number(range[1]);
|
|
374
|
+
const end = Number(range[2]);
|
|
375
|
+
const contentStart = Number(contentRange[1]);
|
|
376
|
+
const contentEnd = Number(contentRange[2]);
|
|
377
|
+
const byteLength = Number(contentRange[3]);
|
|
378
|
+
return [
|
|
379
|
+
start,
|
|
380
|
+
end,
|
|
381
|
+
contentStart,
|
|
382
|
+
contentEnd,
|
|
383
|
+
byteLength
|
|
384
|
+
].every(isSafeInteger$1) && start === contentStart && end === contentEnd && byteLength === response.byteLength && start <= end && end < byteLength && response.contentLength === end - start + 1;
|
|
385
|
+
}
|
|
386
|
+
function isManagedDownloadRestorePending(value) {
|
|
387
|
+
return isExactRecord(value, [
|
|
388
|
+
"mode",
|
|
389
|
+
"operationId",
|
|
390
|
+
"versionId",
|
|
391
|
+
"state",
|
|
392
|
+
"pollAfterSeconds"
|
|
393
|
+
]) && value.mode === "restore-pending" && typeof value.operationId === "string" && RETRIEVAL_ID.test(value.operationId) && typeof value.versionId === "string" && VERSION_ID$1.test(value.versionId) && (value.state === "pending" || value.state === "restoring") && isSafeInteger$1(value.pollAfterSeconds) && value.pollAfterSeconds >= 1 && value.pollAfterSeconds <= 60;
|
|
394
|
+
}
|
|
283
395
|
function isFolderPage(value, workspaceId, parentItemId) {
|
|
284
396
|
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;
|
|
285
397
|
return value.items.every((item) => item.workspaceId === workspaceId && item.parentItemId === parentItemId) && isStrictlyOrdered(value.items, (item) => item.itemId);
|
|
@@ -296,6 +408,101 @@ function isFolderItem(value) {
|
|
|
296
408
|
"revision"
|
|
297
409
|
]) && typeof value.workspaceId === "string" && WORKSPACE_ID$1.test(value.workspaceId) && typeof value.volumeId === "string" && VOLUME_ID.test(value.volumeId) && typeof value.itemId === "string" && ITEM_ID$1.test(value.itemId) && typeof value.parentItemId === "string" && ITEM_ID$1.test(value.parentItemId) && (value.kind === "file" || value.kind === "folder") && isSafeFilename$1(value.name) && (value.visibility === "workspace" || value.visibility === "restricted") && isSafeInteger$1(value.revision);
|
|
298
410
|
}
|
|
411
|
+
function isManagedLifecycleItem(value, workspaceId, itemId, expectedState) {
|
|
412
|
+
if (!isExactRecord(value, [
|
|
413
|
+
"workspaceId",
|
|
414
|
+
"volumeId",
|
|
415
|
+
"itemId",
|
|
416
|
+
"parentItemId",
|
|
417
|
+
"kind",
|
|
418
|
+
"name",
|
|
419
|
+
"state",
|
|
420
|
+
"revision",
|
|
421
|
+
"purgeAfterEpochMilliseconds"
|
|
422
|
+
]) || value.workspaceId !== workspaceId || value.itemId !== itemId || typeof value.volumeId !== "string" || !VOLUME_ID.test(value.volumeId) || typeof value.parentItemId !== "string" || !ITEM_ID$1.test(value.parentItemId) || value.kind !== "file" && value.kind !== "folder" || !isSafeFilename$1(value.name) || value.state !== expectedState || !isSafeInteger$1(value.revision) || (value.state === "active" ? value.purgeAfterEpochMilliseconds !== null : !isSafeInteger$1(value.purgeAfterEpochMilliseconds))) return false;
|
|
423
|
+
Object.freeze(value);
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
426
|
+
function isManagedItemMetadata(value, workspaceId, itemId) {
|
|
427
|
+
if (!isExactRecord(value, [
|
|
428
|
+
"workspaceId",
|
|
429
|
+
"itemId",
|
|
430
|
+
"parentId",
|
|
431
|
+
"type",
|
|
432
|
+
"name",
|
|
433
|
+
"lifecycleState",
|
|
434
|
+
"revision",
|
|
435
|
+
"currentVersion"
|
|
436
|
+
]) || value.workspaceId !== workspaceId || value.itemId !== itemId || !(value.parentId === null || typeof value.parentId === "string" && ITEM_ID$1.test(value.parentId)) || value.type !== "file" && value.type !== "folder" || !isSafeFilename$1(value.name) || value.lifecycleState !== "active" || !isSafeInteger$1(value.revision) || (value.type === "folder" ? value.currentVersion !== null : !isCurrentVersionMetadata(value.currentVersion))) return false;
|
|
437
|
+
if (value.currentVersion !== null) Object.freeze(value.currentVersion);
|
|
438
|
+
Object.freeze(value);
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
function isWorkspaceItemSearchPage(value, workspaceId, query, limit) {
|
|
442
|
+
if (!isExactRecord(value, ["items", "nextCursor"]) || !Array.isArray(value.items) || value.items.length > limit || !value.items.every((item) => isWorkspaceItemSearchItem(item, workspaceId, query)) || !(value.nextCursor === null || typeof value.nextCursor === "string" && value.nextCursor.length <= 699 && CURSOR$1.test(value.nextCursor)) || value.items.length === 0 && value.nextCursor !== null || new Set(value.items.map((item) => item.itemId)).size !== value.items.length || !isWorkspaceItemSearchOrder(value.items)) return false;
|
|
443
|
+
for (const item of value.items) {
|
|
444
|
+
if (item.currentVersion !== null) Object.freeze(item.currentVersion);
|
|
445
|
+
Object.freeze(item);
|
|
446
|
+
}
|
|
447
|
+
Object.freeze(value.items);
|
|
448
|
+
Object.freeze(value);
|
|
449
|
+
return true;
|
|
450
|
+
}
|
|
451
|
+
function itemEtagMatchesRevision(headers, revision) {
|
|
452
|
+
const etag = headers.get("etag");
|
|
453
|
+
return etag !== null && parseItemEtag(etag) === revision;
|
|
454
|
+
}
|
|
455
|
+
function isCurrentVersionMetadata(value) {
|
|
456
|
+
return isExactRecord(value, [
|
|
457
|
+
"versionId",
|
|
458
|
+
"state",
|
|
459
|
+
"byteLength",
|
|
460
|
+
"mediaType",
|
|
461
|
+
"protectionClassification"
|
|
462
|
+
]) && typeof value.versionId === "string" && VERSION_ID$1.test(value.versionId) && value.state === "current" && isSafeInteger$1(value.byteLength) && isMediaType$1(value.mediaType) && (value.protectionClassification === "ordinary" || value.protectionClassification === "opaque-encrypted");
|
|
463
|
+
}
|
|
464
|
+
function isWorkspaceItemSearchItem(value, workspaceId, query) {
|
|
465
|
+
return isExactRecord(value, [
|
|
466
|
+
"workspaceId",
|
|
467
|
+
"volumeId",
|
|
468
|
+
"provider",
|
|
469
|
+
"itemId",
|
|
470
|
+
"parentId",
|
|
471
|
+
"type",
|
|
472
|
+
"name",
|
|
473
|
+
"lifecycleState",
|
|
474
|
+
"revision",
|
|
475
|
+
"currentVersion"
|
|
476
|
+
]) && value.workspaceId === workspaceId && typeof value.volumeId === "string" && VOLUME_ID.test(value.volumeId) && value.provider === "managed" && typeof value.itemId === "string" && ITEM_ID$1.test(value.itemId) && (value.parentId === null || typeof value.parentId === "string" && ITEM_ID$1.test(value.parentId)) && (value.type === "file" || value.type === "folder") && isSafeFilename$1(value.name) && value.name.startsWith(query) && value.lifecycleState === "active" && isSafeInteger$1(value.revision) && (value.type === "folder" ? value.currentVersion === null : isCurrentVersionMetadata(value.currentVersion));
|
|
477
|
+
}
|
|
478
|
+
function isWorkspaceItemSearchOrder(items) {
|
|
479
|
+
for (let index = 1; index < items.length; index += 1) {
|
|
480
|
+
const previous = items[index - 1];
|
|
481
|
+
const current = items[index];
|
|
482
|
+
const nameOrder = compareBinary(previous.name, current.name);
|
|
483
|
+
if (nameOrder > 0 || nameOrder === 0 && previous.itemId >= current.itemId) return false;
|
|
484
|
+
}
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
function compareBinary(left, right) {
|
|
488
|
+
const leftBytes = UTF8.encode(left);
|
|
489
|
+
const rightBytes = UTF8.encode(right);
|
|
490
|
+
const length = Math.min(leftBytes.length, rightBytes.length);
|
|
491
|
+
for (let index = 0; index < length; index += 1) if (leftBytes[index] !== rightBytes[index]) return leftBytes[index] - rightBytes[index];
|
|
492
|
+
return leftBytes.length - rightBytes.length;
|
|
493
|
+
}
|
|
494
|
+
function isManagedItemVersionPage(value, limit) {
|
|
495
|
+
if (!isExactRecord(value, ["items", "nextCursor"]) || !Array.isArray(value.items) || value.items.length > limit || !value.items.every(isManagedItemVersion) || !(value.nextCursor === null || typeof value.nextCursor === "string" && value.nextCursor.length <= 699 && CURSOR$1.test(value.nextCursor)) || value.nextCursor !== null && value.items.length === 0 || !isStrictlyOrdered(value.items, (version) => version.versionId)) return false;
|
|
496
|
+
for (const version of value.items) Object.freeze(version);
|
|
497
|
+
Object.freeze(value.items);
|
|
498
|
+
Object.freeze(value);
|
|
499
|
+
return true;
|
|
500
|
+
}
|
|
501
|
+
function isManagedItemVersionRestoreResult(value, versionId) {
|
|
502
|
+
if (!isExactRecord(value, ["itemRevision", "currentVersionId"]) || !isSafeInteger$1(value.itemRevision) || value.currentVersionId !== versionId) return false;
|
|
503
|
+
Object.freeze(value);
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
299
506
|
function isPermissionPage(value, headers, targetItemId) {
|
|
300
507
|
if (!(isExactRecord(value, [
|
|
301
508
|
"items",
|
|
@@ -350,18 +557,127 @@ function isEffectivePermissionResponse(value, targetItemId) {
|
|
|
350
557
|
}
|
|
351
558
|
return true;
|
|
352
559
|
}
|
|
353
|
-
function
|
|
354
|
-
|
|
355
|
-
"
|
|
560
|
+
function isUploadSession(value, expectedByteLength) {
|
|
561
|
+
if (!isExactRecord(value, [
|
|
562
|
+
"itemId",
|
|
563
|
+
"versionId",
|
|
356
564
|
"uploadId",
|
|
357
|
-
"
|
|
358
|
-
"
|
|
359
|
-
"
|
|
360
|
-
"
|
|
361
|
-
"
|
|
565
|
+
"mode",
|
|
566
|
+
"partByteLength",
|
|
567
|
+
"partCount",
|
|
568
|
+
"revision",
|
|
569
|
+
"expiresAtEpochMilliseconds"
|
|
570
|
+
]) || 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" || 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;
|
|
571
|
+
Object.freeze(value);
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
function isUploadStatus(value, afterPartNumber, limit) {
|
|
575
|
+
if (!isExactRecord(value, [
|
|
576
|
+
"itemId",
|
|
577
|
+
"versionId",
|
|
578
|
+
"uploadId",
|
|
579
|
+
"mode",
|
|
580
|
+
"lifecycle",
|
|
581
|
+
"revision",
|
|
582
|
+
"partPolicy",
|
|
583
|
+
"confirmedParts",
|
|
584
|
+
"nextAfterPartNumber",
|
|
362
585
|
"expiresAtEpochMilliseconds",
|
|
363
|
-
"
|
|
364
|
-
])
|
|
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" || ![
|
|
588
|
+
"initiating",
|
|
589
|
+
"recovery-required",
|
|
590
|
+
"uploading",
|
|
591
|
+
"completing",
|
|
592
|
+
"provider-completed",
|
|
593
|
+
"ready",
|
|
594
|
+
"aborting",
|
|
595
|
+
"aborted"
|
|
596
|
+
].includes(String(value.lifecycle)) || !isSafeInteger$1(value.revision) || !isExactRecord(value.partPolicy, [
|
|
597
|
+
"partByteLength",
|
|
598
|
+
"partCount",
|
|
599
|
+
"maxParts"
|
|
600
|
+
]) || 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
|
+
let previousPartNumber = afterPartNumber;
|
|
602
|
+
for (const part of value.confirmedParts) {
|
|
603
|
+
if (!isExactRecord(part, ["partNumber", "checksumSha256"]) || !isSafeInteger$1(part.partNumber) || part.partNumber <= previousPartNumber || part.partNumber > value.partPolicy.partCount || !isPartChecksum$1(part.checksumSha256)) return false;
|
|
604
|
+
previousPartNumber = part.partNumber;
|
|
605
|
+
}
|
|
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;
|
|
607
|
+
Object.freeze(value.partPolicy);
|
|
608
|
+
for (const part of value.confirmedParts) Object.freeze(part);
|
|
609
|
+
Object.freeze(value.confirmedParts);
|
|
610
|
+
Object.freeze(value);
|
|
611
|
+
return true;
|
|
612
|
+
}
|
|
613
|
+
function isUploadPartDescriptor(value, expectedPartNumber, checksumSha256, allowInsecureHttp) {
|
|
614
|
+
if (!isExactRecord(value, [
|
|
615
|
+
"url",
|
|
616
|
+
"method",
|
|
617
|
+
"headers",
|
|
618
|
+
"partNumber",
|
|
619
|
+
"expectedByteLength",
|
|
620
|
+
"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;
|
|
622
|
+
Object.freeze(value.headers);
|
|
623
|
+
Object.freeze(value);
|
|
624
|
+
return true;
|
|
625
|
+
}
|
|
626
|
+
function isUploadPartResult(value, expectedPartNumber, expectedUploadRevision) {
|
|
627
|
+
if (!isExactRecord(value, ["partNumber", "revision"]) || value.partNumber !== expectedPartNumber || value.revision !== expectedUploadRevision + 1 || !isSafeInteger$1(value.revision)) return false;
|
|
628
|
+
Object.freeze(value);
|
|
629
|
+
return true;
|
|
630
|
+
}
|
|
631
|
+
function isReadyUpload(value, expected) {
|
|
632
|
+
if (!isExactRecord(value, [
|
|
633
|
+
"itemId",
|
|
634
|
+
"versionId",
|
|
635
|
+
"uploadId",
|
|
636
|
+
"byteLength",
|
|
637
|
+
"callerDeclaredContentDigest",
|
|
638
|
+
"displayFilename",
|
|
639
|
+
"mediaType",
|
|
640
|
+
"state"
|
|
641
|
+
]) || typeof value.itemId !== "string" || !ITEM_ID$1.test(value.itemId) || typeof value.versionId !== "string" || !VERSION_ID$1.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;
|
|
642
|
+
Object.freeze(value);
|
|
643
|
+
return true;
|
|
644
|
+
}
|
|
645
|
+
function isPartChecksum$1(value) {
|
|
646
|
+
return typeof value === "string" && /^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/.test(value);
|
|
647
|
+
}
|
|
648
|
+
function isManagedItemVersion(value) {
|
|
649
|
+
const valid = isExactRecord(value, managedItemVersionKeys) && managedItemVersionFieldsAreValid(value);
|
|
650
|
+
if (valid) Object.freeze(value);
|
|
651
|
+
return valid;
|
|
652
|
+
}
|
|
653
|
+
function isManagedItemVersionResource(value, workspaceId, itemId, versionId) {
|
|
654
|
+
const valid = isExactRecord(value, [
|
|
655
|
+
...managedItemVersionKeys,
|
|
656
|
+
"workspaceId",
|
|
657
|
+
"itemId"
|
|
658
|
+
]) && value.workspaceId === workspaceId && value.itemId === itemId && value.versionId === versionId && managedItemVersionFieldsAreValid(value);
|
|
659
|
+
if (valid) Object.freeze(value);
|
|
660
|
+
return valid;
|
|
661
|
+
}
|
|
662
|
+
const managedItemVersionKeys = Object.freeze([
|
|
663
|
+
"versionId",
|
|
664
|
+
"state",
|
|
665
|
+
"revision",
|
|
666
|
+
"byteLength",
|
|
667
|
+
"contentDigest",
|
|
668
|
+
"mediaType",
|
|
669
|
+
"displayFilename",
|
|
670
|
+
"protectionClassification",
|
|
671
|
+
"archiveState"
|
|
672
|
+
]);
|
|
673
|
+
function managedItemVersionFieldsAreValid(value) {
|
|
674
|
+
return typeof value.versionId === "string" && VERSION_ID$1.test(value.versionId) && (value.state === "current" || value.state === "superseded") && isSafeInteger$1(value.revision) && isSafeInteger$1(value.byteLength) && typeof value.contentDigest === "string" && CONTENT_DIGEST$1.test(value.contentDigest) && isMediaType$1(value.mediaType) && isSafeFilename$1(value.displayFilename) && (value.protectionClassification === "ordinary" || value.protectionClassification === "opaque-encrypted") && [
|
|
675
|
+
"available",
|
|
676
|
+
"cold",
|
|
677
|
+
"restoring",
|
|
678
|
+
"unavailable",
|
|
679
|
+
"corrupt"
|
|
680
|
+
].includes(String(value.archiveState));
|
|
365
681
|
}
|
|
366
682
|
function mutationValidatorsAreCoherent(headers) {
|
|
367
683
|
const collection = headers.get("drive-permission-collection-etag");
|
|
@@ -418,6 +734,19 @@ function isSafeFilename$1(value) {
|
|
|
418
734
|
}
|
|
419
735
|
return true;
|
|
420
736
|
}
|
|
737
|
+
function isMediaType$1(value) {
|
|
738
|
+
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);
|
|
739
|
+
}
|
|
740
|
+
function isSignedTransferUrl(value, allowInsecureHttp) {
|
|
741
|
+
if (typeof value !== "string" || value.length < 1 || value.length > 8192 || value !== value.trim()) return false;
|
|
742
|
+
try {
|
|
743
|
+
const url = new URL(value);
|
|
744
|
+
const loopbackHost = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]";
|
|
745
|
+
return (url.protocol === "https:" || url.protocol === "http:" && allowInsecureHttp && loopbackHost) && url.username === "" && url.password === "" && url.hash === "" && url.host !== "";
|
|
746
|
+
} catch {
|
|
747
|
+
return false;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
421
750
|
function filenameIsReserved$1(value) {
|
|
422
751
|
const base = value.split(".", 1)[0].toUpperCase();
|
|
423
752
|
return value === "." || value === ".." || [
|
|
@@ -436,6 +765,22 @@ function isStrictlyOrdered(values, key) {
|
|
|
436
765
|
function isSafeInteger$1(value) {
|
|
437
766
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
438
767
|
}
|
|
768
|
+
function isStrongEtag(value) {
|
|
769
|
+
return /^"[\x21\x23-\x7e]{1,1022}"$/.test(value);
|
|
770
|
+
}
|
|
771
|
+
function isSafeCapabilityUrl(value) {
|
|
772
|
+
try {
|
|
773
|
+
const url = new URL(value);
|
|
774
|
+
const localHttp = url.protocol === "http:" && [
|
|
775
|
+
"localhost",
|
|
776
|
+
"127.0.0.1",
|
|
777
|
+
"[::1]"
|
|
778
|
+
].includes(url.hostname);
|
|
779
|
+
return (url.protocol === "https:" || localHttp) && !url.username && !url.password && !url.hash;
|
|
780
|
+
} catch {
|
|
781
|
+
return false;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
439
784
|
function isExactRecord(value, keys) {
|
|
440
785
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
441
786
|
return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
@@ -446,6 +791,7 @@ const ITEM_ID = /^drive\.item\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-
|
|
|
446
791
|
const WORKSPACE_ID = /^drive\.workspace\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
447
792
|
const GRANT_ID = /^drive\.grant\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
448
793
|
const UPLOAD_ID = /^drive\.upload\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
794
|
+
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}$/;
|
|
449
795
|
const CURSOR = /^drive\.cursor\.v1\.[A-Za-z0-9_-]+$/;
|
|
450
796
|
const AUTH_ID = /^[A-Za-z0-9_-]{1,128}$/;
|
|
451
797
|
const PERMISSION_ACTIONS = Object.freeze([
|
|
@@ -457,7 +803,10 @@ const PERMISSION_ACTIONS = Object.freeze([
|
|
|
457
803
|
"items:update"
|
|
458
804
|
]);
|
|
459
805
|
const IDEMPOTENCY_KEY = /^[A-Za-z0-9_-]{16,128}$/;
|
|
806
|
+
const CONTENT_DIGEST = /^sha256:[0-9a-f]{64}$/;
|
|
807
|
+
const PART_CHECKSUM = /^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/;
|
|
460
808
|
const MAX_UPLOAD_BYTE_LENGTH = 33554432e4;
|
|
809
|
+
const UPLOAD_PART_BYTE_LENGTH$1 = 32 * 1024 * 1024;
|
|
461
810
|
function validateCurrentWorkspaceInput(value) {
|
|
462
811
|
const signal = validateSignal(captureRecord(value === void 0 ? {} : value, [], ["signal"]).signal);
|
|
463
812
|
return signal === void 0 ? {} : { signal };
|
|
@@ -474,6 +823,71 @@ function validateResourceInput(value) {
|
|
|
474
823
|
...signal === void 0 ? {} : { signal }
|
|
475
824
|
};
|
|
476
825
|
}
|
|
826
|
+
function validateItemVersionInput(value) {
|
|
827
|
+
const input = captureRecord(value, [
|
|
828
|
+
"workspaceId",
|
|
829
|
+
"itemId",
|
|
830
|
+
"versionId"
|
|
831
|
+
], ["signal"]);
|
|
832
|
+
const resource = validateResourceInput({
|
|
833
|
+
workspaceId: input.workspaceId,
|
|
834
|
+
itemId: input.itemId,
|
|
835
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
836
|
+
});
|
|
837
|
+
if (typeof input.versionId !== "string" || !VERSION_ID.test(input.versionId)) throw new DriveError("invalid_input");
|
|
838
|
+
return {
|
|
839
|
+
...resource,
|
|
840
|
+
versionId: input.versionId
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
function validateCreateDownloadInput(value) {
|
|
844
|
+
const input = captureRecord(value, [
|
|
845
|
+
"workspaceId",
|
|
846
|
+
"itemId",
|
|
847
|
+
"idempotencyKey"
|
|
848
|
+
], [
|
|
849
|
+
"versionId",
|
|
850
|
+
"method",
|
|
851
|
+
"range",
|
|
852
|
+
"ifMatch",
|
|
853
|
+
"ifNoneMatch",
|
|
854
|
+
"ifRange",
|
|
855
|
+
"signal"
|
|
856
|
+
]);
|
|
857
|
+
const resource = validateResourceInput({
|
|
858
|
+
workspaceId: input.workspaceId,
|
|
859
|
+
itemId: input.itemId,
|
|
860
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
861
|
+
});
|
|
862
|
+
const method = input.method ?? "GET";
|
|
863
|
+
if (!isIdempotencyKey(input.idempotencyKey) || input.versionId !== void 0 && (typeof input.versionId !== "string" || !VERSION_ID.test(input.versionId)) || method !== "GET" && method !== "HEAD" || input.range !== void 0 && (typeof input.range !== "string" || input.range.length > 128 || !/^bytes=(?:[0-9]+-[0-9]*|-[0-9]+)$/.test(input.range)) || !isOptionalHeaderValue(input.ifMatch) || !isOptionalHeaderValue(input.ifNoneMatch) || !isOptionalHeaderValue(input.ifRange)) throw new DriveError("invalid_input");
|
|
864
|
+
return {
|
|
865
|
+
...resource,
|
|
866
|
+
idempotencyKey: input.idempotencyKey,
|
|
867
|
+
method,
|
|
868
|
+
...input.versionId === void 0 ? {} : { versionId: input.versionId },
|
|
869
|
+
...input.range === void 0 ? {} : { range: input.range },
|
|
870
|
+
...input.ifMatch === void 0 ? {} : { ifMatch: input.ifMatch },
|
|
871
|
+
...input.ifNoneMatch === void 0 ? {} : { ifNoneMatch: input.ifNoneMatch },
|
|
872
|
+
...input.ifRange === void 0 ? {} : { ifRange: input.ifRange }
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
function validateSearchWorkspaceItemsInput(value) {
|
|
876
|
+
const input = captureRecord(value, ["workspaceId", "query"], [
|
|
877
|
+
"limit",
|
|
878
|
+
"cursor",
|
|
879
|
+
"signal"
|
|
880
|
+
]);
|
|
881
|
+
const signal = validateSignal(input.signal);
|
|
882
|
+
if (typeof input.workspaceId !== "string" || !WORKSPACE_ID.test(input.workspaceId) || !isSearchQuery(input.query) || input.limit !== void 0 && (!isSafeInteger(input.limit) || input.limit < 1 || input.limit > 50) || input.cursor !== void 0 && (typeof input.cursor !== "string" || input.cursor.length > 699 || !CURSOR.test(input.cursor))) throw new DriveError("invalid_input");
|
|
883
|
+
return {
|
|
884
|
+
workspaceId: input.workspaceId,
|
|
885
|
+
query: input.query,
|
|
886
|
+
...input.limit === void 0 ? {} : { limit: input.limit },
|
|
887
|
+
...input.cursor === void 0 ? {} : { cursor: input.cursor },
|
|
888
|
+
...signal === void 0 ? {} : { signal }
|
|
889
|
+
};
|
|
890
|
+
}
|
|
477
891
|
function validatePageInput(value) {
|
|
478
892
|
const input = captureRecord(value, ["workspaceId", "itemId"], [
|
|
479
893
|
"signal",
|
|
@@ -513,6 +927,69 @@ function validateCreateFolderInput(value) {
|
|
|
513
927
|
idempotencyKey: input.idempotencyKey
|
|
514
928
|
};
|
|
515
929
|
}
|
|
930
|
+
function validateUpdateItemInput(value) {
|
|
931
|
+
const input = captureRecord(value, [
|
|
932
|
+
"workspaceId",
|
|
933
|
+
"itemId",
|
|
934
|
+
"name",
|
|
935
|
+
"parentItemId",
|
|
936
|
+
"idempotencyKey",
|
|
937
|
+
"ifMatch"
|
|
938
|
+
], ["signal"]);
|
|
939
|
+
const mutation = validateLifecycleMutationInput({
|
|
940
|
+
workspaceId: input.workspaceId,
|
|
941
|
+
itemId: input.itemId,
|
|
942
|
+
idempotencyKey: input.idempotencyKey,
|
|
943
|
+
ifMatch: input.ifMatch,
|
|
944
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
945
|
+
});
|
|
946
|
+
if (!isSafeFilename(input.name) || typeof input.parentItemId !== "string" || !ITEM_ID.test(input.parentItemId)) throw new DriveError("invalid_input");
|
|
947
|
+
return {
|
|
948
|
+
...mutation,
|
|
949
|
+
name: input.name,
|
|
950
|
+
parentItemId: input.parentItemId
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
function validateLifecycleMutationInput(value) {
|
|
954
|
+
const input = captureRecord(value, [
|
|
955
|
+
"workspaceId",
|
|
956
|
+
"itemId",
|
|
957
|
+
"idempotencyKey",
|
|
958
|
+
"ifMatch"
|
|
959
|
+
], ["signal"]);
|
|
960
|
+
const resource = validateResourceInput({
|
|
961
|
+
workspaceId: input.workspaceId,
|
|
962
|
+
itemId: input.itemId,
|
|
963
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
964
|
+
});
|
|
965
|
+
if (!isIdempotencyKey(input.idempotencyKey) || typeof input.ifMatch !== "string" || parseItemEtag(input.ifMatch) === void 0) throw new DriveError("invalid_input");
|
|
966
|
+
return {
|
|
967
|
+
...resource,
|
|
968
|
+
idempotencyKey: input.idempotencyKey,
|
|
969
|
+
ifMatch: input.ifMatch
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
function validateRestoreItemVersionInput(value) {
|
|
973
|
+
const input = captureRecord(value, [
|
|
974
|
+
"workspaceId",
|
|
975
|
+
"itemId",
|
|
976
|
+
"versionId",
|
|
977
|
+
"idempotencyKey",
|
|
978
|
+
"ifMatch"
|
|
979
|
+
], ["signal"]);
|
|
980
|
+
const mutation = validateLifecycleMutationInput({
|
|
981
|
+
workspaceId: input.workspaceId,
|
|
982
|
+
itemId: input.itemId,
|
|
983
|
+
idempotencyKey: input.idempotencyKey,
|
|
984
|
+
ifMatch: input.ifMatch,
|
|
985
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
986
|
+
});
|
|
987
|
+
if (typeof input.versionId !== "string" || !VERSION_ID.test(input.versionId)) throw new DriveError("invalid_input");
|
|
988
|
+
return {
|
|
989
|
+
...mutation,
|
|
990
|
+
versionId: input.versionId
|
|
991
|
+
};
|
|
992
|
+
}
|
|
516
993
|
function validateCreatePermissionInput(value) {
|
|
517
994
|
const input = captureRecord(value, [
|
|
518
995
|
"workspaceId",
|
|
@@ -596,26 +1073,133 @@ function validateCreateUploadInput(value) {
|
|
|
596
1073
|
"workspaceId",
|
|
597
1074
|
"parentItemId",
|
|
598
1075
|
"expectedByteLength",
|
|
1076
|
+
"displayFilename",
|
|
1077
|
+
"mediaType",
|
|
1078
|
+
"callerDeclaredContentDigest",
|
|
1079
|
+
"protectionClassification",
|
|
599
1080
|
"idempotencyKey"
|
|
600
1081
|
], ["signal"]);
|
|
601
1082
|
const signal = validateSignal(input.signal);
|
|
602
|
-
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");
|
|
1083
|
+
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");
|
|
603
1084
|
return {
|
|
604
1085
|
workspaceId: input.workspaceId,
|
|
605
1086
|
parentItemId: input.parentItemId,
|
|
606
1087
|
expectedByteLength: input.expectedByteLength,
|
|
1088
|
+
displayFilename: input.displayFilename,
|
|
1089
|
+
mediaType: input.mediaType,
|
|
1090
|
+
callerDeclaredContentDigest: input.callerDeclaredContentDigest,
|
|
1091
|
+
protectionClassification: input.protectionClassification,
|
|
607
1092
|
idempotencyKey: input.idempotencyKey,
|
|
608
1093
|
...signal === void 0 ? {} : { signal }
|
|
609
1094
|
};
|
|
610
1095
|
}
|
|
1096
|
+
function validateGetUploadStatusInput(value) {
|
|
1097
|
+
const input = captureRecord(value, ["workspaceId", "uploadId"], [
|
|
1098
|
+
"afterPartNumber",
|
|
1099
|
+
"limit",
|
|
1100
|
+
"signal"
|
|
1101
|
+
]);
|
|
1102
|
+
const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
|
|
1103
|
+
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");
|
|
1104
|
+
return {
|
|
1105
|
+
...upload,
|
|
1106
|
+
...input.afterPartNumber === void 0 ? {} : { afterPartNumber: input.afterPartNumber },
|
|
1107
|
+
...input.limit === void 0 ? {} : { limit: input.limit }
|
|
1108
|
+
};
|
|
1109
|
+
}
|
|
1110
|
+
function validateCreateUploadPartDescriptorInput(value) {
|
|
1111
|
+
const input = captureRecord(value, [
|
|
1112
|
+
"workspaceId",
|
|
1113
|
+
"uploadId",
|
|
1114
|
+
"partNumber",
|
|
1115
|
+
"checksumSha256"
|
|
1116
|
+
], ["signal"]);
|
|
1117
|
+
const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
|
|
1118
|
+
if (!isPartNumber(input.partNumber) || !isPartChecksum(input.checksumSha256)) throw new DriveError("invalid_input");
|
|
1119
|
+
return {
|
|
1120
|
+
...upload,
|
|
1121
|
+
partNumber: input.partNumber,
|
|
1122
|
+
checksumSha256: input.checksumSha256
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
function validateRecordUploadPartInput(value) {
|
|
1126
|
+
const input = captureRecord(value, [
|
|
1127
|
+
"workspaceId",
|
|
1128
|
+
"uploadId",
|
|
1129
|
+
"partNumber",
|
|
1130
|
+
"expectedUploadRevision",
|
|
1131
|
+
"byteLength",
|
|
1132
|
+
"etag",
|
|
1133
|
+
"checksumSha256"
|
|
1134
|
+
], ["signal"]);
|
|
1135
|
+
const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
|
|
1136
|
+
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");
|
|
1137
|
+
return {
|
|
1138
|
+
...upload,
|
|
1139
|
+
partNumber: input.partNumber,
|
|
1140
|
+
expectedUploadRevision: input.expectedUploadRevision,
|
|
1141
|
+
byteLength: input.byteLength,
|
|
1142
|
+
etag: input.etag,
|
|
1143
|
+
checksumSha256: input.checksumSha256
|
|
1144
|
+
};
|
|
1145
|
+
}
|
|
1146
|
+
function validateCompleteUploadInput(value) {
|
|
1147
|
+
const input = captureRecord(value, [
|
|
1148
|
+
"workspaceId",
|
|
1149
|
+
"uploadId",
|
|
1150
|
+
"idempotencyKey"
|
|
1151
|
+
], ["signal"]);
|
|
1152
|
+
const upload = validateUploadPath(input.workspaceId, input.uploadId, input.signal);
|
|
1153
|
+
if (!isIdempotencyKey(input.idempotencyKey)) throw new DriveError("invalid_input");
|
|
1154
|
+
return {
|
|
1155
|
+
...upload,
|
|
1156
|
+
idempotencyKey: input.idempotencyKey
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
611
1159
|
function validateAbortUploadInput(value) {
|
|
612
1160
|
const input = captureRecord(value, ["workspaceId", "uploadId"], ["signal"]);
|
|
1161
|
+
return validateUploadPath(input.workspaceId, input.uploadId, input.signal);
|
|
1162
|
+
}
|
|
1163
|
+
function validateUploadFileInput(value) {
|
|
1164
|
+
const input = captureRecord(value, [
|
|
1165
|
+
"workspaceId",
|
|
1166
|
+
"parentItemId",
|
|
1167
|
+
"source",
|
|
1168
|
+
"displayFilename",
|
|
1169
|
+
"idempotencyKey",
|
|
1170
|
+
"completionIdempotencyKey"
|
|
1171
|
+
], [
|
|
1172
|
+
"mediaType",
|
|
1173
|
+
"protectionClassification",
|
|
1174
|
+
"signal",
|
|
1175
|
+
"onProgress"
|
|
1176
|
+
]);
|
|
613
1177
|
const signal = validateSignal(input.signal);
|
|
614
|
-
|
|
1178
|
+
const mediaType = input.mediaType ?? "application/octet-stream";
|
|
1179
|
+
const protectionClassification = input.protectionClassification ?? "ordinary";
|
|
1180
|
+
let source;
|
|
1181
|
+
let byteLength;
|
|
1182
|
+
try {
|
|
1183
|
+
if (!(input.source instanceof Blob)) throw new DriveError("invalid_input");
|
|
1184
|
+
source = input.source;
|
|
1185
|
+
byteLength = source.size;
|
|
1186
|
+
} catch (error) {
|
|
1187
|
+
if (error instanceof DriveError) throw error;
|
|
1188
|
+
throw new DriveError("invalid_input");
|
|
1189
|
+
}
|
|
1190
|
+
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");
|
|
615
1191
|
return {
|
|
616
1192
|
workspaceId: input.workspaceId,
|
|
617
|
-
|
|
618
|
-
|
|
1193
|
+
parentItemId: input.parentItemId,
|
|
1194
|
+
source,
|
|
1195
|
+
byteLength,
|
|
1196
|
+
displayFilename: input.displayFilename,
|
|
1197
|
+
mediaType,
|
|
1198
|
+
protectionClassification,
|
|
1199
|
+
idempotencyKey: input.idempotencyKey,
|
|
1200
|
+
completionIdempotencyKey: input.completionIdempotencyKey,
|
|
1201
|
+
...signal === void 0 ? {} : { signal },
|
|
1202
|
+
...input.onProgress === void 0 ? {} : { onProgress: input.onProgress }
|
|
619
1203
|
};
|
|
620
1204
|
}
|
|
621
1205
|
function resourcePath(input) {
|
|
@@ -702,12 +1286,51 @@ function captureArray(value) {
|
|
|
702
1286
|
function isIdempotencyKey(value) {
|
|
703
1287
|
return typeof value === "string" && IDEMPOTENCY_KEY.test(value);
|
|
704
1288
|
}
|
|
705
|
-
function
|
|
706
|
-
|
|
1289
|
+
function validateUploadPath(workspaceId, uploadId, signalValue) {
|
|
1290
|
+
const signal = validateSignal(signalValue);
|
|
1291
|
+
if (typeof workspaceId !== "string" || !WORKSPACE_ID.test(workspaceId) || typeof uploadId !== "string" || !UPLOAD_ID.test(uploadId)) throw new DriveError("invalid_input");
|
|
1292
|
+
return {
|
|
1293
|
+
workspaceId,
|
|
1294
|
+
uploadId,
|
|
1295
|
+
...signal === void 0 ? {} : { signal }
|
|
1296
|
+
};
|
|
707
1297
|
}
|
|
708
|
-
function
|
|
709
|
-
|
|
710
|
-
|
|
1298
|
+
function isPartNumber(value) {
|
|
1299
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 1 && value <= 1e4;
|
|
1300
|
+
}
|
|
1301
|
+
function isPartChecksum(value) {
|
|
1302
|
+
return typeof value === "string" && PART_CHECKSUM.test(value);
|
|
1303
|
+
}
|
|
1304
|
+
function isEtag$1(value) {
|
|
1305
|
+
return typeof value === "string" && value.length >= 1 && value.length <= 1024 && /^[\x20-\x7e]+$/.test(value);
|
|
1306
|
+
}
|
|
1307
|
+
function isMediaType(value) {
|
|
1308
|
+
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);
|
|
1309
|
+
}
|
|
1310
|
+
function isSearchQuery(value) {
|
|
1311
|
+
if (typeof value !== "string" || value.length === 0) return false;
|
|
1312
|
+
try {
|
|
1313
|
+
if (value.normalize("NFC") !== value) return false;
|
|
1314
|
+
let codePoints = 0;
|
|
1315
|
+
let bytes = 0;
|
|
1316
|
+
for (const character of value) {
|
|
1317
|
+
const point = character.codePointAt(0);
|
|
1318
|
+
if (point === void 0 || point <= 31 || point >= 127 && point <= 159 || point === 8232 || point === 8233 || point >= 55296 && point <= 57343) return false;
|
|
1319
|
+
codePoints += 1;
|
|
1320
|
+
bytes += point <= 127 ? 1 : point <= 2047 ? 2 : point <= 65535 ? 3 : 4;
|
|
1321
|
+
if (codePoints > 64 || bytes > 255) return false;
|
|
1322
|
+
}
|
|
1323
|
+
return true;
|
|
1324
|
+
} catch {
|
|
1325
|
+
return false;
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
function isExpiry(value) {
|
|
1329
|
+
return value === null || isSafeInteger(value);
|
|
1330
|
+
}
|
|
1331
|
+
function isSafeFilename(value) {
|
|
1332
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 510 || value.normalize("NFC") !== value || value.endsWith(".") || value.endsWith(" ") || filenameIsReserved(value)) return false;
|
|
1333
|
+
let codePoints = 0;
|
|
711
1334
|
let bytes = 0;
|
|
712
1335
|
for (const character of value) {
|
|
713
1336
|
const point = character.codePointAt(0);
|
|
@@ -733,6 +1356,12 @@ function filenameIsReserved(value) {
|
|
|
733
1356
|
function isSafeInteger(value) {
|
|
734
1357
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
735
1358
|
}
|
|
1359
|
+
function isOptionalHeaderValue(value) {
|
|
1360
|
+
return value === void 0 || typeof value === "string" && value.length <= 8192 && !value.split("").some((character) => {
|
|
1361
|
+
const code = character.charCodeAt(0);
|
|
1362
|
+
return code <= 31 || code === 127;
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
736
1365
|
//#endregion
|
|
737
1366
|
//#region ../../node_modules/.pnpm/openapi-fetch@0.17.0/node_modules/openapi-fetch/dist/index.mjs
|
|
738
1367
|
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
@@ -1188,7 +1817,7 @@ async function execute(runtime, signal, preconditionStatus, send, successStatuse
|
|
|
1188
1817
|
signal: operationSignal
|
|
1189
1818
|
});
|
|
1190
1819
|
if (!capturedResponse) throw new DriveError("network_error");
|
|
1191
|
-
return await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes);
|
|
1820
|
+
return guard === null ? await parseNoContentResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, allowedErrorCodes) : await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes);
|
|
1192
1821
|
} catch (error) {
|
|
1193
1822
|
if (operation.didTimeout()) throw new DriveError("timeout");
|
|
1194
1823
|
if (error instanceof DriveError) throw error;
|
|
@@ -1276,27 +1905,310 @@ const CURRENT_WORKSPACE_ERROR_CODES = Object.freeze([
|
|
|
1276
1905
|
"invalid_request",
|
|
1277
1906
|
"service_unavailable"
|
|
1278
1907
|
]);
|
|
1279
|
-
|
|
1280
|
-
|
|
1908
|
+
const GET_ITEM_ERROR_CODES = Object.freeze([
|
|
1909
|
+
"authentication_required",
|
|
1910
|
+
"identity_authority_unavailable",
|
|
1911
|
+
"permission_denied",
|
|
1912
|
+
"resource_not_found",
|
|
1913
|
+
"invalid_request",
|
|
1914
|
+
"precondition_failed",
|
|
1915
|
+
"service_unavailable"
|
|
1916
|
+
]);
|
|
1917
|
+
const SEARCH_WORKSPACE_ITEMS_ERROR_CODES = Object.freeze([
|
|
1918
|
+
"authentication_required",
|
|
1919
|
+
"identity_authority_unavailable",
|
|
1920
|
+
"permission_denied",
|
|
1921
|
+
"resource_not_found",
|
|
1922
|
+
"invalid_request",
|
|
1923
|
+
"invalid_pagination_cursor",
|
|
1924
|
+
"precondition_failed",
|
|
1925
|
+
"service_unavailable"
|
|
1926
|
+
]);
|
|
1927
|
+
const TRANSFER_ERROR_CODES = Object.freeze([
|
|
1928
|
+
"authentication_required",
|
|
1929
|
+
"identity_authority_unavailable",
|
|
1930
|
+
"permission_denied",
|
|
1931
|
+
"resource_not_found",
|
|
1932
|
+
"invalid_request",
|
|
1933
|
+
"precondition_failed",
|
|
1934
|
+
"upload_recovery_required",
|
|
1935
|
+
"service_unavailable"
|
|
1936
|
+
]);
|
|
1937
|
+
const STATUS_ERROR_CODES = Object.freeze([
|
|
1938
|
+
"authentication_required",
|
|
1939
|
+
"identity_authority_unavailable",
|
|
1940
|
+
"permission_denied",
|
|
1941
|
+
"resource_not_found",
|
|
1942
|
+
"invalid_request",
|
|
1943
|
+
"service_unavailable"
|
|
1944
|
+
]);
|
|
1945
|
+
const CREATE_UPLOAD_ERROR_CODES = Object.freeze([
|
|
1946
|
+
...TRANSFER_ERROR_CODES,
|
|
1947
|
+
"invalid_idempotency_key",
|
|
1948
|
+
"idempotency_conflict",
|
|
1949
|
+
"quota_exceeded"
|
|
1950
|
+
]);
|
|
1951
|
+
const COMPLETE_UPLOAD_ERROR_CODES = Object.freeze([...TRANSFER_ERROR_CODES, "invalid_idempotency_key"]);
|
|
1952
|
+
const LIFECYCLE_MUTATION_ERROR_CODES = Object.freeze([
|
|
1953
|
+
"authentication_required",
|
|
1954
|
+
"identity_authority_unavailable",
|
|
1955
|
+
"permission_denied",
|
|
1956
|
+
"resource_not_found",
|
|
1957
|
+
"invalid_request",
|
|
1958
|
+
"invalid_idempotency_key",
|
|
1959
|
+
"idempotency_conflict",
|
|
1960
|
+
"precondition_failed",
|
|
1961
|
+
"service_unavailable"
|
|
1962
|
+
]);
|
|
1963
|
+
const LIST_ITEM_VERSIONS_ERROR_CODES = Object.freeze([
|
|
1964
|
+
"authentication_required",
|
|
1965
|
+
"identity_authority_unavailable",
|
|
1966
|
+
"permission_denied",
|
|
1967
|
+
"resource_not_found",
|
|
1968
|
+
"invalid_request",
|
|
1969
|
+
"precondition_failed",
|
|
1970
|
+
"service_unavailable"
|
|
1971
|
+
]);
|
|
1972
|
+
const DOWNLOAD_ERROR_CODES = Object.freeze([
|
|
1973
|
+
"authentication_required",
|
|
1974
|
+
"identity_authority_unavailable",
|
|
1975
|
+
"permission_denied",
|
|
1976
|
+
"resource_not_found",
|
|
1977
|
+
"invalid_request",
|
|
1978
|
+
"invalid_idempotency_key",
|
|
1979
|
+
"idempotency_conflict",
|
|
1980
|
+
"precondition_failed",
|
|
1981
|
+
"range_not_satisfiable",
|
|
1982
|
+
"service_unavailable"
|
|
1983
|
+
]);
|
|
1984
|
+
function createDriveOperations(runtime) {
|
|
1281
1985
|
return Object.freeze({
|
|
1282
1986
|
getCurrentWorkspace: (input) => getCurrentWorkspace(runtime, input),
|
|
1987
|
+
getItem: (input) => getItem(runtime, input),
|
|
1988
|
+
searchWorkspaceItems: (input) => searchWorkspaceItems(runtime, input),
|
|
1283
1989
|
listFolderChildren: (input) => listFolderChildren(runtime, input),
|
|
1284
1990
|
createFolder: (input) => createFolder(runtime, input),
|
|
1991
|
+
updateItem: (input) => updateItem(runtime, input),
|
|
1992
|
+
trashItem: (input) => trashItem(runtime, input),
|
|
1993
|
+
restoreItem: (input) => restoreItem(runtime, input),
|
|
1994
|
+
deleteItem: (input) => deleteItem(runtime, input),
|
|
1995
|
+
listItemVersions: (input) => listItemVersions(runtime, input),
|
|
1996
|
+
getItemVersion: (input) => getItemVersion(runtime, input),
|
|
1997
|
+
restoreItemVersion: (input) => restoreItemVersion(runtime, input),
|
|
1998
|
+
createDownload: (input) => createDownload(runtime, input),
|
|
1999
|
+
downloadItem: (input) => downloadItem(runtime, input),
|
|
1285
2000
|
listItemPermissions: (input) => listItemPermissions(runtime, input),
|
|
1286
2001
|
readEffectiveItemPermissions: (input) => readEffectiveItemPermissions(runtime, input),
|
|
1287
2002
|
createItemPermission: (input) => createItemPermission(runtime, input),
|
|
1288
2003
|
updateItemPermission: (input) => updateItemPermission(runtime, input),
|
|
1289
2004
|
revokeItemPermission: (input) => revokeItemPermission(runtime, input),
|
|
1290
2005
|
createUpload: (input) => createUpload(runtime, input),
|
|
2006
|
+
getUploadStatus: (input) => getUploadStatus(runtime, input),
|
|
2007
|
+
createUploadPartDescriptor: (input) => createUploadPartDescriptor(runtime, input),
|
|
2008
|
+
recordUploadPart: (input) => recordUploadPart(runtime, input),
|
|
2009
|
+
completeUpload: (input) => completeUpload(runtime, input),
|
|
1291
2010
|
abortUpload: (input) => abortUpload(runtime, input)
|
|
1292
2011
|
});
|
|
1293
2012
|
}
|
|
2013
|
+
async function createDownload(runtime, input) {
|
|
2014
|
+
const validated = validateCreateDownloadInput(input);
|
|
2015
|
+
return execute(runtime, validated.signal, 412, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/items/{itemId}/downloads", {
|
|
2016
|
+
...operationOptions("createDownload", { params: {
|
|
2017
|
+
path: {
|
|
2018
|
+
workspaceId: validated.workspaceId,
|
|
2019
|
+
itemId: validated.itemId
|
|
2020
|
+
},
|
|
2021
|
+
query: validated.versionId === void 0 ? {} : { versionId: validated.versionId },
|
|
2022
|
+
header: {
|
|
2023
|
+
"Idempotency-Key": validated.idempotencyKey,
|
|
2024
|
+
"Download-Method": validated.method,
|
|
2025
|
+
...validated.range === void 0 ? {} : { Range: validated.range },
|
|
2026
|
+
...validated.ifMatch === void 0 ? {} : { "If-Match": validated.ifMatch },
|
|
2027
|
+
...validated.ifNoneMatch === void 0 ? {} : { "If-None-Match": validated.ifNoneMatch },
|
|
2028
|
+
...validated.ifRange === void 0 ? {} : { "If-Range": validated.ifRange }
|
|
2029
|
+
}
|
|
2030
|
+
} }),
|
|
2031
|
+
...requestOptions
|
|
2032
|
+
}), [
|
|
2033
|
+
200,
|
|
2034
|
+
202,
|
|
2035
|
+
304
|
|
2036
|
+
], (value, status) => status === 200 ? isManagedDownloadDescriptor(value) : status === 202 ? isManagedDownloadRestorePending(value) : value === void 0, false, DOWNLOAD_ERROR_CODES);
|
|
2037
|
+
}
|
|
2038
|
+
async function downloadItem(runtime, input) {
|
|
2039
|
+
const validated = validateCreateDownloadInput(input);
|
|
2040
|
+
const created = await createDownload(runtime, input);
|
|
2041
|
+
if (created.status === 202 || created.status === 304) return created;
|
|
2042
|
+
const descriptor = created.data;
|
|
2043
|
+
if (descriptor.expiresAtEpochMilliseconds <= Date.now()) throw new DriveError("invalid_response");
|
|
2044
|
+
const operation = createOperationSignal(validated.signal, runtime.timeoutMilliseconds);
|
|
2045
|
+
try {
|
|
2046
|
+
const response = await raceWithAbort(runtime.fetchImplementation(directDownloadRequest(descriptor, operation.signal)), operation.signal);
|
|
2047
|
+
if (!responseMatchesDownloadDescriptor(response, descriptor)) {
|
|
2048
|
+
await response.body?.cancel().catch(() => void 0);
|
|
2049
|
+
throw new DriveError("invalid_response");
|
|
2050
|
+
}
|
|
2051
|
+
const responseHeaders = downloadResponseHeaders(descriptor);
|
|
2052
|
+
if (descriptor.method === "HEAD") {
|
|
2053
|
+
await response.body?.cancel().catch(() => void 0);
|
|
2054
|
+
operation.dispose();
|
|
2055
|
+
return new Response(null, {
|
|
2056
|
+
status: response.status,
|
|
2057
|
+
headers: responseHeaders
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
if (!response.body) {
|
|
2061
|
+
operation.dispose();
|
|
2062
|
+
if (descriptor.response.contentLength !== 0) throw new DriveError("invalid_response");
|
|
2063
|
+
return new Response(null, {
|
|
2064
|
+
status: response.status,
|
|
2065
|
+
headers: responseHeaders
|
|
2066
|
+
});
|
|
2067
|
+
}
|
|
2068
|
+
operation.dispose();
|
|
2069
|
+
return new Response(streamWithOperationLifetime(response.body, descriptor.response.contentLength, validated.signal), {
|
|
2070
|
+
status: response.status,
|
|
2071
|
+
headers: responseHeaders
|
|
2072
|
+
});
|
|
2073
|
+
} catch (error) {
|
|
2074
|
+
operation.dispose();
|
|
2075
|
+
if (operation.didTimeout()) throw new DriveError("timeout");
|
|
2076
|
+
if (error instanceof DriveError) throw error;
|
|
2077
|
+
throw operation.signal.aborted ? new DriveError(operation.didTimeout() ? "timeout" : "aborted") : new DriveError("network_error");
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
function downloadResponseHeaders(descriptor) {
|
|
2081
|
+
const expected = descriptor.response;
|
|
2082
|
+
const headers = new Headers();
|
|
2083
|
+
headers.set("accept-ranges", expected.acceptRanges);
|
|
2084
|
+
headers.set("content-disposition", expected.contentDisposition);
|
|
2085
|
+
headers.set("content-length", String(expected.contentLength));
|
|
2086
|
+
headers.set("content-type", expected.contentType);
|
|
2087
|
+
headers.set("etag", expected.etag);
|
|
2088
|
+
if (expected.contentRange === null) headers.delete("content-range");
|
|
2089
|
+
else headers.set("content-range", expected.contentRange);
|
|
2090
|
+
return headers;
|
|
2091
|
+
}
|
|
2092
|
+
function directDownloadRequest(descriptor, signal) {
|
|
2093
|
+
const base = {
|
|
2094
|
+
method: descriptor.method,
|
|
2095
|
+
headers: descriptor.headers,
|
|
2096
|
+
redirect: "manual",
|
|
2097
|
+
signal
|
|
2098
|
+
};
|
|
2099
|
+
try {
|
|
2100
|
+
return new Request(descriptor.url, {
|
|
2101
|
+
...base,
|
|
2102
|
+
cache: "no-store",
|
|
2103
|
+
credentials: "omit",
|
|
2104
|
+
referrerPolicy: "no-referrer"
|
|
2105
|
+
});
|
|
2106
|
+
} catch {
|
|
2107
|
+
try {
|
|
2108
|
+
return new Request(descriptor.url, {
|
|
2109
|
+
...base,
|
|
2110
|
+
credentials: "omit",
|
|
2111
|
+
referrerPolicy: "no-referrer"
|
|
2112
|
+
});
|
|
2113
|
+
} catch {
|
|
2114
|
+
return new Request(descriptor.url, {
|
|
2115
|
+
...base,
|
|
2116
|
+
credentials: "omit"
|
|
2117
|
+
});
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
function responseMatchesDownloadDescriptor(response, descriptor) {
|
|
2122
|
+
const expected = descriptor.response;
|
|
2123
|
+
const encoding = response.headers.get("content-encoding");
|
|
2124
|
+
return response.status === expected.status && response.headers.get("etag") === expected.etag && response.headers.get("content-length") === String(expected.contentLength) && (encoding === null || encoding === "identity") && (expected.contentRange === null ? response.headers.get("content-range") === null : response.headers.get("content-range") === expected.contentRange);
|
|
2125
|
+
}
|
|
2126
|
+
function streamWithOperationLifetime(source, expectedLength, signal) {
|
|
2127
|
+
const reader = source.getReader();
|
|
2128
|
+
let receivedLength = 0;
|
|
2129
|
+
let finished = false;
|
|
2130
|
+
let removeAbort = () => {};
|
|
2131
|
+
return new ReadableStream({
|
|
2132
|
+
start(controller) {
|
|
2133
|
+
if (!signal) return;
|
|
2134
|
+
const onAbort = () => {
|
|
2135
|
+
if (finished) return;
|
|
2136
|
+
finished = true;
|
|
2137
|
+
removeAbort();
|
|
2138
|
+
reader.cancel().catch(() => void 0);
|
|
2139
|
+
controller.error(new DriveError("aborted"));
|
|
2140
|
+
};
|
|
2141
|
+
if (signal.aborted) onAbort();
|
|
2142
|
+
else {
|
|
2143
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2144
|
+
removeAbort = () => signal.removeEventListener("abort", onAbort);
|
|
2145
|
+
}
|
|
2146
|
+
},
|
|
2147
|
+
async pull(controller) {
|
|
2148
|
+
if (finished) return;
|
|
2149
|
+
try {
|
|
2150
|
+
const chunk = await reader.read();
|
|
2151
|
+
if (finished) return;
|
|
2152
|
+
if (chunk.done) {
|
|
2153
|
+
finished = true;
|
|
2154
|
+
removeAbort();
|
|
2155
|
+
reader.releaseLock();
|
|
2156
|
+
if (receivedLength === expectedLength) controller.close();
|
|
2157
|
+
else controller.error(new DriveError("invalid_response"));
|
|
2158
|
+
} else {
|
|
2159
|
+
receivedLength += chunk.value.byteLength;
|
|
2160
|
+
if (!Number.isSafeInteger(receivedLength) || receivedLength > expectedLength) {
|
|
2161
|
+
finished = true;
|
|
2162
|
+
removeAbort();
|
|
2163
|
+
await reader.cancel().catch(() => void 0);
|
|
2164
|
+
controller.error(new DriveError("invalid_response"));
|
|
2165
|
+
return;
|
|
2166
|
+
}
|
|
2167
|
+
controller.enqueue(chunk.value);
|
|
2168
|
+
}
|
|
2169
|
+
} catch (error) {
|
|
2170
|
+
if (finished) return;
|
|
2171
|
+
finished = true;
|
|
2172
|
+
removeAbort();
|
|
2173
|
+
await reader.cancel().catch(() => void 0);
|
|
2174
|
+
controller.error(error instanceof DriveError ? error : signal?.aborted ? new DriveError("aborted") : new DriveError("network_error"));
|
|
2175
|
+
}
|
|
2176
|
+
},
|
|
2177
|
+
async cancel(reason) {
|
|
2178
|
+
if (finished) return;
|
|
2179
|
+
finished = true;
|
|
2180
|
+
removeAbort();
|
|
2181
|
+
await reader.cancel(reason).catch(() => void 0);
|
|
2182
|
+
}
|
|
2183
|
+
});
|
|
2184
|
+
}
|
|
1294
2185
|
async function getCurrentWorkspace(runtime, input) {
|
|
1295
2186
|
return execute(runtime, validateCurrentWorkspaceInput(input).signal, null, (api, requestOptions) => api.GET("/api/v1/workspaces/current", {
|
|
1296
2187
|
...operationOptions("getCurrentWorkspace", { params: {} }),
|
|
1297
2188
|
...requestOptions
|
|
1298
2189
|
}), [200], isCurrentWorkspace, false, CURRENT_WORKSPACE_ERROR_CODES);
|
|
1299
2190
|
}
|
|
2191
|
+
async function getItem(runtime, input) {
|
|
2192
|
+
const validated = validateResourceInput(input);
|
|
2193
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}", {
|
|
2194
|
+
...operationOptions("getItem", { params: { path: resourcePath(validated) } }),
|
|
2195
|
+
...requestOptions
|
|
2196
|
+
}), [200], (value, _status, headers) => isManagedItemMetadata(value, validated.workspaceId, validated.itemId) && itemEtagMatchesRevision(headers, value.revision), false, GET_ITEM_ERROR_CODES);
|
|
2197
|
+
}
|
|
2198
|
+
async function searchWorkspaceItems(runtime, input) {
|
|
2199
|
+
const validated = validateSearchWorkspaceItemsInput(input);
|
|
2200
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/search", {
|
|
2201
|
+
...operationOptions("searchWorkspaceItems", { params: {
|
|
2202
|
+
path: { workspaceId: validated.workspaceId },
|
|
2203
|
+
query: {
|
|
2204
|
+
query: validated.query,
|
|
2205
|
+
...validated.limit === void 0 ? {} : { limit: validated.limit },
|
|
2206
|
+
...validated.cursor === void 0 ? {} : { cursor: validated.cursor }
|
|
2207
|
+
}
|
|
2208
|
+
} }),
|
|
2209
|
+
...requestOptions
|
|
2210
|
+
}), [200], (value) => isWorkspaceItemSearchPage(value, validated.workspaceId, validated.query, validated.limit ?? 50), false, SEARCH_WORKSPACE_ITEMS_ERROR_CODES);
|
|
2211
|
+
}
|
|
1300
2212
|
async function listFolderChildren(runtime, input) {
|
|
1301
2213
|
const validated = validatePageInput(input);
|
|
1302
2214
|
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/children", {
|
|
@@ -1320,6 +2232,100 @@ async function createFolder(runtime, input) {
|
|
|
1320
2232
|
...requestOptions
|
|
1321
2233
|
}), [200, 201], (value) => isFolderItem(value) && value.workspaceId === validated.workspaceId && value.parentItemId === validated.itemId && value.kind === "folder" && value.name === validated.name);
|
|
1322
2234
|
}
|
|
2235
|
+
async function updateItem(runtime, input) {
|
|
2236
|
+
const validated = validateUpdateItemInput(input);
|
|
2237
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.PATCH("/api/v1/workspaces/{workspaceId}/items/{itemId}", {
|
|
2238
|
+
...operationOptions("updateItem", {
|
|
2239
|
+
params: {
|
|
2240
|
+
path: resourcePath(validated),
|
|
2241
|
+
header: {
|
|
2242
|
+
"Idempotency-Key": validated.idempotencyKey,
|
|
2243
|
+
"If-Match": validated.ifMatch
|
|
2244
|
+
}
|
|
2245
|
+
},
|
|
2246
|
+
body: {
|
|
2247
|
+
name: validated.name,
|
|
2248
|
+
parentItemId: validated.parentItemId
|
|
2249
|
+
}
|
|
2250
|
+
}),
|
|
2251
|
+
...requestOptions
|
|
2252
|
+
}), [200], (value, _status, headers) => isManagedLifecycleItem(value, validated.workspaceId, validated.itemId, "active") && value.name === validated.name && value.parentItemId === validated.parentItemId && itemEtagMatchesRevision(headers, value.revision), false, LIFECYCLE_MUTATION_ERROR_CODES);
|
|
2253
|
+
}
|
|
2254
|
+
async function trashItem(runtime, input) {
|
|
2255
|
+
const validated = validateLifecycleMutationInput(input);
|
|
2256
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/items/{itemId}/trash", {
|
|
2257
|
+
...operationOptions("trashItem", { params: {
|
|
2258
|
+
path: resourcePath(validated),
|
|
2259
|
+
header: {
|
|
2260
|
+
"Idempotency-Key": validated.idempotencyKey,
|
|
2261
|
+
"If-Match": validated.ifMatch
|
|
2262
|
+
}
|
|
2263
|
+
} }),
|
|
2264
|
+
...requestOptions
|
|
2265
|
+
}), [200], (value, _status, headers) => isManagedLifecycleItem(value, validated.workspaceId, validated.itemId, "trashed") && itemEtagMatchesRevision(headers, value.revision), false, LIFECYCLE_MUTATION_ERROR_CODES);
|
|
2266
|
+
}
|
|
2267
|
+
async function restoreItem(runtime, input) {
|
|
2268
|
+
const validated = validateLifecycleMutationInput(input);
|
|
2269
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/items/{itemId}/restore", {
|
|
2270
|
+
...operationOptions("restoreItem", { params: {
|
|
2271
|
+
path: resourcePath(validated),
|
|
2272
|
+
header: {
|
|
2273
|
+
"Idempotency-Key": validated.idempotencyKey,
|
|
2274
|
+
"If-Match": validated.ifMatch
|
|
2275
|
+
}
|
|
2276
|
+
} }),
|
|
2277
|
+
...requestOptions
|
|
2278
|
+
}), [200], (value, _status, headers) => isManagedLifecycleItem(value, validated.workspaceId, validated.itemId, "active") && itemEtagMatchesRevision(headers, value.revision), false, LIFECYCLE_MUTATION_ERROR_CODES);
|
|
2279
|
+
}
|
|
2280
|
+
async function deleteItem(runtime, input) {
|
|
2281
|
+
const validated = validateLifecycleMutationInput(input);
|
|
2282
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.DELETE("/api/v1/workspaces/{workspaceId}/items/{itemId}", {
|
|
2283
|
+
...operationOptions("deleteItem", { params: {
|
|
2284
|
+
path: resourcePath(validated),
|
|
2285
|
+
header: {
|
|
2286
|
+
"Idempotency-Key": validated.idempotencyKey,
|
|
2287
|
+
"If-Match": validated.ifMatch
|
|
2288
|
+
}
|
|
2289
|
+
} }),
|
|
2290
|
+
...requestOptions
|
|
2291
|
+
}), [200, 202], (value, _status, headers) => isManagedLifecycleItem(value, validated.workspaceId, validated.itemId, "deleting") && itemEtagMatchesRevision(headers, value.revision), false, LIFECYCLE_MUTATION_ERROR_CODES);
|
|
2292
|
+
}
|
|
2293
|
+
async function listItemVersions(runtime, input) {
|
|
2294
|
+
const validated = validatePageInput(input);
|
|
2295
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/versions", {
|
|
2296
|
+
...operationOptions("listItemVersions", { params: {
|
|
2297
|
+
path: resourcePath(validated),
|
|
2298
|
+
query: pageQuery(validated)
|
|
2299
|
+
} }),
|
|
2300
|
+
...requestOptions
|
|
2301
|
+
}), [200], (value) => isManagedItemVersionPage(value, validated.limit ?? 50), false, LIST_ITEM_VERSIONS_ERROR_CODES);
|
|
2302
|
+
}
|
|
2303
|
+
async function getItemVersion(runtime, input) {
|
|
2304
|
+
const validated = validateItemVersionInput(input);
|
|
2305
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/versions/{versionId}", {
|
|
2306
|
+
...operationOptions("getItemVersion", { params: { path: {
|
|
2307
|
+
...resourcePath(validated),
|
|
2308
|
+
versionId: validated.versionId
|
|
2309
|
+
} } }),
|
|
2310
|
+
...requestOptions
|
|
2311
|
+
}), [200], (value) => isManagedItemVersionResource(value, validated.workspaceId, validated.itemId, validated.versionId), false, LIST_ITEM_VERSIONS_ERROR_CODES);
|
|
2312
|
+
}
|
|
2313
|
+
async function restoreItemVersion(runtime, input) {
|
|
2314
|
+
const validated = validateRestoreItemVersionInput(input);
|
|
2315
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/items/{itemId}/versions/{versionId}/restore", {
|
|
2316
|
+
...operationOptions("restoreItemVersion", { params: {
|
|
2317
|
+
path: {
|
|
2318
|
+
...resourcePath(validated),
|
|
2319
|
+
versionId: validated.versionId
|
|
2320
|
+
},
|
|
2321
|
+
header: {
|
|
2322
|
+
"Idempotency-Key": validated.idempotencyKey,
|
|
2323
|
+
"If-Match": validated.ifMatch
|
|
2324
|
+
}
|
|
2325
|
+
} }),
|
|
2326
|
+
...requestOptions
|
|
2327
|
+
}), [200], (value, _status, headers) => isManagedItemVersionRestoreResult(value, validated.versionId) && itemEtagMatchesRevision(headers, value.itemRevision), false, LIFECYCLE_MUTATION_ERROR_CODES);
|
|
2328
|
+
}
|
|
1323
2329
|
async function listItemPermissions(runtime, input) {
|
|
1324
2330
|
const validated = validatePageInput(input);
|
|
1325
2331
|
return execute(runtime, validated.signal, 412, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/permissions", {
|
|
@@ -1405,11 +2411,81 @@ async function createUpload(runtime, input) {
|
|
|
1405
2411
|
},
|
|
1406
2412
|
body: {
|
|
1407
2413
|
parentItemId: validated.parentItemId,
|
|
1408
|
-
expectedByteLength: validated.expectedByteLength
|
|
2414
|
+
expectedByteLength: validated.expectedByteLength,
|
|
2415
|
+
displayFilename: validated.displayFilename,
|
|
2416
|
+
mediaType: validated.mediaType,
|
|
2417
|
+
callerDeclaredContentDigest: validated.callerDeclaredContentDigest,
|
|
2418
|
+
protectionClassification: validated.protectionClassification
|
|
2419
|
+
}
|
|
2420
|
+
}),
|
|
2421
|
+
...requestOptions
|
|
2422
|
+
}), [200, 201], (value) => isUploadSession(value, validated.expectedByteLength), true, CREATE_UPLOAD_ERROR_CODES);
|
|
2423
|
+
}
|
|
2424
|
+
async function getUploadStatus(runtime, input) {
|
|
2425
|
+
const validated = validateGetUploadStatusInput(input);
|
|
2426
|
+
const afterPartNumber = validated.afterPartNumber ?? 0;
|
|
2427
|
+
const limit = validated.limit ?? 100;
|
|
2428
|
+
return execute(runtime, validated.signal, null, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}", {
|
|
2429
|
+
...operationOptions("getUploadStatus", { params: {
|
|
2430
|
+
path: {
|
|
2431
|
+
workspaceId: validated.workspaceId,
|
|
2432
|
+
uploadId: validated.uploadId
|
|
2433
|
+
},
|
|
2434
|
+
query: {
|
|
2435
|
+
...validated.afterPartNumber === void 0 ? {} : { afterPartNumber: String(validated.afterPartNumber) },
|
|
2436
|
+
...validated.limit === void 0 ? {} : { limit: String(validated.limit) }
|
|
2437
|
+
}
|
|
2438
|
+
} }),
|
|
2439
|
+
...requestOptions
|
|
2440
|
+
}), [200], (value) => isUploadStatus(value, afterPartNumber, limit), false, STATUS_ERROR_CODES);
|
|
2441
|
+
}
|
|
2442
|
+
async function createUploadPartDescriptor(runtime, input) {
|
|
2443
|
+
const validated = validateCreateUploadPartDescriptorInput(input);
|
|
2444
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}/parts", {
|
|
2445
|
+
...operationOptions("createUploadPartDescriptor", {
|
|
2446
|
+
params: { path: {
|
|
2447
|
+
workspaceId: validated.workspaceId,
|
|
2448
|
+
uploadId: validated.uploadId
|
|
2449
|
+
} },
|
|
2450
|
+
body: {
|
|
2451
|
+
partNumber: validated.partNumber,
|
|
2452
|
+
checksumSha256: validated.checksumSha256
|
|
1409
2453
|
}
|
|
1410
2454
|
}),
|
|
1411
2455
|
...requestOptions
|
|
1412
|
-
}), [200
|
|
2456
|
+
}), [200], (value) => isUploadPartDescriptor(value, validated.partNumber, validated.checksumSha256, new URL(runtime.baseUrl).protocol === "http:"), false, TRANSFER_ERROR_CODES);
|
|
2457
|
+
}
|
|
2458
|
+
async function recordUploadPart(runtime, input) {
|
|
2459
|
+
const validated = validateRecordUploadPartInput(input);
|
|
2460
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}/parts/{partNumber}", {
|
|
2461
|
+
...operationOptions("recordUploadPart", {
|
|
2462
|
+
params: { path: {
|
|
2463
|
+
workspaceId: validated.workspaceId,
|
|
2464
|
+
uploadId: validated.uploadId,
|
|
2465
|
+
partNumber: String(validated.partNumber)
|
|
2466
|
+
} },
|
|
2467
|
+
body: {
|
|
2468
|
+
expectedUploadRevision: validated.expectedUploadRevision,
|
|
2469
|
+
byteLength: validated.byteLength,
|
|
2470
|
+
etag: validated.etag,
|
|
2471
|
+
checksumSha256: validated.checksumSha256
|
|
2472
|
+
}
|
|
2473
|
+
}),
|
|
2474
|
+
...requestOptions
|
|
2475
|
+
}), [200], (value) => isUploadPartResult(value, validated.partNumber, validated.expectedUploadRevision), false, TRANSFER_ERROR_CODES);
|
|
2476
|
+
}
|
|
2477
|
+
async function completeUpload(runtime, input) {
|
|
2478
|
+
const validated = validateCompleteUploadInput(input);
|
|
2479
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}/complete", {
|
|
2480
|
+
...operationOptions("completeUpload", { params: {
|
|
2481
|
+
path: {
|
|
2482
|
+
workspaceId: validated.workspaceId,
|
|
2483
|
+
uploadId: validated.uploadId
|
|
2484
|
+
},
|
|
2485
|
+
header: { "Idempotency-Key": validated.idempotencyKey }
|
|
2486
|
+
} }),
|
|
2487
|
+
...requestOptions
|
|
2488
|
+
}), [200], (value) => isReadyUpload(value, { uploadId: validated.uploadId }), false, COMPLETE_UPLOAD_ERROR_CODES);
|
|
1413
2489
|
}
|
|
1414
2490
|
async function abortUpload(runtime, input) {
|
|
1415
2491
|
const validated = validateAbortUploadInput(input);
|
|
@@ -1419,12 +2495,717 @@ async function abortUpload(runtime, input) {
|
|
|
1419
2495
|
uploadId: validated.uploadId
|
|
1420
2496
|
} } }),
|
|
1421
2497
|
...requestOptions
|
|
1422
|
-
}), [
|
|
2498
|
+
}), [204], null, false, TRANSFER_ERROR_CODES);
|
|
2499
|
+
}
|
|
2500
|
+
//#endregion
|
|
2501
|
+
//#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/_u64.js
|
|
2502
|
+
const fromNumH = (n) => n / 2 ** 32 | 0;
|
|
2503
|
+
const fromNumL = (n) => n >>> 0;
|
|
2504
|
+
function setU64FromNum(view, byteOffset, n, isLE) {
|
|
2505
|
+
const h = fromNumH(n);
|
|
2506
|
+
const l = fromNumL(n);
|
|
2507
|
+
view.setUint32(byteOffset, isLE ? l : h, isLE);
|
|
2508
|
+
view.setUint32(byteOffset + 4, isLE ? h : l, isLE);
|
|
2509
|
+
}
|
|
2510
|
+
//#endregion
|
|
2511
|
+
//#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/utils.js
|
|
2512
|
+
function isBytes(a) {
|
|
2513
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array" && "BYTES_PER_ELEMENT" in a && a.BYTES_PER_ELEMENT === 1;
|
|
2514
|
+
}
|
|
2515
|
+
const atitle = (title) => title ? `"${title}" ` : "";
|
|
2516
|
+
function anumber(n, title = "") {
|
|
2517
|
+
if (typeof n !== "number") throw new TypeError(atitle(title) + "expected number, got " + typeof n);
|
|
2518
|
+
if (!Number.isSafeInteger(n) || n < 0) throw new RangeError(atitle(title) + "expected integer >= 0, got " + n);
|
|
2519
|
+
return n;
|
|
2520
|
+
}
|
|
2521
|
+
function abytes(value, length, title = "") {
|
|
2522
|
+
if (isBytes(value) && (length === void 0 || value.length === length)) return value;
|
|
2523
|
+
if (length !== void 0) anumber(length, "length");
|
|
2524
|
+
const bytes = isBytes(value);
|
|
2525
|
+
const ofLen = length !== void 0 ? ` of length ${length}` : "";
|
|
2526
|
+
const got = bytes ? `length=${value.length}` : `type=${typeof value}`;
|
|
2527
|
+
const message = atitle(title) + "expected Uint8Array" + ofLen + ", got " + got;
|
|
2528
|
+
if (!bytes) throw new TypeError(message);
|
|
2529
|
+
throw new RangeError(message);
|
|
2530
|
+
}
|
|
2531
|
+
const aobject = (value, label) => {
|
|
2532
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) throw new TypeError((label === "object" ? "" : `"${label}" `) + "expected object, got type=" + typeof value);
|
|
2533
|
+
};
|
|
2534
|
+
function aexists(instance, checkFinished = true) {
|
|
2535
|
+
if (instance.destroyed) throw new Error("hash was destroyed");
|
|
2536
|
+
if (checkFinished && instance.finished) throw new Error("digest() was already called");
|
|
2537
|
+
}
|
|
2538
|
+
function aoutput(out, instance) {
|
|
2539
|
+
abytes(out, void 0, "output");
|
|
2540
|
+
const min = instance.outputLen;
|
|
2541
|
+
if (!(out.length >= min)) throw new RangeError("\"output\" expected length >= " + min);
|
|
2542
|
+
}
|
|
2543
|
+
function clean(...arrays) {
|
|
2544
|
+
for (let i = 0; i < arrays.length; i++) arrays[i].fill(0);
|
|
2545
|
+
}
|
|
2546
|
+
function createView(arr) {
|
|
2547
|
+
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
2548
|
+
}
|
|
2549
|
+
function rotr(word, shift) {
|
|
2550
|
+
return word << 32 - shift | word >>> shift;
|
|
2551
|
+
}
|
|
2552
|
+
const hasHexBuiltin = (() => typeof Uint8Array.from([]).toHex === "function" && typeof Uint8Array.fromHex === "function")();
|
|
2553
|
+
const hexes = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
|
|
2554
|
+
function bytesToHex(bytes) {
|
|
2555
|
+
abytes(bytes);
|
|
2556
|
+
if (hasHexBuiltin) return bytes.toHex();
|
|
2557
|
+
let hex = "";
|
|
2558
|
+
for (let i = 0; i < bytes.length; i++) hex += hexes[bytes[i]];
|
|
2559
|
+
return hex;
|
|
2560
|
+
}
|
|
2561
|
+
function checkOpts(defaults, opts, title = "opts") {
|
|
2562
|
+
aobject(defaults, "defaults");
|
|
2563
|
+
if (opts !== void 0) aobject(opts, title);
|
|
2564
|
+
return Object.assign(defaults, opts);
|
|
2565
|
+
}
|
|
2566
|
+
function createHasher(hashCons, info = {}) {
|
|
2567
|
+
if (typeof hashCons !== "function") throw new TypeError("\"hashCons\" expected function, got type=" + typeof hashCons);
|
|
2568
|
+
info = checkOpts({}, info, "info");
|
|
2569
|
+
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
2570
|
+
const tmp = hashCons(void 0);
|
|
2571
|
+
hashC.outputLen = tmp.outputLen;
|
|
2572
|
+
hashC.blockLen = tmp.blockLen;
|
|
2573
|
+
hashC.canXOF = tmp.canXOF;
|
|
2574
|
+
hashC.create = (opts) => hashCons(opts);
|
|
2575
|
+
Object.assign(hashC, info);
|
|
2576
|
+
return Object.freeze(hashC);
|
|
2577
|
+
}
|
|
2578
|
+
const oidNist = (suffix) => ({ oid: Uint8Array.from([
|
|
2579
|
+
6,
|
|
2580
|
+
9,
|
|
2581
|
+
96,
|
|
2582
|
+
134,
|
|
2583
|
+
72,
|
|
2584
|
+
1,
|
|
2585
|
+
101,
|
|
2586
|
+
3,
|
|
2587
|
+
4,
|
|
2588
|
+
2,
|
|
2589
|
+
suffix
|
|
2590
|
+
]) });
|
|
2591
|
+
//#endregion
|
|
2592
|
+
//#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/_md.js
|
|
2593
|
+
function Chi(a, b, c) {
|
|
2594
|
+
return a & b ^ ~a & c;
|
|
2595
|
+
}
|
|
2596
|
+
function Maj(a, b, c) {
|
|
2597
|
+
return a & b ^ a & c ^ b & c;
|
|
2598
|
+
}
|
|
2599
|
+
var HashMD = class {
|
|
2600
|
+
blockLen;
|
|
2601
|
+
outputLen;
|
|
2602
|
+
canXOF = false;
|
|
2603
|
+
padOffset;
|
|
2604
|
+
isLE;
|
|
2605
|
+
buffer;
|
|
2606
|
+
view;
|
|
2607
|
+
finished = false;
|
|
2608
|
+
length = 0;
|
|
2609
|
+
pos = 0;
|
|
2610
|
+
destroyed = false;
|
|
2611
|
+
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
2612
|
+
this.blockLen = blockLen;
|
|
2613
|
+
this.outputLen = outputLen;
|
|
2614
|
+
this.padOffset = padOffset;
|
|
2615
|
+
this.isLE = isLE;
|
|
2616
|
+
this.buffer = new Uint8Array(blockLen);
|
|
2617
|
+
this.view = createView(this.buffer);
|
|
2618
|
+
}
|
|
2619
|
+
update(data) {
|
|
2620
|
+
aexists(this);
|
|
2621
|
+
abytes(data);
|
|
2622
|
+
const { view, buffer, blockLen } = this;
|
|
2623
|
+
const len = data.length;
|
|
2624
|
+
let processed = false;
|
|
2625
|
+
for (let pos = 0; pos < len;) {
|
|
2626
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
2627
|
+
if (take === blockLen) {
|
|
2628
|
+
const dataView = createView(data);
|
|
2629
|
+
for (; blockLen <= len - pos; pos += blockLen) this.process(dataView, pos);
|
|
2630
|
+
processed = true;
|
|
2631
|
+
continue;
|
|
2632
|
+
}
|
|
2633
|
+
buffer.set(pos === 0 && take === len ? data : data.subarray(pos, pos + take), this.pos);
|
|
2634
|
+
this.pos += take;
|
|
2635
|
+
pos += take;
|
|
2636
|
+
if (this.pos === blockLen) {
|
|
2637
|
+
this.process(view, 0);
|
|
2638
|
+
this.pos = 0;
|
|
2639
|
+
processed = true;
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
this.length += data.length;
|
|
2643
|
+
if (processed) this.roundClean();
|
|
2644
|
+
return this;
|
|
2645
|
+
}
|
|
2646
|
+
digestInto(out) {
|
|
2647
|
+
aexists(this);
|
|
2648
|
+
aoutput(out, this);
|
|
2649
|
+
this.finished = true;
|
|
2650
|
+
const { buffer, view, blockLen, isLE } = this;
|
|
2651
|
+
let { pos } = this;
|
|
2652
|
+
buffer[pos++] = 128;
|
|
2653
|
+
buffer.fill(0, pos);
|
|
2654
|
+
if (this.padOffset > blockLen - pos) {
|
|
2655
|
+
this.process(view, 0);
|
|
2656
|
+
buffer.fill(0);
|
|
2657
|
+
}
|
|
2658
|
+
setU64FromNum(view, blockLen - 8, this.length * 8, isLE);
|
|
2659
|
+
this.process(view, 0);
|
|
2660
|
+
this.roundClean();
|
|
2661
|
+
const oview = out === buffer ? view : createView(out);
|
|
2662
|
+
const len = this.outputLen;
|
|
2663
|
+
const outLen = len / 4;
|
|
2664
|
+
const state = this.get();
|
|
2665
|
+
if (len % 4 || outLen > state.length) throw new Error("invalid outputLen");
|
|
2666
|
+
for (let i = 0; i < outLen; i++) oview.setUint32(4 * i, state[i], isLE);
|
|
2667
|
+
}
|
|
2668
|
+
digest() {
|
|
2669
|
+
const { buffer, outputLen } = this;
|
|
2670
|
+
this.digestInto(buffer);
|
|
2671
|
+
const res = buffer.slice(0, outputLen);
|
|
2672
|
+
this.destroy();
|
|
2673
|
+
return res;
|
|
2674
|
+
}
|
|
2675
|
+
_cloneIntoMeta(to) {
|
|
2676
|
+
const { buffer, length, finished, destroyed, pos } = this;
|
|
2677
|
+
to.destroyed = destroyed;
|
|
2678
|
+
to.finished = finished;
|
|
2679
|
+
to.length = length;
|
|
2680
|
+
to.pos = pos;
|
|
2681
|
+
if (pos) to.buffer.set(buffer);
|
|
2682
|
+
return to;
|
|
2683
|
+
}
|
|
2684
|
+
clone() {
|
|
2685
|
+
return this._cloneInto();
|
|
2686
|
+
}
|
|
2687
|
+
};
|
|
2688
|
+
const SHA256_IV = Uint32Array.from([
|
|
2689
|
+
1779033703,
|
|
2690
|
+
3144134277,
|
|
2691
|
+
1013904242,
|
|
2692
|
+
2773480762,
|
|
2693
|
+
1359893119,
|
|
2694
|
+
2600822924,
|
|
2695
|
+
528734635,
|
|
2696
|
+
1541459225
|
|
2697
|
+
]);
|
|
2698
|
+
//#endregion
|
|
2699
|
+
//#region ../../node_modules/.pnpm/@noble+hashes@2.3.0/node_modules/@noble/hashes/sha2.js
|
|
2700
|
+
const SHA256_K = Uint32Array.from([
|
|
2701
|
+
1116352408,
|
|
2702
|
+
1899447441,
|
|
2703
|
+
3049323471,
|
|
2704
|
+
3921009573,
|
|
2705
|
+
961987163,
|
|
2706
|
+
1508970993,
|
|
2707
|
+
2453635748,
|
|
2708
|
+
2870763221,
|
|
2709
|
+
3624381080,
|
|
2710
|
+
310598401,
|
|
2711
|
+
607225278,
|
|
2712
|
+
1426881987,
|
|
2713
|
+
1925078388,
|
|
2714
|
+
2162078206,
|
|
2715
|
+
2614888103,
|
|
2716
|
+
3248222580,
|
|
2717
|
+
3835390401,
|
|
2718
|
+
4022224774,
|
|
2719
|
+
264347078,
|
|
2720
|
+
604807628,
|
|
2721
|
+
770255983,
|
|
2722
|
+
1249150122,
|
|
2723
|
+
1555081692,
|
|
2724
|
+
1996064986,
|
|
2725
|
+
2554220882,
|
|
2726
|
+
2821834349,
|
|
2727
|
+
2952996808,
|
|
2728
|
+
3210313671,
|
|
2729
|
+
3336571891,
|
|
2730
|
+
3584528711,
|
|
2731
|
+
113926993,
|
|
2732
|
+
338241895,
|
|
2733
|
+
666307205,
|
|
2734
|
+
773529912,
|
|
2735
|
+
1294757372,
|
|
2736
|
+
1396182291,
|
|
2737
|
+
1695183700,
|
|
2738
|
+
1986661051,
|
|
2739
|
+
2177026350,
|
|
2740
|
+
2456956037,
|
|
2741
|
+
2730485921,
|
|
2742
|
+
2820302411,
|
|
2743
|
+
3259730800,
|
|
2744
|
+
3345764771,
|
|
2745
|
+
3516065817,
|
|
2746
|
+
3600352804,
|
|
2747
|
+
4094571909,
|
|
2748
|
+
275423344,
|
|
2749
|
+
430227734,
|
|
2750
|
+
506948616,
|
|
2751
|
+
659060556,
|
|
2752
|
+
883997877,
|
|
2753
|
+
958139571,
|
|
2754
|
+
1322822218,
|
|
2755
|
+
1537002063,
|
|
2756
|
+
1747873779,
|
|
2757
|
+
1955562222,
|
|
2758
|
+
2024104815,
|
|
2759
|
+
2227730452,
|
|
2760
|
+
2361852424,
|
|
2761
|
+
2428436474,
|
|
2762
|
+
2756734187,
|
|
2763
|
+
3204031479,
|
|
2764
|
+
3329325298
|
|
2765
|
+
]);
|
|
2766
|
+
const SHA256_W = new Uint32Array(64);
|
|
2767
|
+
var SHA2_32B = class extends HashMD {
|
|
2768
|
+
A = 0;
|
|
2769
|
+
B = 0;
|
|
2770
|
+
C = 0;
|
|
2771
|
+
D = 0;
|
|
2772
|
+
E = 0;
|
|
2773
|
+
F = 0;
|
|
2774
|
+
G = 0;
|
|
2775
|
+
H = 0;
|
|
2776
|
+
constructor(outputLen, IV) {
|
|
2777
|
+
super(64, outputLen, 8, false);
|
|
2778
|
+
this.A = IV[0] | 0;
|
|
2779
|
+
this.B = IV[1] | 0;
|
|
2780
|
+
this.C = IV[2] | 0;
|
|
2781
|
+
this.D = IV[3] | 0;
|
|
2782
|
+
this.E = IV[4] | 0;
|
|
2783
|
+
this.F = IV[5] | 0;
|
|
2784
|
+
this.G = IV[6] | 0;
|
|
2785
|
+
this.H = IV[7] | 0;
|
|
2786
|
+
}
|
|
2787
|
+
get() {
|
|
2788
|
+
const { A, B, C, D, E, F, G, H } = this;
|
|
2789
|
+
return [
|
|
2790
|
+
A,
|
|
2791
|
+
B,
|
|
2792
|
+
C,
|
|
2793
|
+
D,
|
|
2794
|
+
E,
|
|
2795
|
+
F,
|
|
2796
|
+
G,
|
|
2797
|
+
H
|
|
2798
|
+
];
|
|
2799
|
+
}
|
|
2800
|
+
set(A, B, C, D, E, F, G, H) {
|
|
2801
|
+
this.A = A | 0;
|
|
2802
|
+
this.B = B | 0;
|
|
2803
|
+
this.C = C | 0;
|
|
2804
|
+
this.D = D | 0;
|
|
2805
|
+
this.E = E | 0;
|
|
2806
|
+
this.F = F | 0;
|
|
2807
|
+
this.G = G | 0;
|
|
2808
|
+
this.H = H | 0;
|
|
2809
|
+
}
|
|
2810
|
+
_cloneInto(to) {
|
|
2811
|
+
(to ||= new this.constructor()).set(...this.get());
|
|
2812
|
+
return this._cloneIntoMeta(to);
|
|
2813
|
+
}
|
|
2814
|
+
process(view, offset) {
|
|
2815
|
+
for (let i = 0; i < 16; i++, offset += 4) SHA256_W[i] = view.getUint32(offset, false);
|
|
2816
|
+
for (let i = 16; i < 64; i++) {
|
|
2817
|
+
const W15 = SHA256_W[i - 15];
|
|
2818
|
+
const W2 = SHA256_W[i - 2];
|
|
2819
|
+
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
2820
|
+
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
2821
|
+
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
|
|
2822
|
+
}
|
|
2823
|
+
let { A, B, C, D, E, F, G, H } = this;
|
|
2824
|
+
for (let i = 0; i < 64; i++) {
|
|
2825
|
+
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
2826
|
+
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
|
|
2827
|
+
const T2 = (rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22)) + Maj(A, B, C) | 0;
|
|
2828
|
+
H = G;
|
|
2829
|
+
G = F;
|
|
2830
|
+
F = E;
|
|
2831
|
+
E = D + T1 | 0;
|
|
2832
|
+
D = C;
|
|
2833
|
+
C = B;
|
|
2834
|
+
B = A;
|
|
2835
|
+
A = T1 + T2 | 0;
|
|
2836
|
+
}
|
|
2837
|
+
A = A + this.A | 0;
|
|
2838
|
+
B = B + this.B | 0;
|
|
2839
|
+
C = C + this.C | 0;
|
|
2840
|
+
D = D + this.D | 0;
|
|
2841
|
+
E = E + this.E | 0;
|
|
2842
|
+
F = F + this.F | 0;
|
|
2843
|
+
G = G + this.G | 0;
|
|
2844
|
+
H = H + this.H | 0;
|
|
2845
|
+
this.set(A, B, C, D, E, F, G, H);
|
|
2846
|
+
}
|
|
2847
|
+
roundClean() {
|
|
2848
|
+
clean(SHA256_W);
|
|
2849
|
+
}
|
|
2850
|
+
destroy() {
|
|
2851
|
+
this.destroyed = true;
|
|
2852
|
+
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
2853
|
+
clean(this.buffer);
|
|
2854
|
+
}
|
|
2855
|
+
};
|
|
2856
|
+
var _SHA256 = class extends SHA2_32B {
|
|
2857
|
+
constructor() {
|
|
2858
|
+
super(32, SHA256_IV);
|
|
2859
|
+
}
|
|
2860
|
+
};
|
|
2861
|
+
const sha256 = createHasher(() => new _SHA256(), oidNist(1));
|
|
2862
|
+
//#endregion
|
|
2863
|
+
//#region src/internal/client/upload.ts
|
|
2864
|
+
const UPLOAD_PART_BYTE_LENGTH = 32 * 1024 * 1024;
|
|
2865
|
+
const STATUS_PAGE_LIMIT = 100;
|
|
2866
|
+
const STATUS_PAGE_MAXIMUM = 100;
|
|
2867
|
+
const ABORT_DEADLINE_MILLISECONDS = 5e3;
|
|
2868
|
+
async function uploadFileInternal(runtime, input, controls) {
|
|
2869
|
+
const validated = validateUploadFileInput(input);
|
|
2870
|
+
const totalPartCount = Math.ceil(validated.byteLength / UPLOAD_PART_BYTE_LENGTH);
|
|
2871
|
+
emitProgress(validated.onProgress, "preparing", 0, validated.byteLength, 0, totalPartCount);
|
|
2872
|
+
let session;
|
|
2873
|
+
try {
|
|
2874
|
+
const digests = await hashSource(validated.source, validated.byteLength, totalPartCount, validated.signal);
|
|
2875
|
+
const created = await controls.createUpload({
|
|
2876
|
+
workspaceId: validated.workspaceId,
|
|
2877
|
+
parentItemId: validated.parentItemId,
|
|
2878
|
+
expectedByteLength: validated.byteLength,
|
|
2879
|
+
displayFilename: validated.displayFilename,
|
|
2880
|
+
mediaType: validated.mediaType,
|
|
2881
|
+
callerDeclaredContentDigest: digests.callerDeclaredContentDigest,
|
|
2882
|
+
protectionClassification: validated.protectionClassification,
|
|
2883
|
+
idempotencyKey: validated.idempotencyKey,
|
|
2884
|
+
...validated.signal === void 0 ? {} : { signal: validated.signal }
|
|
2885
|
+
});
|
|
2886
|
+
session = created.data;
|
|
2887
|
+
assertSessionPolicy(session, validated.byteLength, totalPartCount, created.status, created.requestId);
|
|
2888
|
+
const resumed = await readResumeState(controls, validated, session, digests);
|
|
2889
|
+
emitProgress(validated.onProgress, "uploading", resumed.confirmedByteLength, validated.byteLength, resumed.confirmedParts.size, totalPartCount);
|
|
2890
|
+
if (resumed.readyResult) {
|
|
2891
|
+
emitProgress(validated.onProgress, "completing", resumed.confirmedByteLength, validated.byteLength, resumed.confirmedParts.size, totalPartCount);
|
|
2892
|
+
return resumed.readyResult;
|
|
2893
|
+
}
|
|
2894
|
+
let revision = resumed.revision;
|
|
2895
|
+
let confirmedByteLength = resumed.confirmedByteLength;
|
|
2896
|
+
let confirmedPartCount = resumed.confirmedParts.size;
|
|
2897
|
+
if (resumed.lifecycle === "uploading") for (const partNumber of pendingUploadPartNumbers(session.partCount, resumed.confirmedParts)) {
|
|
2898
|
+
const index = partNumber - 1;
|
|
2899
|
+
throwIfCallerAborted(validated.signal);
|
|
2900
|
+
const start = index * session.partByteLength;
|
|
2901
|
+
const end = Math.min(start + session.partByteLength, validated.byteLength);
|
|
2902
|
+
const expectedByteLength = end - start;
|
|
2903
|
+
const checksumSha256 = digests.partChecksums[index];
|
|
2904
|
+
if (!checksumSha256) throw new DriveError("invalid_response");
|
|
2905
|
+
const descriptorResult = await controls.createUploadPartDescriptor({
|
|
2906
|
+
workspaceId: validated.workspaceId,
|
|
2907
|
+
uploadId: session.uploadId,
|
|
2908
|
+
partNumber,
|
|
2909
|
+
checksumSha256,
|
|
2910
|
+
...validated.signal === void 0 ? {} : { signal: validated.signal }
|
|
2911
|
+
});
|
|
2912
|
+
const descriptor = descriptorResult.data;
|
|
2913
|
+
if (descriptor.expectedByteLength !== expectedByteLength || descriptor.expiresAtEpochMilliseconds > session.expiresAtEpochMilliseconds) throw new DriveError("invalid_response", {
|
|
2914
|
+
status: descriptorResult.status,
|
|
2915
|
+
requestId: descriptorResult.requestId
|
|
2916
|
+
});
|
|
2917
|
+
const etag = await putPart(runtime, descriptor, slicePart(validated.source, start, end, expectedByteLength), checksumSha256, validated.signal);
|
|
2918
|
+
revision = await recordPartWithReconciliation(controls, validated, session, partNumber, revision, expectedByteLength, etag, checksumSha256);
|
|
2919
|
+
confirmedByteLength += expectedByteLength;
|
|
2920
|
+
confirmedPartCount += 1;
|
|
2921
|
+
emitProgress(validated.onProgress, "uploading", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
|
|
2922
|
+
}
|
|
2923
|
+
emitProgress(validated.onProgress, "completing", confirmedByteLength, validated.byteLength, confirmedPartCount, totalPartCount);
|
|
2924
|
+
return await completeWithReconciliation(controls, validated, session, digests);
|
|
2925
|
+
} catch (error) {
|
|
2926
|
+
if (validated.signal?.aborted && session) await bestEffortAbort(controls, validated.workspaceId, session.uploadId);
|
|
2927
|
+
if (error instanceof DriveError) throw error;
|
|
2928
|
+
throw validated.signal?.aborted ? new DriveError("aborted") : new DriveError("invalid_input");
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
function* pendingUploadPartNumbers(partCount, confirmedParts) {
|
|
2932
|
+
for (let partNumber = 1; partNumber <= partCount; partNumber += 1) if (!confirmedParts.has(partNumber)) yield partNumber;
|
|
2933
|
+
}
|
|
2934
|
+
async function readResumeState(controls, input, session, digests) {
|
|
2935
|
+
const confirmedParts = new Set();
|
|
2936
|
+
let confirmedByteLength = 0;
|
|
2937
|
+
let afterPartNumber = 0;
|
|
2938
|
+
let baseline;
|
|
2939
|
+
let baselineRequestId;
|
|
2940
|
+
let readyResult;
|
|
2941
|
+
for (let pageNumber = 0; pageNumber < STATUS_PAGE_MAXIMUM; pageNumber += 1) {
|
|
2942
|
+
const result = await controls.getUploadStatus({
|
|
2943
|
+
workspaceId: input.workspaceId,
|
|
2944
|
+
uploadId: session.uploadId,
|
|
2945
|
+
afterPartNumber,
|
|
2946
|
+
limit: STATUS_PAGE_LIMIT,
|
|
2947
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
2948
|
+
});
|
|
2949
|
+
const status = result.data;
|
|
2950
|
+
assertStatusMatchesSession(status, session);
|
|
2951
|
+
if (baseline) assertSameStatusSnapshot(status, baseline);
|
|
2952
|
+
else {
|
|
2953
|
+
baseline = status;
|
|
2954
|
+
baselineRequestId = result.requestId;
|
|
2955
|
+
}
|
|
2956
|
+
for (const part of status.confirmedParts) {
|
|
2957
|
+
const expectedChecksum = digests.partChecksums[part.partNumber - 1];
|
|
2958
|
+
if (!expectedChecksum || part.checksumSha256 !== expectedChecksum || confirmedParts.has(part.partNumber)) throw new DriveError("invalid_response", {
|
|
2959
|
+
status: result.status,
|
|
2960
|
+
requestId: result.requestId
|
|
2961
|
+
});
|
|
2962
|
+
confirmedParts.add(part.partNumber);
|
|
2963
|
+
confirmedByteLength += expectedPartByteLength(input.byteLength, part.partNumber);
|
|
2964
|
+
}
|
|
2965
|
+
if (status.lifecycle === "ready" && status.ready) {
|
|
2966
|
+
assertReadyMatchesInput(status.ready, session, input, digests, result.requestId);
|
|
2967
|
+
readyResult = resultFromStatus(result, status.ready);
|
|
2968
|
+
}
|
|
2969
|
+
if (status.nextAfterPartNumber === null) break;
|
|
2970
|
+
if (pageNumber === STATUS_PAGE_MAXIMUM - 1) throw new DriveError("invalid_response", {
|
|
2971
|
+
status: result.status,
|
|
2972
|
+
requestId: result.requestId
|
|
2973
|
+
});
|
|
2974
|
+
afterPartNumber = status.nextAfterPartNumber;
|
|
2975
|
+
}
|
|
2976
|
+
if (!baseline) throw new DriveError("invalid_response");
|
|
2977
|
+
if (session.mode === "presigned-multipart" && [
|
|
2978
|
+
"completing",
|
|
2979
|
+
"provider-completed",
|
|
2980
|
+
"ready"
|
|
2981
|
+
].includes(baseline.lifecycle) && confirmedParts.size !== session.partCount) throw new DriveError("invalid_response");
|
|
2982
|
+
failForTerminalStatus(baseline.lifecycle, baselineRequestId);
|
|
2983
|
+
return Object.freeze({
|
|
2984
|
+
revision: baseline.revision,
|
|
2985
|
+
confirmedParts,
|
|
2986
|
+
confirmedByteLength,
|
|
2987
|
+
lifecycle: baseline.lifecycle,
|
|
2988
|
+
...readyResult === void 0 ? {} : { readyResult }
|
|
2989
|
+
});
|
|
2990
|
+
}
|
|
2991
|
+
async function recordPartWithReconciliation(controls, input, session, partNumber, expectedUploadRevision, byteLength, etag, checksumSha256) {
|
|
2992
|
+
const record = (revision) => controls.recordUploadPart({
|
|
2993
|
+
workspaceId: input.workspaceId,
|
|
2994
|
+
uploadId: session.uploadId,
|
|
2995
|
+
partNumber,
|
|
2996
|
+
expectedUploadRevision: revision,
|
|
2997
|
+
byteLength,
|
|
2998
|
+
etag,
|
|
2999
|
+
checksumSha256,
|
|
3000
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
3001
|
+
});
|
|
3002
|
+
try {
|
|
3003
|
+
return (await record(expectedUploadRevision)).data.revision;
|
|
3004
|
+
} catch (error) {
|
|
3005
|
+
if (!isAmbiguousControlFailure(error) || input.signal?.aborted) throw error;
|
|
3006
|
+
const statusResult = await controls.getUploadStatus({
|
|
3007
|
+
workspaceId: input.workspaceId,
|
|
3008
|
+
uploadId: session.uploadId,
|
|
3009
|
+
afterPartNumber: partNumber - 1,
|
|
3010
|
+
limit: 1,
|
|
3011
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
3012
|
+
});
|
|
3013
|
+
const status = statusResult.data;
|
|
3014
|
+
assertStatusMatchesSession(status, session);
|
|
3015
|
+
failForTerminalStatus(status.lifecycle, statusResult.requestId);
|
|
3016
|
+
const confirmed = status.confirmedParts.find((part) => part.partNumber === partNumber);
|
|
3017
|
+
if (confirmed) {
|
|
3018
|
+
if (confirmed.checksumSha256 !== checksumSha256) throw new DriveError("invalid_response", {
|
|
3019
|
+
status: statusResult.status,
|
|
3020
|
+
requestId: statusResult.requestId
|
|
3021
|
+
});
|
|
3022
|
+
return status.revision;
|
|
3023
|
+
}
|
|
3024
|
+
if (status.lifecycle !== "uploading") throw new DriveError("precondition_failed");
|
|
3025
|
+
return (await record(status.revision)).data.revision;
|
|
3026
|
+
}
|
|
3027
|
+
}
|
|
3028
|
+
async function completeWithReconciliation(controls, input, session, digests) {
|
|
3029
|
+
try {
|
|
3030
|
+
const completed = await controls.completeUpload({
|
|
3031
|
+
workspaceId: input.workspaceId,
|
|
3032
|
+
uploadId: session.uploadId,
|
|
3033
|
+
idempotencyKey: input.completionIdempotencyKey,
|
|
3034
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
3035
|
+
});
|
|
3036
|
+
assertReadyMatchesInput(completed.data, session, input, digests, completed.requestId);
|
|
3037
|
+
return completed;
|
|
3038
|
+
} catch (error) {
|
|
3039
|
+
if (!isAmbiguousControlFailure(error) || input.signal?.aborted) throw error;
|
|
3040
|
+
const statusResult = await controls.getUploadStatus({
|
|
3041
|
+
workspaceId: input.workspaceId,
|
|
3042
|
+
uploadId: session.uploadId,
|
|
3043
|
+
afterPartNumber: 0,
|
|
3044
|
+
limit: 1,
|
|
3045
|
+
...input.signal === void 0 ? {} : { signal: input.signal }
|
|
3046
|
+
});
|
|
3047
|
+
const status = statusResult.data;
|
|
3048
|
+
assertStatusMatchesSession(status, session);
|
|
3049
|
+
if (status.lifecycle !== "ready" || !status.ready) throw error;
|
|
3050
|
+
assertReadyMatchesInput(status.ready, session, input, digests, statusResult.requestId);
|
|
3051
|
+
return resultFromStatus(statusResult, status.ready);
|
|
3052
|
+
}
|
|
3053
|
+
}
|
|
3054
|
+
async function hashSource(source, byteLength, partCount, signal) {
|
|
3055
|
+
const fullHash = sha256.create();
|
|
3056
|
+
const partChecksums = [];
|
|
3057
|
+
for (let index = 0; index < partCount; index += 1) {
|
|
3058
|
+
throwIfCallerAborted(signal);
|
|
3059
|
+
const start = index * UPLOAD_PART_BYTE_LENGTH;
|
|
3060
|
+
const end = Math.min(start + UPLOAD_PART_BYTE_LENGTH, byteLength);
|
|
3061
|
+
const part = slicePart(source, start, end, end - start);
|
|
3062
|
+
let buffer;
|
|
3063
|
+
try {
|
|
3064
|
+
buffer = signal ? await raceWithAbort(part.arrayBuffer(), signal) : await part.arrayBuffer();
|
|
3065
|
+
} catch (error) {
|
|
3066
|
+
if (error instanceof DriveError) throw error;
|
|
3067
|
+
throw signal?.aborted ? new DriveError("aborted") : new DriveError("invalid_input");
|
|
3068
|
+
}
|
|
3069
|
+
if (buffer.byteLength !== end - start) throw new DriveError("invalid_input");
|
|
3070
|
+
const bytes = new Uint8Array(buffer);
|
|
3071
|
+
fullHash.update(bytes);
|
|
3072
|
+
partChecksums.push(toBase64(sha256(bytes)));
|
|
3073
|
+
}
|
|
3074
|
+
return Object.freeze({
|
|
3075
|
+
callerDeclaredContentDigest: `sha256:${bytesToHex(fullHash.digest())}`,
|
|
3076
|
+
partChecksums: Object.freeze(partChecksums)
|
|
3077
|
+
});
|
|
3078
|
+
}
|
|
3079
|
+
async function putPart(runtime, descriptor, part, checksumSha256, callerSignal) {
|
|
3080
|
+
const remainingMilliseconds = descriptor.expiresAtEpochMilliseconds - Date.now();
|
|
3081
|
+
if (remainingMilliseconds < 1) throw new DriveError("invalid_response");
|
|
3082
|
+
const operation = createOperationSignal(callerSignal, Math.min(runtime.timeoutMilliseconds, remainingMilliseconds));
|
|
3083
|
+
let response;
|
|
3084
|
+
try {
|
|
3085
|
+
response = await raceWithAbort(runtime.fetchImplementation(descriptor.url, {
|
|
3086
|
+
method: descriptor.method,
|
|
3087
|
+
body: part,
|
|
3088
|
+
headers: descriptor.headers,
|
|
3089
|
+
credentials: "omit",
|
|
3090
|
+
cache: "no-store",
|
|
3091
|
+
redirect: "error",
|
|
3092
|
+
referrerPolicy: "no-referrer",
|
|
3093
|
+
signal: operation.signal
|
|
3094
|
+
}), operation.signal);
|
|
3095
|
+
if (!(response instanceof Response)) throw new DriveError("invalid_response");
|
|
3096
|
+
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 });
|
|
3099
|
+
return etag;
|
|
3100
|
+
} catch (error) {
|
|
3101
|
+
if (operation.didTimeout()) throw new DriveError("timeout");
|
|
3102
|
+
if (callerSignal?.aborted) throw new DriveError("aborted");
|
|
3103
|
+
if (error instanceof DriveError) throw error;
|
|
3104
|
+
throw new DriveError("network_error");
|
|
3105
|
+
} finally {
|
|
3106
|
+
operation.dispose();
|
|
3107
|
+
response?.body?.cancel().catch(() => {});
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
function assertSessionPolicy(session, byteLength, partCount, status, requestId) {
|
|
3111
|
+
const expectedMode = byteLength === 0 ? "server-mediated-zero-byte" : "presigned-multipart";
|
|
3112
|
+
if (session.mode !== expectedMode || session.partByteLength !== UPLOAD_PART_BYTE_LENGTH || session.partCount !== partCount || session.expiresAtEpochMilliseconds <= Date.now()) throw new DriveError("invalid_response", {
|
|
3113
|
+
status,
|
|
3114
|
+
requestId
|
|
3115
|
+
});
|
|
3116
|
+
}
|
|
3117
|
+
function assertStatusMatchesSession(status, session) {
|
|
3118
|
+
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");
|
|
3119
|
+
}
|
|
3120
|
+
function assertSameStatusSnapshot(status, baseline) {
|
|
3121
|
+
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");
|
|
3122
|
+
}
|
|
3123
|
+
function assertReadyMatchesInput(ready, session, input, digests, requestId) {
|
|
3124
|
+
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", {
|
|
3125
|
+
status: 200,
|
|
3126
|
+
requestId
|
|
3127
|
+
});
|
|
3128
|
+
}
|
|
3129
|
+
function failForTerminalStatus(lifecycle, requestId) {
|
|
3130
|
+
if (lifecycle === "initiating" || lifecycle === "recovery-required") throw new DriveError("upload_recovery_required", {
|
|
3131
|
+
status: 409,
|
|
3132
|
+
...requestId === void 0 ? {} : { requestId }
|
|
3133
|
+
});
|
|
3134
|
+
if (lifecycle === "aborting" || lifecycle === "aborted") throw new DriveError("precondition_failed", {
|
|
3135
|
+
status: 409,
|
|
3136
|
+
...requestId === void 0 ? {} : { requestId }
|
|
3137
|
+
});
|
|
3138
|
+
}
|
|
3139
|
+
function resultFromStatus(status, ready) {
|
|
3140
|
+
return Object.freeze({
|
|
3141
|
+
data: ready,
|
|
3142
|
+
status: status.status,
|
|
3143
|
+
requestId: status.requestId,
|
|
3144
|
+
validators: status.validators
|
|
3145
|
+
});
|
|
3146
|
+
}
|
|
3147
|
+
function expectedPartByteLength(byteLength, partNumber) {
|
|
3148
|
+
return Math.min(UPLOAD_PART_BYTE_LENGTH, byteLength - (partNumber - 1) * UPLOAD_PART_BYTE_LENGTH);
|
|
3149
|
+
}
|
|
3150
|
+
function slicePart(source, start, end, expectedByteLength) {
|
|
3151
|
+
try {
|
|
3152
|
+
const part = source.slice(start, end);
|
|
3153
|
+
if (!(part instanceof Blob) || part.size !== expectedByteLength) throw new DriveError("invalid_input");
|
|
3154
|
+
return part;
|
|
3155
|
+
} catch (error) {
|
|
3156
|
+
if (error instanceof DriveError) throw error;
|
|
3157
|
+
throw new DriveError("invalid_input");
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
function emitProgress(callback, phase, confirmedByteLength, totalByteLength, confirmedPartCount, totalPartCount) {
|
|
3161
|
+
if (!callback) return;
|
|
3162
|
+
const progress = Object.freeze({
|
|
3163
|
+
phase,
|
|
3164
|
+
confirmedByteLength,
|
|
3165
|
+
totalByteLength,
|
|
3166
|
+
confirmedPartCount,
|
|
3167
|
+
totalPartCount
|
|
3168
|
+
});
|
|
3169
|
+
try {
|
|
3170
|
+
callback(progress);
|
|
3171
|
+
} catch {}
|
|
3172
|
+
}
|
|
3173
|
+
async function bestEffortAbort(controls, workspaceId, uploadId) {
|
|
3174
|
+
const controller = new AbortController();
|
|
3175
|
+
const timeout = setTimeout(() => controller.abort(), ABORT_DEADLINE_MILLISECONDS);
|
|
3176
|
+
try {
|
|
3177
|
+
await controls.abortUpload({
|
|
3178
|
+
workspaceId,
|
|
3179
|
+
uploadId,
|
|
3180
|
+
signal: controller.signal
|
|
3181
|
+
});
|
|
3182
|
+
} catch {} finally {
|
|
3183
|
+
clearTimeout(timeout);
|
|
3184
|
+
}
|
|
3185
|
+
}
|
|
3186
|
+
function isAmbiguousControlFailure(value) {
|
|
3187
|
+
return value instanceof DriveError && (value.code === "network_error" || value.code === "timeout" || value.code === "invalid_response");
|
|
3188
|
+
}
|
|
3189
|
+
function throwIfCallerAborted(signal) {
|
|
3190
|
+
if (signal?.aborted) throw new DriveError("aborted");
|
|
3191
|
+
}
|
|
3192
|
+
function toBase64(bytes) {
|
|
3193
|
+
let binary = "";
|
|
3194
|
+
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
3195
|
+
return btoa(binary);
|
|
3196
|
+
}
|
|
3197
|
+
function isEtag(value) {
|
|
3198
|
+
return value !== null && value.length >= 1 && value.length <= 1024 && /^[\x20-\x7e]+$/.test(value);
|
|
1423
3199
|
}
|
|
1424
3200
|
//#endregion
|
|
1425
3201
|
//#region src/client.ts
|
|
1426
3202
|
function createDriveClient(config) {
|
|
1427
|
-
|
|
3203
|
+
const runtime = createClientRuntime(config);
|
|
3204
|
+
const operations = createDriveOperations(runtime);
|
|
3205
|
+
return Object.freeze({
|
|
3206
|
+
...operations,
|
|
3207
|
+
uploadFile: (input) => uploadFileInternal(runtime, input, operations)
|
|
3208
|
+
});
|
|
1428
3209
|
}
|
|
1429
3210
|
//#endregion
|
|
1430
3211
|
export { createDriveClient };
|