@finueva/drive 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +16 -12
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1160 -1067
- package/dist/contract.d.ts +395 -500
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1160 -1067
- package/dist/server.d.ts +2 -2
- package/dist/server.js +1160 -1067
- package/dist/types.d.ts +2 -2
- package/package.json +6 -6
package/dist/server.js
CHANGED
|
@@ -1,483 +1,257 @@
|
|
|
1
|
-
//#region
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
//#region src/core.ts
|
|
2
|
+
const DRIVE_API_ERROR_CODES = Object.freeze([
|
|
3
|
+
"authentication_required",
|
|
4
|
+
"identity_authority_unavailable",
|
|
5
|
+
"permission_denied",
|
|
6
|
+
"resource_not_found",
|
|
7
|
+
"invalid_request",
|
|
8
|
+
"invalid_pagination_cursor",
|
|
9
|
+
"invalid_idempotency_key",
|
|
10
|
+
"precondition_failed",
|
|
11
|
+
"idempotency_conflict",
|
|
12
|
+
"quota_exceeded",
|
|
13
|
+
"service_unavailable",
|
|
14
|
+
"internal_error"
|
|
15
|
+
]);
|
|
16
|
+
const DRIVE_API_ERROR_MESSAGES = Object.freeze({
|
|
17
|
+
authentication_required: "Authentication is required.",
|
|
18
|
+
identity_authority_unavailable: "Authentication is temporarily unavailable.",
|
|
19
|
+
permission_denied: "The requested action is not permitted.",
|
|
20
|
+
resource_not_found: "The requested resource was not found.",
|
|
21
|
+
invalid_request: "The request is invalid.",
|
|
22
|
+
invalid_pagination_cursor: "The pagination cursor is invalid.",
|
|
23
|
+
invalid_idempotency_key: "The idempotency key is invalid.",
|
|
24
|
+
precondition_failed: "The request precondition failed.",
|
|
25
|
+
idempotency_conflict: "The idempotency key conflicts with an earlier request.",
|
|
26
|
+
quota_exceeded: "The workspace storage quota would be exceeded.",
|
|
27
|
+
service_unavailable: "The service is temporarily unavailable.",
|
|
28
|
+
internal_error: "The request could not be completed."
|
|
29
|
+
});
|
|
30
|
+
const SDK_MESSAGES = Object.freeze({
|
|
31
|
+
invalid_input: "The Drive SDK input is invalid.",
|
|
32
|
+
credential_unavailable: "A Drive credential could not be obtained.",
|
|
33
|
+
network_error: "The Drive request could not reach the service.",
|
|
34
|
+
timeout: "The Drive request timed out.",
|
|
35
|
+
aborted: "The Drive request was aborted.",
|
|
36
|
+
invalid_response: "Drive returned an invalid response."
|
|
37
|
+
});
|
|
38
|
+
var DriveError = class extends Error {
|
|
39
|
+
code;
|
|
40
|
+
status;
|
|
41
|
+
requestId;
|
|
42
|
+
details;
|
|
43
|
+
constructor(code, options = {}) {
|
|
44
|
+
super(code in DRIVE_API_ERROR_MESSAGES ? DRIVE_API_ERROR_MESSAGES[code] : SDK_MESSAGES[code]);
|
|
45
|
+
this.name = "DriveError";
|
|
46
|
+
this.code = code;
|
|
47
|
+
this.status = options.status ?? null;
|
|
48
|
+
this.requestId = options.requestId ?? null;
|
|
49
|
+
this.details = Object.freeze({});
|
|
50
|
+
}
|
|
5
51
|
};
|
|
6
|
-
|
|
7
|
-
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/internal/client/response.ts
|
|
54
|
+
const ERROR_BODY_LIMIT = 16 * 1024;
|
|
55
|
+
const SUCCESS_BODY_LIMIT = 256 * 1024;
|
|
56
|
+
const RESPONSE_CHUNK_LIMIT = 256;
|
|
57
|
+
const RESPONSE_DEADLINE_MILLISECONDS = 5e3;
|
|
58
|
+
const REQUEST_ID = /^[A-Za-z0-9_-]{16,128}$/;
|
|
59
|
+
const COLLECTION_ETAG = /^"drive\.permission-collection\.v1\.(0|[1-9][0-9]*)"$/;
|
|
60
|
+
const GRANT_ETAG$1 = /^"drive\.permission-grant\.v1\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"$/;
|
|
61
|
+
const LIST_ETAG$1 = /^"drive\.permission-list\.v1\.[0-9a-f]{64}"$/;
|
|
62
|
+
async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes) {
|
|
63
|
+
const requestId = safeRequestId(response.headers.get("x-request-id"));
|
|
64
|
+
if (requestId === null) {
|
|
65
|
+
cancelResponse(response);
|
|
66
|
+
throw new DriveError("invalid_response", { status: response.status });
|
|
67
|
+
}
|
|
68
|
+
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes);
|
|
69
|
+
const { value } = await parseBoundedJson(response, SUCCESS_BODY_LIMIT, response.status, requestId, operationSignal);
|
|
70
|
+
const status = response.status;
|
|
71
|
+
if (!guard(value, status, response.headers)) throw new DriveError("invalid_response", {
|
|
72
|
+
status,
|
|
73
|
+
requestId
|
|
74
|
+
});
|
|
75
|
+
return Object.freeze({
|
|
76
|
+
data: value,
|
|
77
|
+
status,
|
|
78
|
+
requestId,
|
|
79
|
+
validators: readValidators(response.headers)
|
|
80
|
+
});
|
|
8
81
|
}
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
82
|
+
function parseCollectionEtag(value) {
|
|
83
|
+
const match = COLLECTION_ETAG.exec(value);
|
|
84
|
+
if (!match) return void 0;
|
|
85
|
+
const revision = Number(match[1]);
|
|
86
|
+
return Number.isSafeInteger(revision) ? revision : void 0;
|
|
87
|
+
}
|
|
88
|
+
function parseGrantEtag(value) {
|
|
89
|
+
const match = GRANT_ETAG$1.exec(value);
|
|
90
|
+
if (!match) return void 0;
|
|
91
|
+
const collectionRevision = Number(match[1]);
|
|
92
|
+
const grantRevision = Number(match[2]);
|
|
93
|
+
return Number.isSafeInteger(collectionRevision) && Number.isSafeInteger(grantRevision) ? [collectionRevision, grantRevision] : void 0;
|
|
94
|
+
}
|
|
95
|
+
async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
|
|
96
|
+
let parsed;
|
|
97
|
+
try {
|
|
98
|
+
parsed = await parseBoundedJson(response, ERROR_BODY_LIMIT, response.status, headerRequestId, signal);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (error instanceof DriveError && error.code === "aborted") return error;
|
|
101
|
+
return new DriveError("invalid_response", {
|
|
102
|
+
status: response.status,
|
|
103
|
+
requestId: headerRequestId
|
|
22
104
|
});
|
|
23
|
-
const pathSerializer = requestPathSerializer || globalPathSerializer || defaultPathSerializer;
|
|
24
|
-
const serializedBody = body === void 0 ? void 0 : bodySerializer(body, mergeHeaders(baseHeaders, headers, params.header));
|
|
25
|
-
const finalHeaders = mergeHeaders(serializedBody === void 0 || serializedBody instanceof FormData ? {} : { "Content-Type": "application/json" }, baseHeaders, headers, params.header);
|
|
26
|
-
const finalMiddlewares = [...globalMiddlewares, ...requestMiddlewares];
|
|
27
|
-
const requestInit = {
|
|
28
|
-
redirect: "follow",
|
|
29
|
-
...baseOptions,
|
|
30
|
-
...init,
|
|
31
|
-
body: serializedBody,
|
|
32
|
-
headers: finalHeaders
|
|
33
|
-
};
|
|
34
|
-
let id;
|
|
35
|
-
let options;
|
|
36
|
-
let request = new Request(createFinalURL(schemaPath, {
|
|
37
|
-
baseUrl: finalBaseUrl,
|
|
38
|
-
params,
|
|
39
|
-
querySerializer,
|
|
40
|
-
pathSerializer
|
|
41
|
-
}), requestInit);
|
|
42
|
-
let response;
|
|
43
|
-
for (const key in init) if (!(key in request)) request[key] = init[key];
|
|
44
|
-
if (finalMiddlewares.length) {
|
|
45
|
-
id = randomID();
|
|
46
|
-
options = Object.freeze({
|
|
47
|
-
baseUrl: finalBaseUrl,
|
|
48
|
-
fetch,
|
|
49
|
-
parseAs,
|
|
50
|
-
querySerializer,
|
|
51
|
-
bodySerializer,
|
|
52
|
-
pathSerializer
|
|
53
|
-
});
|
|
54
|
-
for (const m of finalMiddlewares) if (m && typeof m === "object" && typeof m.onRequest === "function") {
|
|
55
|
-
const result = await m.onRequest({
|
|
56
|
-
request,
|
|
57
|
-
schemaPath,
|
|
58
|
-
params,
|
|
59
|
-
options,
|
|
60
|
-
id
|
|
61
|
-
});
|
|
62
|
-
if (result) if (result instanceof Request) request = result;
|
|
63
|
-
else if (result instanceof Response) {
|
|
64
|
-
response = result;
|
|
65
|
-
break;
|
|
66
|
-
} else throw new Error("onRequest: must return new Request() or Response() when modifying the request");
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (!response) {
|
|
70
|
-
try {
|
|
71
|
-
response = await fetch(request, requestInitExt);
|
|
72
|
-
} catch (error2) {
|
|
73
|
-
let errorAfterMiddleware = error2;
|
|
74
|
-
if (finalMiddlewares.length) for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
75
|
-
const m = finalMiddlewares[i];
|
|
76
|
-
if (m && typeof m === "object" && typeof m.onError === "function") {
|
|
77
|
-
const result = await m.onError({
|
|
78
|
-
request,
|
|
79
|
-
error: errorAfterMiddleware,
|
|
80
|
-
schemaPath,
|
|
81
|
-
params,
|
|
82
|
-
options,
|
|
83
|
-
id
|
|
84
|
-
});
|
|
85
|
-
if (result) {
|
|
86
|
-
if (result instanceof Response) {
|
|
87
|
-
errorAfterMiddleware = void 0;
|
|
88
|
-
response = result;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
if (result instanceof Error) {
|
|
92
|
-
errorAfterMiddleware = result;
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
throw new Error("onError: must return new Response() or instance of Error");
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (errorAfterMiddleware) throw errorAfterMiddleware;
|
|
100
|
-
}
|
|
101
|
-
if (finalMiddlewares.length) for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
102
|
-
const m = finalMiddlewares[i];
|
|
103
|
-
if (m && typeof m === "object" && typeof m.onResponse === "function") {
|
|
104
|
-
const result = await m.onResponse({
|
|
105
|
-
request,
|
|
106
|
-
response,
|
|
107
|
-
schemaPath,
|
|
108
|
-
params,
|
|
109
|
-
options,
|
|
110
|
-
id
|
|
111
|
-
});
|
|
112
|
-
if (result) {
|
|
113
|
-
if (!(result instanceof Response)) throw new Error("onResponse: must return new Response() when modifying the response");
|
|
114
|
-
response = result;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
const contentLength = response.headers.get("Content-Length");
|
|
120
|
-
if (response.status === 204 || request.method === "HEAD" || contentLength === "0" && !response.headers.get("Transfer-Encoding")?.includes("chunked")) return response.ok ? {
|
|
121
|
-
data: void 0,
|
|
122
|
-
response
|
|
123
|
-
} : {
|
|
124
|
-
error: void 0,
|
|
125
|
-
response
|
|
126
|
-
};
|
|
127
|
-
if (response.ok) {
|
|
128
|
-
const getResponseData = async () => {
|
|
129
|
-
if (parseAs === "stream") return response.body;
|
|
130
|
-
if (parseAs === "json" && !contentLength) {
|
|
131
|
-
const raw = await response.text();
|
|
132
|
-
return raw ? JSON.parse(raw) : void 0;
|
|
133
|
-
}
|
|
134
|
-
return await response[parseAs]();
|
|
135
|
-
};
|
|
136
|
-
return {
|
|
137
|
-
data: await getResponseData(),
|
|
138
|
-
response
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
let error = await response.text();
|
|
142
|
-
try {
|
|
143
|
-
error = JSON.parse(error);
|
|
144
|
-
} catch {}
|
|
145
|
-
return {
|
|
146
|
-
error,
|
|
147
|
-
response
|
|
148
|
-
};
|
|
149
105
|
}
|
|
106
|
+
const value = parsed.value;
|
|
107
|
+
if (!isExactRecord$1(value, ["error"]) || !isExactRecord$1(value.error, [
|
|
108
|
+
"code",
|
|
109
|
+
"message",
|
|
110
|
+
"requestId",
|
|
111
|
+
"details"
|
|
112
|
+
])) return new DriveError("invalid_response", {
|
|
113
|
+
status: response.status,
|
|
114
|
+
requestId: headerRequestId
|
|
115
|
+
});
|
|
116
|
+
const envelope = value.error;
|
|
117
|
+
if (typeof envelope.code !== "string" || !DRIVE_API_ERROR_CODES.includes(envelope.code) || envelope.message !== DRIVE_API_ERROR_MESSAGES[envelope.code] || !REQUEST_ID.test(String(envelope.requestId)) || envelope.requestId !== headerRequestId || !isExactRecord$1(envelope.details, []) || !errorStatusMatches(envelope.code, response.status, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) || parsed.text !== JSON.stringify(value)) return new DriveError("invalid_response", {
|
|
118
|
+
status: response.status,
|
|
119
|
+
requestId: headerRequestId
|
|
120
|
+
});
|
|
121
|
+
return new DriveError(envelope.code, {
|
|
122
|
+
status: response.status,
|
|
123
|
+
requestId: envelope.requestId
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
|
|
127
|
+
if (allowedErrorCodes && !allowedErrorCodes.includes(code)) return false;
|
|
128
|
+
if (code === "quota_exceeded" && !allowsQuotaExceeded) return false;
|
|
150
129
|
return {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
...init,
|
|
196
|
-
method: "PATCH"
|
|
197
|
-
});
|
|
198
|
-
},
|
|
199
|
-
TRACE(url, init) {
|
|
200
|
-
return coreFetch(url, {
|
|
201
|
-
...init,
|
|
202
|
-
method: "TRACE"
|
|
130
|
+
authentication_required: [401],
|
|
131
|
+
identity_authority_unavailable: [503],
|
|
132
|
+
permission_denied: [403],
|
|
133
|
+
resource_not_found: [404],
|
|
134
|
+
invalid_request: [422],
|
|
135
|
+
invalid_pagination_cursor: [422],
|
|
136
|
+
invalid_idempotency_key: [422],
|
|
137
|
+
precondition_failed: preconditionStatus === null ? [] : [preconditionStatus],
|
|
138
|
+
idempotency_conflict: [409],
|
|
139
|
+
quota_exceeded: [409],
|
|
140
|
+
service_unavailable: [503],
|
|
141
|
+
internal_error: [500]
|
|
142
|
+
}[code].includes(status);
|
|
143
|
+
}
|
|
144
|
+
async function parseBoundedJson(response, maximumBytes, status, requestId, signal) {
|
|
145
|
+
if (!response.body) throw new DriveError("invalid_response", {
|
|
146
|
+
status,
|
|
147
|
+
requestId
|
|
148
|
+
});
|
|
149
|
+
const reader = response.body.getReader();
|
|
150
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
151
|
+
let size = 0;
|
|
152
|
+
let chunks = 0;
|
|
153
|
+
let text = "";
|
|
154
|
+
const contentLength = response.headers.get("content-length");
|
|
155
|
+
if (contentLength !== null && (!/^(?:0|[1-9][0-9]*)$/.test(contentLength) || Number(contentLength) > maximumBytes)) {
|
|
156
|
+
reader.cancel().catch(() => {});
|
|
157
|
+
throw new DriveError("invalid_response", {
|
|
158
|
+
status,
|
|
159
|
+
requestId
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
const deadline = new AbortController();
|
|
163
|
+
const timeout = setTimeout(() => deadline.abort(), RESPONSE_DEADLINE_MILLISECONDS);
|
|
164
|
+
try {
|
|
165
|
+
while (true) {
|
|
166
|
+
if (signal?.aborted) throw new DriveError("aborted");
|
|
167
|
+
const { done, value } = await readResponseChunk(reader, signal, deadline.signal);
|
|
168
|
+
if (done) break;
|
|
169
|
+
chunks += 1;
|
|
170
|
+
size += value.byteLength;
|
|
171
|
+
if (chunks > RESPONSE_CHUNK_LIMIT || size > maximumBytes) throw new DriveError("invalid_response", {
|
|
172
|
+
status,
|
|
173
|
+
requestId
|
|
203
174
|
});
|
|
204
|
-
|
|
205
|
-
use(...middleware) {
|
|
206
|
-
for (const m of middleware) {
|
|
207
|
-
if (!m) continue;
|
|
208
|
-
if (typeof m !== "object" || !("onRequest" in m || "onResponse" in m || "onError" in m)) throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
|
|
209
|
-
globalMiddlewares.push(m);
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
eject(...middleware) {
|
|
213
|
-
for (const m of middleware) {
|
|
214
|
-
const i = globalMiddlewares.indexOf(m);
|
|
215
|
-
if (i !== -1) globalMiddlewares.splice(i, 1);
|
|
216
|
-
}
|
|
175
|
+
text += decoder.decode(value, { stream: true });
|
|
217
176
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const values = [];
|
|
228
|
-
const joiner = {
|
|
229
|
-
simple: ",",
|
|
230
|
-
label: ".",
|
|
231
|
-
matrix: ";"
|
|
232
|
-
}[options.style] || "&";
|
|
233
|
-
if (options.style !== "deepObject" && options.explode === false) {
|
|
234
|
-
for (const k in value) values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k]));
|
|
235
|
-
const final2 = values.join(",");
|
|
236
|
-
switch (options.style) {
|
|
237
|
-
case "form": return `${name}=${final2}`;
|
|
238
|
-
case "label": return `.${final2}`;
|
|
239
|
-
case "matrix": return `;${name}=${final2}`;
|
|
240
|
-
default: return final2;
|
|
177
|
+
text += decoder.decode();
|
|
178
|
+
return {
|
|
179
|
+
value: JSON.parse(text),
|
|
180
|
+
text
|
|
181
|
+
};
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error instanceof DriveError) {
|
|
184
|
+
if (error.code === "aborted" || signal?.aborted) throw new DriveError("aborted");
|
|
185
|
+
throw error;
|
|
241
186
|
}
|
|
187
|
+
throw new DriveError("invalid_response", {
|
|
188
|
+
status,
|
|
189
|
+
requestId
|
|
190
|
+
});
|
|
191
|
+
} finally {
|
|
192
|
+
clearTimeout(timeout);
|
|
193
|
+
reader.cancel().catch(() => {});
|
|
242
194
|
}
|
|
243
|
-
for (const k in value) {
|
|
244
|
-
const finalName = options.style === "deepObject" ? `${name}[${k}]` : k;
|
|
245
|
-
values.push(serializePrimitiveParam(finalName, value[k], options));
|
|
246
|
-
}
|
|
247
|
-
const final = values.join(joiner);
|
|
248
|
-
return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
|
|
249
195
|
}
|
|
250
|
-
function
|
|
251
|
-
if (
|
|
252
|
-
if (
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
196
|
+
async function readResponseChunk(reader, operationSignal, deadlineSignal) {
|
|
197
|
+
if (operationSignal?.aborted) throw new DriveError("aborted");
|
|
198
|
+
if (deadlineSignal.aborted) throw new DriveError("invalid_response");
|
|
199
|
+
let removeOperationAbort = () => {};
|
|
200
|
+
let removeDeadlineAbort = () => {};
|
|
201
|
+
const operationAbort = new Promise((_, reject) => {
|
|
202
|
+
if (!operationSignal) return;
|
|
203
|
+
const onAbort = () => reject(new DriveError("aborted"));
|
|
204
|
+
operationSignal.addEventListener("abort", onAbort, { once: true });
|
|
205
|
+
removeOperationAbort = () => operationSignal.removeEventListener("abort", onAbort);
|
|
206
|
+
});
|
|
207
|
+
const deadlineAbort = new Promise((_, reject) => {
|
|
208
|
+
const onAbort = () => reject(new DriveError("invalid_response"));
|
|
209
|
+
deadlineSignal.addEventListener("abort", onAbort, { once: true });
|
|
210
|
+
removeDeadlineAbort = () => deadlineSignal.removeEventListener("abort", onAbort);
|
|
211
|
+
});
|
|
212
|
+
try {
|
|
213
|
+
return await Promise.race([
|
|
214
|
+
reader.read(),
|
|
215
|
+
operationAbort,
|
|
216
|
+
deadlineAbort
|
|
217
|
+
]);
|
|
218
|
+
} finally {
|
|
219
|
+
removeOperationAbort();
|
|
220
|
+
removeDeadlineAbort();
|
|
265
221
|
}
|
|
266
|
-
const joiner = {
|
|
267
|
-
simple: ",",
|
|
268
|
-
label: ".",
|
|
269
|
-
matrix: ";"
|
|
270
|
-
}[options.style] || "&";
|
|
271
|
-
const values = [];
|
|
272
|
-
for (const v of value) if (options.style === "simple" || options.style === "label") values.push(options.allowReserved === true ? v : encodeURIComponent(v));
|
|
273
|
-
else values.push(serializePrimitiveParam(name, v, options));
|
|
274
|
-
return options.style === "label" || options.style === "matrix" ? `${joiner}${values.join(joiner)}` : values.join(joiner);
|
|
275
222
|
}
|
|
276
|
-
function
|
|
277
|
-
|
|
278
|
-
const search = [];
|
|
279
|
-
if (queryParams && typeof queryParams === "object") for (const name in queryParams) {
|
|
280
|
-
const value = queryParams[name];
|
|
281
|
-
if (value === void 0 || value === null) continue;
|
|
282
|
-
if (Array.isArray(value)) {
|
|
283
|
-
if (value.length === 0) continue;
|
|
284
|
-
search.push(serializeArrayParam(name, value, {
|
|
285
|
-
style: "form",
|
|
286
|
-
explode: true,
|
|
287
|
-
...options?.array,
|
|
288
|
-
allowReserved: options?.allowReserved || false
|
|
289
|
-
}));
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
if (typeof value === "object") {
|
|
293
|
-
search.push(serializeObjectParam(name, value, {
|
|
294
|
-
style: "deepObject",
|
|
295
|
-
explode: true,
|
|
296
|
-
...options?.object,
|
|
297
|
-
allowReserved: options?.allowReserved || false
|
|
298
|
-
}));
|
|
299
|
-
continue;
|
|
300
|
-
}
|
|
301
|
-
search.push(serializePrimitiveParam(name, value, options));
|
|
302
|
-
}
|
|
303
|
-
return search.join("&");
|
|
304
|
-
};
|
|
223
|
+
function cancelResponse(response) {
|
|
224
|
+
response.body?.cancel().catch(() => {});
|
|
305
225
|
}
|
|
306
|
-
function
|
|
307
|
-
|
|
308
|
-
for (const match of pathname.match(PATH_PARAM_RE) ?? []) {
|
|
309
|
-
let name = match.substring(1, match.length - 1);
|
|
310
|
-
let explode = false;
|
|
311
|
-
let style = "simple";
|
|
312
|
-
if (name.endsWith("*")) {
|
|
313
|
-
explode = true;
|
|
314
|
-
name = name.substring(0, name.length - 1);
|
|
315
|
-
}
|
|
316
|
-
if (name.startsWith(".")) {
|
|
317
|
-
style = "label";
|
|
318
|
-
name = name.substring(1);
|
|
319
|
-
} else if (name.startsWith(";")) {
|
|
320
|
-
style = "matrix";
|
|
321
|
-
name = name.substring(1);
|
|
322
|
-
}
|
|
323
|
-
if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) continue;
|
|
324
|
-
const value = pathParams[name];
|
|
325
|
-
if (Array.isArray(value)) {
|
|
326
|
-
nextURL = nextURL.replace(match, serializeArrayParam(name, value, {
|
|
327
|
-
style,
|
|
328
|
-
explode
|
|
329
|
-
}));
|
|
330
|
-
continue;
|
|
331
|
-
}
|
|
332
|
-
if (typeof value === "object") {
|
|
333
|
-
nextURL = nextURL.replace(match, serializeObjectParam(name, value, {
|
|
334
|
-
style,
|
|
335
|
-
explode
|
|
336
|
-
}));
|
|
337
|
-
continue;
|
|
338
|
-
}
|
|
339
|
-
if (style === "matrix") {
|
|
340
|
-
nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);
|
|
341
|
-
continue;
|
|
342
|
-
}
|
|
343
|
-
nextURL = nextURL.replace(match, style === "label" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));
|
|
344
|
-
}
|
|
345
|
-
return nextURL;
|
|
346
|
-
}
|
|
347
|
-
function defaultBodySerializer(body, headers) {
|
|
348
|
-
if (body instanceof FormData) return body;
|
|
349
|
-
if (headers) {
|
|
350
|
-
if ((headers.get instanceof Function ? headers.get("Content-Type") ?? headers.get("content-type") : headers["Content-Type"] ?? headers["content-type"]) === "application/x-www-form-urlencoded") return new URLSearchParams(body).toString();
|
|
351
|
-
}
|
|
352
|
-
return JSON.stringify(body);
|
|
353
|
-
}
|
|
354
|
-
function createFinalURL(pathname, options) {
|
|
355
|
-
let finalURL = `${options.baseUrl}${pathname}`;
|
|
356
|
-
if (options.params?.path) finalURL = options.pathSerializer(finalURL, options.params.path);
|
|
357
|
-
let search = options.querySerializer(options.params.query ?? {});
|
|
358
|
-
if (search.startsWith("?")) search = search.substring(1);
|
|
359
|
-
if (search) finalURL += `?${search}`;
|
|
360
|
-
return finalURL;
|
|
361
|
-
}
|
|
362
|
-
function mergeHeaders(...allHeaders) {
|
|
363
|
-
const finalHeaders = new Headers();
|
|
364
|
-
for (const h of allHeaders) {
|
|
365
|
-
if (!h || typeof h !== "object") continue;
|
|
366
|
-
const iterator = h instanceof Headers ? h.entries() : Object.entries(h);
|
|
367
|
-
for (const [k, v] of iterator) if (v === null) finalHeaders.delete(k);
|
|
368
|
-
else if (Array.isArray(v)) for (const v2 of v) finalHeaders.append(k, v2);
|
|
369
|
-
else if (v !== void 0) finalHeaders.set(k, v);
|
|
370
|
-
}
|
|
371
|
-
return finalHeaders;
|
|
372
|
-
}
|
|
373
|
-
function removeTrailingSlash(url) {
|
|
374
|
-
if (url.endsWith("/")) return url.substring(0, url.length - 1);
|
|
375
|
-
return url;
|
|
376
|
-
}
|
|
377
|
-
String.fromCharCode;
|
|
378
|
-
const TRAILING_SLASH_RE = /\/$|\/\?|\/#/;
|
|
379
|
-
const JOIN_LEADING_SLASH_RE = /^\.?\//;
|
|
380
|
-
function hasTrailingSlash(input = "", respectQueryAndFragment) {
|
|
381
|
-
if (!respectQueryAndFragment) return input.endsWith("/");
|
|
382
|
-
return TRAILING_SLASH_RE.test(input);
|
|
383
|
-
}
|
|
384
|
-
function withTrailingSlash(input = "", respectQueryAndFragment) {
|
|
385
|
-
if (!respectQueryAndFragment) return input.endsWith("/") ? input : input + "/";
|
|
386
|
-
if (hasTrailingSlash(input, true)) return input || "/";
|
|
387
|
-
let path = input;
|
|
388
|
-
let fragment = "";
|
|
389
|
-
const fragmentIndex = input.indexOf("#");
|
|
390
|
-
if (fragmentIndex !== -1) {
|
|
391
|
-
path = input.slice(0, fragmentIndex);
|
|
392
|
-
fragment = input.slice(fragmentIndex);
|
|
393
|
-
if (!path) return fragment;
|
|
394
|
-
}
|
|
395
|
-
const [s0, ...s] = path.split("?");
|
|
396
|
-
return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
226
|
+
function safeRequestId(value) {
|
|
227
|
+
return value !== null && REQUEST_ID.test(value) ? value : null;
|
|
397
228
|
}
|
|
398
|
-
function
|
|
399
|
-
|
|
229
|
+
function readValidators(headers) {
|
|
230
|
+
const etag = headers.get("etag");
|
|
231
|
+
const permissionCollectionEtag = headers.get("drive-permission-collection-etag");
|
|
232
|
+
const permissionGrantEtag = headers.get("drive-permission-grant-etag");
|
|
233
|
+
return Object.freeze({
|
|
234
|
+
...etag !== null && LIST_ETAG$1.test(etag) ? { etag } : {},
|
|
235
|
+
...permissionCollectionEtag !== null && parseCollectionEtag(permissionCollectionEtag) !== void 0 ? { permissionCollectionEtag } : {},
|
|
236
|
+
...permissionGrantEtag !== null && parseGrantEtag(permissionGrantEtag) !== void 0 ? { permissionGrantEtag } : {}
|
|
237
|
+
});
|
|
400
238
|
}
|
|
401
|
-
function
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
|
|
405
|
-
url = withTrailingSlash(url) + _segment;
|
|
406
|
-
} else url = segment;
|
|
407
|
-
return url;
|
|
239
|
+
function isExactRecord$1(value, keys) {
|
|
240
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
241
|
+
return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
408
242
|
}
|
|
409
243
|
//#endregion
|
|
410
|
-
//#region src/
|
|
411
|
-
const
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
"invalid_idempotency_key",
|
|
419
|
-
"precondition_failed",
|
|
420
|
-
"idempotency_conflict",
|
|
421
|
-
"quota_exceeded",
|
|
422
|
-
"service_unavailable",
|
|
423
|
-
"internal_error"
|
|
424
|
-
]);
|
|
425
|
-
const DRIVE_API_ERROR_MESSAGES = Object.freeze({
|
|
426
|
-
authentication_required: "Authentication is required.",
|
|
427
|
-
identity_authority_unavailable: "Authentication is temporarily unavailable.",
|
|
428
|
-
permission_denied: "The requested action is not permitted.",
|
|
429
|
-
resource_not_found: "The requested resource was not found.",
|
|
430
|
-
invalid_request: "The request is invalid.",
|
|
431
|
-
invalid_pagination_cursor: "The pagination cursor is invalid.",
|
|
432
|
-
invalid_idempotency_key: "The idempotency key is invalid.",
|
|
433
|
-
precondition_failed: "The request precondition failed.",
|
|
434
|
-
idempotency_conflict: "The idempotency key conflicts with an earlier request.",
|
|
435
|
-
quota_exceeded: "The workspace storage quota would be exceeded.",
|
|
436
|
-
service_unavailable: "The service is temporarily unavailable.",
|
|
437
|
-
internal_error: "The request could not be completed."
|
|
438
|
-
});
|
|
439
|
-
const SDK_MESSAGES = Object.freeze({
|
|
440
|
-
invalid_input: "The Drive SDK input is invalid.",
|
|
441
|
-
credential_unavailable: "A Drive credential could not be obtained.",
|
|
442
|
-
network_error: "The Drive request could not reach the service.",
|
|
443
|
-
timeout: "The Drive request timed out.",
|
|
444
|
-
aborted: "The Drive request was aborted.",
|
|
445
|
-
invalid_response: "Drive returned an invalid response."
|
|
446
|
-
});
|
|
447
|
-
var DriveError = class extends Error {
|
|
448
|
-
code;
|
|
449
|
-
status;
|
|
450
|
-
requestId;
|
|
451
|
-
details;
|
|
452
|
-
constructor(code, options = {}) {
|
|
453
|
-
super(code in DRIVE_API_ERROR_MESSAGES ? DRIVE_API_ERROR_MESSAGES[code] : SDK_MESSAGES[code]);
|
|
454
|
-
this.name = "DriveError";
|
|
455
|
-
this.code = code;
|
|
456
|
-
this.status = options.status ?? null;
|
|
457
|
-
this.requestId = options.requestId ?? null;
|
|
458
|
-
this.details = Object.freeze({});
|
|
459
|
-
}
|
|
460
|
-
};
|
|
461
|
-
//#endregion
|
|
462
|
-
//#region src/internal/client.ts
|
|
463
|
-
const ERROR_BODY_LIMIT = 16 * 1024;
|
|
464
|
-
const SUCCESS_BODY_LIMIT = 256 * 1024;
|
|
465
|
-
const RESPONSE_CHUNK_LIMIT = 256;
|
|
466
|
-
const RESPONSE_DEADLINE_MILLISECONDS = 5e3;
|
|
467
|
-
const DEFAULT_REQUEST_TIMEOUT_MILLISECONDS = 3e4;
|
|
468
|
-
const MAX_REQUEST_TIMEOUT_MILLISECONDS = 12e4;
|
|
469
|
-
const REQUEST_ID = /^[A-Za-z0-9_-]{16,128}$/;
|
|
470
|
-
const COLLECTION_ETAG = /^"drive\.permission-collection\.v1\.(0|[1-9][0-9]*)"$/;
|
|
244
|
+
//#region src/internal/client/guards.ts
|
|
245
|
+
const ITEM_ID$1 = /^drive\.item\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
246
|
+
const WORKSPACE_ID$1 = /^drive\.workspace\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
247
|
+
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
|
+
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
|
+
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}$/;
|
|
250
|
+
const CURSOR$1 = /^drive\.cursor\.v1\.[A-Za-z0-9_-]+$/;
|
|
251
|
+
const AUTH_ID$1 = /^[A-Za-z0-9_-]{1,128}$/;
|
|
471
252
|
const GRANT_ETAG = /^"drive\.permission-grant\.v1\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"$/;
|
|
472
253
|
const LIST_ETAG = /^"drive\.permission-list\.v1\.[0-9a-f]{64}"$/;
|
|
473
|
-
const
|
|
474
|
-
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}$/;
|
|
475
|
-
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}$/;
|
|
476
|
-
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}$/;
|
|
477
|
-
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}$/;
|
|
478
|
-
const CURSOR = /^drive\.cursor\.v1\.[A-Za-z0-9_-]+$/;
|
|
479
|
-
const AUTH_ID = /^[A-Za-z0-9_-]{1,128}$/;
|
|
480
|
-
const PERMISSION_ACTIONS = Object.freeze([
|
|
254
|
+
const PERMISSION_ACTIONS$1 = Object.freeze([
|
|
481
255
|
"items:content:read",
|
|
482
256
|
"items:create",
|
|
483
257
|
"items:delete",
|
|
@@ -494,280 +268,199 @@ const EFFECTIVE_ACTIONS = Object.freeze([
|
|
|
494
268
|
"items:permissions:read",
|
|
495
269
|
"items:update"
|
|
496
270
|
]);
|
|
497
|
-
const
|
|
498
|
-
const MAX_UPLOAD_BYTE_LENGTH = 33554432e4;
|
|
271
|
+
const MAX_UPLOAD_BYTE_LENGTH$1 = 33554432e4;
|
|
499
272
|
const UPLOAD_QUOTA_EXPIRY_MILLISECONDS = 864e5;
|
|
500
|
-
function
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
} catch {
|
|
510
|
-
throw new DriveError("invalid_input");
|
|
511
|
-
}
|
|
512
|
-
if (typeof runtime.fetchImplementation !== "function" || typeof runtime.getCredential !== "function") throw new DriveError("invalid_input");
|
|
513
|
-
return Object.freeze({
|
|
514
|
-
listFolderChildren: (input) => listFolderChildren(runtime, input),
|
|
515
|
-
createFolder: (input) => createFolder(runtime, input),
|
|
516
|
-
listItemPermissions: (input) => listItemPermissions(runtime, input),
|
|
517
|
-
readEffectiveItemPermissions: (input) => readEffectiveItemPermissions(runtime, input),
|
|
518
|
-
createItemPermission: (input) => createItemPermission(runtime, input),
|
|
519
|
-
updateItemPermission: (input) => updateItemPermission(runtime, input),
|
|
520
|
-
revokeItemPermission: (input) => revokeItemPermission(runtime, input),
|
|
521
|
-
createUpload: (input) => createUpload(runtime, input),
|
|
522
|
-
abortUpload: (input) => abortUpload(runtime, input)
|
|
523
|
-
});
|
|
273
|
+
function isCurrentWorkspace(value) {
|
|
274
|
+
if (!isExactRecord(value, [
|
|
275
|
+
"workspaceId",
|
|
276
|
+
"rootVolumeId",
|
|
277
|
+
"rootItemId",
|
|
278
|
+
"workspaceReference"
|
|
279
|
+
]) || typeof value.workspaceId !== "string" || !WORKSPACE_ID$1.test(value.workspaceId) || typeof value.rootVolumeId !== "string" || !VOLUME_ID.test(value.rootVolumeId) || typeof value.rootItemId !== "string" || !ITEM_ID$1.test(value.rootItemId)) return false;
|
|
280
|
+
const reference = value.workspaceReference;
|
|
281
|
+
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);
|
|
524
282
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
return
|
|
528
|
-
...operationOptions("listFolderChildren", { params: {
|
|
529
|
-
path: resourcePath(validated),
|
|
530
|
-
query: pageQuery(validated)
|
|
531
|
-
} }),
|
|
532
|
-
...requestOptions
|
|
533
|
-
}), [200], (value) => isFolderPage(value, validated.workspaceId, validated.itemId));
|
|
283
|
+
function isFolderPage(value, workspaceId, parentItemId) {
|
|
284
|
+
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
|
+
return value.items.every((item) => item.workspaceId === workspaceId && item.parentItemId === parentItemId) && isStrictlyOrdered(value.items, (item) => item.itemId);
|
|
534
286
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
}), [200, 201], (value) => isFolderItem(value) && value.workspaceId === validated.workspaceId && value.parentItemId === validated.itemId && value.kind === "folder" && value.name === validated.name);
|
|
287
|
+
function isFolderItem(value) {
|
|
288
|
+
return isExactRecord(value, [
|
|
289
|
+
"workspaceId",
|
|
290
|
+
"volumeId",
|
|
291
|
+
"itemId",
|
|
292
|
+
"parentItemId",
|
|
293
|
+
"kind",
|
|
294
|
+
"name",
|
|
295
|
+
"visibility",
|
|
296
|
+
"revision"
|
|
297
|
+
]) && 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);
|
|
547
298
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
299
|
+
function isPermissionPage(value, headers, targetItemId) {
|
|
300
|
+
if (!(isExactRecord(value, [
|
|
301
|
+
"items",
|
|
302
|
+
"nextCursor",
|
|
303
|
+
"collectionRevision",
|
|
304
|
+
"collectionEtag"
|
|
305
|
+
]) && Array.isArray(value.items) && value.items.length <= 50 && value.items.every(isPermissionGrant) && (value.nextCursor === null || typeof value.nextCursor === "string" && value.nextCursor.length <= 699 && CURSOR$1.test(value.nextCursor)) && isSafeInteger$1(value.collectionRevision) && typeof value.collectionEtag === "string" && parseCollectionEtag(value.collectionEtag) === value.collectionRevision)) return false;
|
|
306
|
+
const collectionHeader = headers.get("drive-permission-collection-etag");
|
|
307
|
+
const representationEtag = headers.get("etag");
|
|
308
|
+
const collectionRevision = value.collectionRevision;
|
|
309
|
+
if (!isSafeInteger$1(collectionRevision)) return false;
|
|
310
|
+
return collectionHeader === value.collectionEtag && representationEtag !== null && LIST_ETAG.test(representationEtag) && value.items.every((grant) => (grant.source === "direct" ? grant.sourceItemId === targetItemId : grant.sourceItemId !== targetItemId) && grant.etag === permissionGrantEtag(collectionRevision, grant.revision)) && isStrictlyOrdered(value.items, (grant) => `${grant.sourceItemId}\0${grant.grantId}`);
|
|
557
311
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
312
|
+
function isPermissionMutation(value, targetItemId, expectedGrantId) {
|
|
313
|
+
if (!isExactRecord(value, [
|
|
314
|
+
"outcome",
|
|
315
|
+
"grant",
|
|
316
|
+
"collectionRevision"
|
|
317
|
+
]) || value.outcome !== "committed" && value.outcome !== "replayed" || !isSafeInteger$1(value.collectionRevision)) return false;
|
|
318
|
+
const grant = value.grant;
|
|
319
|
+
return isExactRecord(grant, [
|
|
320
|
+
"source",
|
|
321
|
+
"sourceItemId",
|
|
322
|
+
"grantId",
|
|
323
|
+
"grantee",
|
|
324
|
+
"actions",
|
|
325
|
+
"availability",
|
|
326
|
+
"expiresAtEpochMilliseconds",
|
|
327
|
+
"revision"
|
|
328
|
+
]) && grant.source === "direct" && typeof grant.sourceItemId === "string" && grant.sourceItemId === targetItemId && typeof grant.grantId === "string" && GRANT_ID$1.test(grant.grantId) && (expectedGrantId === void 0 || grant.grantId === expectedGrantId) && isGrantee(grant.grantee) && isPermissionActions(grant.actions) && [
|
|
329
|
+
"active",
|
|
330
|
+
"expired",
|
|
331
|
+
"revoked"
|
|
332
|
+
].includes(String(grant.availability)) && (grant.expiresAtEpochMilliseconds === null || isSafeInteger$1(grant.expiresAtEpochMilliseconds)) && isSafeInteger$1(grant.revision);
|
|
564
333
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
}), [200, 201], (value, status, headers) => isPermissionMutation(value, validated.itemId) && (status === 201 && value.outcome === "committed" || status === 200 && value.outcome === "replayed") && (status === 200 || value.grant.availability !== "revoked") && mutationValidatorsAreCoherent(headers));
|
|
334
|
+
function isEffectivePermissionResponse(value, targetItemId) {
|
|
335
|
+
if (!isExactRecord(value, ["actions"]) || !Array.isArray(value.actions) || value.actions.length !== 7) return false;
|
|
336
|
+
for (let index = 0; index < value.actions.length; index += 1) {
|
|
337
|
+
const action = value.actions[index];
|
|
338
|
+
if (action === void 0 || !isExactRecord(action, [
|
|
339
|
+
"action",
|
|
340
|
+
"allowed",
|
|
341
|
+
"basis",
|
|
342
|
+
"sourceItemId",
|
|
343
|
+
"grantId"
|
|
344
|
+
]) || action.action !== EFFECTIVE_ACTIONS[index] || typeof action.allowed !== "boolean" || !(action.basis === null || [
|
|
345
|
+
"workspace_visibility",
|
|
346
|
+
"restricted_administrator_bypass",
|
|
347
|
+
"direct_grant",
|
|
348
|
+
"inherited_grant"
|
|
349
|
+
].includes(String(action.basis))) || !(action.sourceItemId === null || typeof action.sourceItemId === "string" && ITEM_ID$1.test(action.sourceItemId)) || !(action.grantId === null || typeof action.grantId === "string" && GRANT_ID$1.test(action.grantId)) || !effectiveSourceIsCoherent(action, targetItemId)) return false;
|
|
350
|
+
}
|
|
351
|
+
return true;
|
|
584
352
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
header: {
|
|
598
|
-
"Idempotency-Key": validated.idempotencyKey,
|
|
599
|
-
"If-Match": validated.ifMatch
|
|
600
|
-
}
|
|
601
|
-
},
|
|
602
|
-
body
|
|
603
|
-
}),
|
|
604
|
-
...requestOptions
|
|
605
|
-
}), [200], (value, _status, headers) => isPermissionMutation(value, validated.itemId, validated.grantId) && value.grant.availability !== "revoked" && mutationValidatorsAreCoherent(headers));
|
|
353
|
+
function isUploadQuotaReservation(value) {
|
|
354
|
+
return isExactRecord(value, [
|
|
355
|
+
"workspaceId",
|
|
356
|
+
"uploadId",
|
|
357
|
+
"parentItemId",
|
|
358
|
+
"expectedByteLength",
|
|
359
|
+
"state",
|
|
360
|
+
"terminalReason",
|
|
361
|
+
"createdAtEpochMilliseconds",
|
|
362
|
+
"expiresAtEpochMilliseconds",
|
|
363
|
+
"terminalAtEpochMilliseconds"
|
|
364
|
+
]) && typeof value.workspaceId === "string" && WORKSPACE_ID$1.test(value.workspaceId) && typeof value.uploadId === "string" && UPLOAD_ID$1.test(value.uploadId) && typeof value.parentItemId === "string" && ITEM_ID$1.test(value.parentItemId) && typeof value.expectedByteLength === "number" && Number.isSafeInteger(value.expectedByteLength) && value.expectedByteLength >= 0 && value.expectedByteLength <= MAX_UPLOAD_BYTE_LENGTH$1 && (value.state === "reserved" || value.state === "converted" || value.state === "released") && (value.terminalReason === null || value.terminalReason === "completed" || value.terminalReason === "aborted" || value.terminalReason === "failed" || value.terminalReason === "expired") && isSafeInteger$1(value.createdAtEpochMilliseconds) && isSafeInteger$1(value.expiresAtEpochMilliseconds) && value.expiresAtEpochMilliseconds - value.createdAtEpochMilliseconds === UPLOAD_QUOTA_EXPIRY_MILLISECONDS && (value.terminalAtEpochMilliseconds === null || isSafeInteger$1(value.terminalAtEpochMilliseconds) && value.terminalAtEpochMilliseconds >= value.createdAtEpochMilliseconds);
|
|
606
365
|
}
|
|
607
|
-
|
|
608
|
-
const
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
header: {
|
|
616
|
-
"Idempotency-Key": validated.idempotencyKey,
|
|
617
|
-
"If-Match": validated.ifMatch
|
|
618
|
-
}
|
|
619
|
-
} }),
|
|
620
|
-
...requestOptions
|
|
621
|
-
}), [200], (value, _status, headers) => isPermissionMutation(value, validated.itemId, validated.grantId) && value.grant.availability === "revoked" && parseCollectionEtag(headers.get("drive-permission-collection-etag") ?? "") !== void 0 && headers.get("drive-permission-grant-etag") === null);
|
|
366
|
+
function mutationValidatorsAreCoherent(headers) {
|
|
367
|
+
const collection = headers.get("drive-permission-collection-etag");
|
|
368
|
+
const grant = headers.get("drive-permission-grant-etag");
|
|
369
|
+
const collectionRevision = collection === null ? void 0 : parseCollectionEtag(collection);
|
|
370
|
+
if (collectionRevision === void 0) return false;
|
|
371
|
+
if (grant === null) return true;
|
|
372
|
+
const currentGrant = parseGrantEtag(grant);
|
|
373
|
+
return currentGrant !== void 0 && currentGrant[0] === collectionRevision;
|
|
622
374
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
375
|
+
function isPermissionGrant(value) {
|
|
376
|
+
return isExactRecord(value, [
|
|
377
|
+
"source",
|
|
378
|
+
"sourceItemId",
|
|
379
|
+
"grantId",
|
|
380
|
+
"grantee",
|
|
381
|
+
"actions",
|
|
382
|
+
"availability",
|
|
383
|
+
"expiresAtEpochMilliseconds",
|
|
384
|
+
"revision",
|
|
385
|
+
"etag"
|
|
386
|
+
]) && (value.source === "direct" || value.source === "inherited") && typeof value.sourceItemId === "string" && ITEM_ID$1.test(value.sourceItemId) && typeof value.grantId === "string" && GRANT_ID$1.test(value.grantId) && isGrantee(value.grantee) && isPermissionActions(value.actions) && [
|
|
387
|
+
"active",
|
|
388
|
+
"expired",
|
|
389
|
+
"revoked"
|
|
390
|
+
].includes(String(value.availability)) && (value.expiresAtEpochMilliseconds === null || isSafeInteger$1(value.expiresAtEpochMilliseconds)) && isSafeInteger$1(value.revision) && typeof value.etag === "string" && GRANT_ETAG.test(value.etag);
|
|
638
391
|
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.DELETE("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}", {
|
|
642
|
-
...operationOptions("abortUpload", { params: { path: {
|
|
643
|
-
workspaceId: validated.workspaceId,
|
|
644
|
-
uploadId: validated.uploadId
|
|
645
|
-
} } }),
|
|
646
|
-
...requestOptions
|
|
647
|
-
}), [200], (value) => isUploadQuotaReservation(value) && value.workspaceId === validated.workspaceId && value.uploadId === validated.uploadId && value.state === "released" && value.terminalReason === "aborted" && value.terminalAtEpochMilliseconds !== null);
|
|
392
|
+
function isGrantee(value) {
|
|
393
|
+
return isExactRecord(value, ["type", "userId"]) && value.type === "user" && typeof value.userId === "string" && AUTH_ID$1.test(value.userId) || isExactRecord(value, ["type", "teamId"]) && value.type === "team" && typeof value.teamId === "string" && AUTH_ID$1.test(value.teamId);
|
|
648
394
|
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
try {
|
|
652
|
-
const operationSignal = operation.signal;
|
|
653
|
-
throwIfAborted(operationSignal);
|
|
654
|
-
const credential = await obtainCredential(runtime.getCredential, operationSignal);
|
|
655
|
-
let capturedResponse;
|
|
656
|
-
await send(createClient({
|
|
657
|
-
baseUrl: runtime.baseUrl,
|
|
658
|
-
fetch: async (request) => {
|
|
659
|
-
try {
|
|
660
|
-
const response = await raceWithAbort(runtime.fetchImplementation(request), operationSignal);
|
|
661
|
-
if (!(response instanceof Response)) throw new DriveError("invalid_response");
|
|
662
|
-
capturedResponse = response;
|
|
663
|
-
} catch (error) {
|
|
664
|
-
if (error instanceof DriveError) throw error;
|
|
665
|
-
throw operationSignal.aborted ? new DriveError("aborted") : new DriveError("network_error");
|
|
666
|
-
}
|
|
667
|
-
return new Response(null, { status: 204 });
|
|
668
|
-
}
|
|
669
|
-
}), {
|
|
670
|
-
cache: "no-store",
|
|
671
|
-
credentials: "omit",
|
|
672
|
-
headers: new Headers({ authorization: `Bearer ${credential}` }),
|
|
673
|
-
signal: operationSignal
|
|
674
|
-
});
|
|
675
|
-
if (!capturedResponse) throw new DriveError("network_error");
|
|
676
|
-
const response = capturedResponse;
|
|
677
|
-
const requestId = safeRequestId(response.headers.get("x-request-id"));
|
|
678
|
-
if (requestId === null) {
|
|
679
|
-
cancelResponse(response);
|
|
680
|
-
throw new DriveError("invalid_response", { status: response.status });
|
|
681
|
-
}
|
|
682
|
-
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded);
|
|
683
|
-
const { value } = await parseBoundedJson(response, SUCCESS_BODY_LIMIT, response.status, requestId, operationSignal);
|
|
684
|
-
const status = response.status;
|
|
685
|
-
if (!guard(value, status, response.headers)) throw new DriveError("invalid_response", {
|
|
686
|
-
status,
|
|
687
|
-
requestId
|
|
688
|
-
});
|
|
689
|
-
return Object.freeze({
|
|
690
|
-
data: value,
|
|
691
|
-
status,
|
|
692
|
-
requestId,
|
|
693
|
-
validators: readValidators(response.headers)
|
|
694
|
-
});
|
|
695
|
-
} catch (error) {
|
|
696
|
-
if (operation.didTimeout()) throw new DriveError("timeout");
|
|
697
|
-
if (error instanceof DriveError) throw error;
|
|
698
|
-
throw operation.signal.aborted ? new DriveError("aborted") : new DriveError("network_error");
|
|
699
|
-
} finally {
|
|
700
|
-
operation.dispose();
|
|
701
|
-
}
|
|
395
|
+
function isPermissionActions(value) {
|
|
396
|
+
return Array.isArray(value) && value.length >= 1 && value.length <= 6 && new Set(value).size === value.length && value.every((action) => PERMISSION_ACTIONS$1.includes(action)) && value.every((action, index) => index === 0 || PERMISSION_ACTIONS$1.indexOf(action) > PERMISSION_ACTIONS$1.indexOf(value[index - 1]));
|
|
702
397
|
}
|
|
703
|
-
function
|
|
704
|
-
if (
|
|
705
|
-
if (
|
|
706
|
-
return
|
|
398
|
+
function effectiveSourceIsCoherent(action, targetItemId) {
|
|
399
|
+
if (!action.allowed) return action.basis === null && action.sourceItemId === null && action.grantId === null;
|
|
400
|
+
if (action.basis === "workspace_visibility" || action.basis === "restricted_administrator_bypass") return action.sourceItemId === null && action.grantId === null;
|
|
401
|
+
if (action.basis === "direct_grant") return action.sourceItemId === targetItemId && typeof action.grantId === "string";
|
|
402
|
+
if (action.basis === "inherited_grant") return typeof action.sourceItemId === "string" && action.sourceItemId !== targetItemId && typeof action.grantId === "string";
|
|
403
|
+
return false;
|
|
707
404
|
}
|
|
708
|
-
function
|
|
709
|
-
|
|
710
|
-
let timedOut = false;
|
|
711
|
-
const onAbort = () => controller.abort();
|
|
712
|
-
if (callerSignal?.aborted) controller.abort();
|
|
713
|
-
else callerSignal?.addEventListener("abort", onAbort, { once: true });
|
|
714
|
-
const timeout = setTimeout(() => {
|
|
715
|
-
timedOut = true;
|
|
716
|
-
controller.abort();
|
|
717
|
-
}, timeoutMilliseconds);
|
|
718
|
-
return {
|
|
719
|
-
signal: controller.signal,
|
|
720
|
-
didTimeout: () => timedOut,
|
|
721
|
-
dispose: () => {
|
|
722
|
-
clearTimeout(timeout);
|
|
723
|
-
callerSignal?.removeEventListener("abort", onAbort);
|
|
724
|
-
}
|
|
725
|
-
};
|
|
405
|
+
function permissionGrantEtag(collectionRevision, grantRevision) {
|
|
406
|
+
return `"drive.permission-grant.v1.${collectionRevision}.${grantRevision}"`;
|
|
726
407
|
}
|
|
727
|
-
function
|
|
728
|
-
if (typeof value !== "string"
|
|
729
|
-
let
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
408
|
+
function isSafeFilename$1(value) {
|
|
409
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 510 || value.normalize("NFC") !== value || value.endsWith(".") || value.endsWith(" ") || filenameIsReserved$1(value)) return false;
|
|
410
|
+
let codePoints = 0;
|
|
411
|
+
let bytes = 0;
|
|
412
|
+
for (const character of value) {
|
|
413
|
+
const point = character.codePointAt(0);
|
|
414
|
+
if (point === void 0 || point === 47 || point === 92 || point <= 31 || point >= 127 && point <= 159 || point === 8232 || point === 8233 || point >= 55296 && point <= 57343) return false;
|
|
415
|
+
codePoints += 1;
|
|
416
|
+
bytes += point <= 127 ? 1 : point <= 2047 ? 2 : point <= 65535 ? 3 : 4;
|
|
417
|
+
if (codePoints > 255 || bytes > 255) return false;
|
|
734
418
|
}
|
|
735
|
-
|
|
736
|
-
"localhost",
|
|
737
|
-
"127.0.0.1",
|
|
738
|
-
"[::1]"
|
|
739
|
-
].includes(url.hostname);
|
|
740
|
-
if (url.protocol !== "https:" && !localHttp || url.username || url.password || url.search || url.hash || !url.host) throw new TypeError("Drive base URL is invalid");
|
|
741
|
-
return joinURL(url.origin, url.pathname);
|
|
419
|
+
return true;
|
|
742
420
|
}
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
421
|
+
function filenameIsReserved$1(value) {
|
|
422
|
+
const base = value.split(".", 1)[0].toUpperCase();
|
|
423
|
+
return value === "." || value === ".." || [
|
|
424
|
+
"CON",
|
|
425
|
+
"PRN",
|
|
426
|
+
"AUX",
|
|
427
|
+
"NUL",
|
|
428
|
+
"CLOCK$",
|
|
429
|
+
"CONIN$",
|
|
430
|
+
"CONOUT$"
|
|
431
|
+
].includes(base) || /^COM[1-9]$/.test(base) || /^LPT[1-9]$/.test(base);
|
|
754
432
|
}
|
|
755
|
-
function
|
|
756
|
-
|
|
433
|
+
function isStrictlyOrdered(values, key) {
|
|
434
|
+
return values.every((value, index) => index === 0 || key(values[index - 1]) < key(value));
|
|
757
435
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
436
|
+
function isSafeInteger$1(value) {
|
|
437
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
438
|
+
}
|
|
439
|
+
function isExactRecord(value, keys) {
|
|
440
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
441
|
+
return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
442
|
+
}
|
|
443
|
+
//#endregion
|
|
444
|
+
//#region src/internal/client/request.ts
|
|
445
|
+
const ITEM_ID = /^drive\.item\.[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
446
|
+
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
|
+
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
|
+
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}$/;
|
|
449
|
+
const CURSOR = /^drive\.cursor\.v1\.[A-Za-z0-9_-]+$/;
|
|
450
|
+
const AUTH_ID = /^[A-Za-z0-9_-]{1,128}$/;
|
|
451
|
+
const PERMISSION_ACTIONS = Object.freeze([
|
|
452
|
+
"items:content:read",
|
|
453
|
+
"items:create",
|
|
454
|
+
"items:delete",
|
|
455
|
+
"items:metadata:read",
|
|
456
|
+
"items:permissions:read",
|
|
457
|
+
"items:update"
|
|
458
|
+
]);
|
|
459
|
+
const IDEMPOTENCY_KEY = /^[A-Za-z0-9_-]{16,128}$/;
|
|
460
|
+
const MAX_UPLOAD_BYTE_LENGTH = 33554432e4;
|
|
461
|
+
function validateCurrentWorkspaceInput(value) {
|
|
462
|
+
const signal = validateSignal(captureRecord(value === void 0 ? {} : value, [], ["signal"]).signal);
|
|
463
|
+
return signal === void 0 ? {} : { signal };
|
|
771
464
|
}
|
|
772
465
|
function validateResourceInput(value) {
|
|
773
466
|
const input = captureRecord(value, ["workspaceId", "itemId"], ["signal"]);
|
|
@@ -925,6 +618,21 @@ function validateAbortUploadInput(value) {
|
|
|
925
618
|
...signal === void 0 ? {} : { signal }
|
|
926
619
|
};
|
|
927
620
|
}
|
|
621
|
+
function resourcePath(input) {
|
|
622
|
+
return {
|
|
623
|
+
workspaceId: input.workspaceId,
|
|
624
|
+
itemId: input.itemId
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
function pageQuery(input) {
|
|
628
|
+
return {
|
|
629
|
+
...input.limit === void 0 ? {} : { limit: input.limit },
|
|
630
|
+
...input.cursor === void 0 ? {} : { cursor: input.cursor }
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
function operationOptions(_operationId, options) {
|
|
634
|
+
return options;
|
|
635
|
+
}
|
|
928
636
|
function captureRecord(value, required, optional) {
|
|
929
637
|
try {
|
|
930
638
|
if (typeof value !== "object" && typeof value !== "function" || value === null || Array.isArray(value)) throw new DriveError("invalid_input");
|
|
@@ -939,394 +647,779 @@ function captureRecord(value, required, optional) {
|
|
|
939
647
|
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) throw new DriveError("invalid_input");
|
|
940
648
|
result[key] = descriptor.value;
|
|
941
649
|
}
|
|
942
|
-
return result;
|
|
943
|
-
} catch (error) {
|
|
944
|
-
if (error instanceof DriveError) throw error;
|
|
945
|
-
throw new DriveError("invalid_input");
|
|
946
|
-
}
|
|
650
|
+
return result;
|
|
651
|
+
} catch (error) {
|
|
652
|
+
if (error instanceof DriveError) throw error;
|
|
653
|
+
throw new DriveError("invalid_input");
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
function validateSignal(value) {
|
|
657
|
+
if (value === void 0) return void 0;
|
|
658
|
+
if (!(value instanceof AbortSignal)) throw new DriveError("invalid_input");
|
|
659
|
+
return value;
|
|
660
|
+
}
|
|
661
|
+
function validateGrantee(value) {
|
|
662
|
+
const type = captureRecord(value, ["type"], ["userId", "teamId"]);
|
|
663
|
+
if (type.type === "user") {
|
|
664
|
+
const user = captureRecord(value, ["type", "userId"], []);
|
|
665
|
+
if (typeof user.userId === "string" && AUTH_ID.test(user.userId)) return {
|
|
666
|
+
type: "user",
|
|
667
|
+
userId: user.userId
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
if (type.type === "team") {
|
|
671
|
+
const team = captureRecord(value, ["type", "teamId"], []);
|
|
672
|
+
if (typeof team.teamId === "string" && AUTH_ID.test(team.teamId)) return {
|
|
673
|
+
type: "team",
|
|
674
|
+
teamId: team.teamId
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
throw new DriveError("invalid_input");
|
|
678
|
+
}
|
|
679
|
+
function validateInputActions(value) {
|
|
680
|
+
const actions = captureArray(value);
|
|
681
|
+
if (actions.length < 1 || actions.length > PERMISSION_ACTIONS.length || new Set(actions).size !== actions.length || !actions.every((action) => PERMISSION_ACTIONS.includes(action))) throw new DriveError("invalid_input");
|
|
682
|
+
return actions;
|
|
683
|
+
}
|
|
684
|
+
function captureArray(value) {
|
|
685
|
+
try {
|
|
686
|
+
if (!Array.isArray(value)) throw new DriveError("invalid_input");
|
|
687
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
688
|
+
if (Reflect.ownKeys(descriptors).some((key) => typeof key !== "string")) throw new DriveError("invalid_input");
|
|
689
|
+
const result = [];
|
|
690
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
691
|
+
const descriptor = descriptors[String(index)];
|
|
692
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) throw new DriveError("invalid_input");
|
|
693
|
+
result.push(descriptor.value);
|
|
694
|
+
}
|
|
695
|
+
if (Reflect.ownKeys(descriptors).length !== value.length + 1) throw new DriveError("invalid_input");
|
|
696
|
+
return result;
|
|
697
|
+
} catch (error) {
|
|
698
|
+
if (error instanceof DriveError) throw error;
|
|
699
|
+
throw new DriveError("invalid_input");
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
function isIdempotencyKey(value) {
|
|
703
|
+
return typeof value === "string" && IDEMPOTENCY_KEY.test(value);
|
|
704
|
+
}
|
|
705
|
+
function isExpiry(value) {
|
|
706
|
+
return value === null || isSafeInteger(value);
|
|
707
|
+
}
|
|
708
|
+
function isSafeFilename(value) {
|
|
709
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 510 || value.normalize("NFC") !== value || value.endsWith(".") || value.endsWith(" ") || filenameIsReserved(value)) return false;
|
|
710
|
+
let codePoints = 0;
|
|
711
|
+
let bytes = 0;
|
|
712
|
+
for (const character of value) {
|
|
713
|
+
const point = character.codePointAt(0);
|
|
714
|
+
if (point === void 0 || point === 47 || point === 92 || point <= 31 || point >= 127 && point <= 159 || point === 8232 || point === 8233 || point >= 55296 && point <= 57343) return false;
|
|
715
|
+
codePoints += 1;
|
|
716
|
+
bytes += point <= 127 ? 1 : point <= 2047 ? 2 : point <= 65535 ? 3 : 4;
|
|
717
|
+
if (codePoints > 255 || bytes > 255) return false;
|
|
718
|
+
}
|
|
719
|
+
return true;
|
|
720
|
+
}
|
|
721
|
+
function filenameIsReserved(value) {
|
|
722
|
+
const base = value.split(".", 1)[0].toUpperCase();
|
|
723
|
+
return value === "." || value === ".." || [
|
|
724
|
+
"CON",
|
|
725
|
+
"PRN",
|
|
726
|
+
"AUX",
|
|
727
|
+
"NUL",
|
|
728
|
+
"CLOCK$",
|
|
729
|
+
"CONIN$",
|
|
730
|
+
"CONOUT$"
|
|
731
|
+
].includes(base) || /^COM[1-9]$/.test(base) || /^LPT[1-9]$/.test(base);
|
|
732
|
+
}
|
|
733
|
+
function isSafeInteger(value) {
|
|
734
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
735
|
+
}
|
|
736
|
+
//#endregion
|
|
737
|
+
//#region ../../node_modules/.pnpm/openapi-fetch@0.17.0/node_modules/openapi-fetch/dist/index.mjs
|
|
738
|
+
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
739
|
+
const supportsRequestInitExt = () => {
|
|
740
|
+
return typeof process === "object" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;
|
|
741
|
+
};
|
|
742
|
+
function randomID() {
|
|
743
|
+
return Math.random().toString(36).slice(2, 11);
|
|
744
|
+
}
|
|
745
|
+
function createClient(clientOptions) {
|
|
746
|
+
let { baseUrl = "", Request: CustomRequest = globalThis.Request, fetch: baseFetch = globalThis.fetch, querySerializer: globalQuerySerializer, bodySerializer: globalBodySerializer, pathSerializer: globalPathSerializer, headers: baseHeaders, requestInitExt = void 0, ...baseOptions } = { ...clientOptions };
|
|
747
|
+
requestInitExt = supportsRequestInitExt() ? requestInitExt : void 0;
|
|
748
|
+
baseUrl = removeTrailingSlash(baseUrl);
|
|
749
|
+
const globalMiddlewares = [];
|
|
750
|
+
async function coreFetch(schemaPath, fetchOptions) {
|
|
751
|
+
const { baseUrl: localBaseUrl, fetch = baseFetch, Request = CustomRequest, headers, params = {}, parseAs = "json", querySerializer: requestQuerySerializer, bodySerializer = globalBodySerializer ?? defaultBodySerializer, pathSerializer: requestPathSerializer, body, middleware: requestMiddlewares = [], ...init } = fetchOptions || {};
|
|
752
|
+
let finalBaseUrl = baseUrl;
|
|
753
|
+
if (localBaseUrl) finalBaseUrl = removeTrailingSlash(localBaseUrl) ?? baseUrl;
|
|
754
|
+
let querySerializer = typeof globalQuerySerializer === "function" ? globalQuerySerializer : createQuerySerializer(globalQuerySerializer);
|
|
755
|
+
if (requestQuerySerializer) querySerializer = typeof requestQuerySerializer === "function" ? requestQuerySerializer : createQuerySerializer({
|
|
756
|
+
...typeof globalQuerySerializer === "object" ? globalQuerySerializer : {},
|
|
757
|
+
...requestQuerySerializer
|
|
758
|
+
});
|
|
759
|
+
const pathSerializer = requestPathSerializer || globalPathSerializer || defaultPathSerializer;
|
|
760
|
+
const serializedBody = body === void 0 ? void 0 : bodySerializer(body, mergeHeaders(baseHeaders, headers, params.header));
|
|
761
|
+
const finalHeaders = mergeHeaders(serializedBody === void 0 || serializedBody instanceof FormData ? {} : { "Content-Type": "application/json" }, baseHeaders, headers, params.header);
|
|
762
|
+
const finalMiddlewares = [...globalMiddlewares, ...requestMiddlewares];
|
|
763
|
+
const requestInit = {
|
|
764
|
+
redirect: "follow",
|
|
765
|
+
...baseOptions,
|
|
766
|
+
...init,
|
|
767
|
+
body: serializedBody,
|
|
768
|
+
headers: finalHeaders
|
|
769
|
+
};
|
|
770
|
+
let id;
|
|
771
|
+
let options;
|
|
772
|
+
let request = new Request(createFinalURL(schemaPath, {
|
|
773
|
+
baseUrl: finalBaseUrl,
|
|
774
|
+
params,
|
|
775
|
+
querySerializer,
|
|
776
|
+
pathSerializer
|
|
777
|
+
}), requestInit);
|
|
778
|
+
let response;
|
|
779
|
+
for (const key in init) if (!(key in request)) request[key] = init[key];
|
|
780
|
+
if (finalMiddlewares.length) {
|
|
781
|
+
id = randomID();
|
|
782
|
+
options = Object.freeze({
|
|
783
|
+
baseUrl: finalBaseUrl,
|
|
784
|
+
fetch,
|
|
785
|
+
parseAs,
|
|
786
|
+
querySerializer,
|
|
787
|
+
bodySerializer,
|
|
788
|
+
pathSerializer
|
|
789
|
+
});
|
|
790
|
+
for (const m of finalMiddlewares) if (m && typeof m === "object" && typeof m.onRequest === "function") {
|
|
791
|
+
const result = await m.onRequest({
|
|
792
|
+
request,
|
|
793
|
+
schemaPath,
|
|
794
|
+
params,
|
|
795
|
+
options,
|
|
796
|
+
id
|
|
797
|
+
});
|
|
798
|
+
if (result) if (result instanceof Request) request = result;
|
|
799
|
+
else if (result instanceof Response) {
|
|
800
|
+
response = result;
|
|
801
|
+
break;
|
|
802
|
+
} else throw new Error("onRequest: must return new Request() or Response() when modifying the request");
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
if (!response) {
|
|
806
|
+
try {
|
|
807
|
+
response = await fetch(request, requestInitExt);
|
|
808
|
+
} catch (error2) {
|
|
809
|
+
let errorAfterMiddleware = error2;
|
|
810
|
+
if (finalMiddlewares.length) for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
811
|
+
const m = finalMiddlewares[i];
|
|
812
|
+
if (m && typeof m === "object" && typeof m.onError === "function") {
|
|
813
|
+
const result = await m.onError({
|
|
814
|
+
request,
|
|
815
|
+
error: errorAfterMiddleware,
|
|
816
|
+
schemaPath,
|
|
817
|
+
params,
|
|
818
|
+
options,
|
|
819
|
+
id
|
|
820
|
+
});
|
|
821
|
+
if (result) {
|
|
822
|
+
if (result instanceof Response) {
|
|
823
|
+
errorAfterMiddleware = void 0;
|
|
824
|
+
response = result;
|
|
825
|
+
break;
|
|
826
|
+
}
|
|
827
|
+
if (result instanceof Error) {
|
|
828
|
+
errorAfterMiddleware = result;
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
throw new Error("onError: must return new Response() or instance of Error");
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
if (errorAfterMiddleware) throw errorAfterMiddleware;
|
|
836
|
+
}
|
|
837
|
+
if (finalMiddlewares.length) for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
|
|
838
|
+
const m = finalMiddlewares[i];
|
|
839
|
+
if (m && typeof m === "object" && typeof m.onResponse === "function") {
|
|
840
|
+
const result = await m.onResponse({
|
|
841
|
+
request,
|
|
842
|
+
response,
|
|
843
|
+
schemaPath,
|
|
844
|
+
params,
|
|
845
|
+
options,
|
|
846
|
+
id
|
|
847
|
+
});
|
|
848
|
+
if (result) {
|
|
849
|
+
if (!(result instanceof Response)) throw new Error("onResponse: must return new Response() when modifying the response");
|
|
850
|
+
response = result;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
const contentLength = response.headers.get("Content-Length");
|
|
856
|
+
if (response.status === 204 || request.method === "HEAD" || contentLength === "0" && !response.headers.get("Transfer-Encoding")?.includes("chunked")) return response.ok ? {
|
|
857
|
+
data: void 0,
|
|
858
|
+
response
|
|
859
|
+
} : {
|
|
860
|
+
error: void 0,
|
|
861
|
+
response
|
|
862
|
+
};
|
|
863
|
+
if (response.ok) {
|
|
864
|
+
const getResponseData = async () => {
|
|
865
|
+
if (parseAs === "stream") return response.body;
|
|
866
|
+
if (parseAs === "json" && !contentLength) {
|
|
867
|
+
const raw = await response.text();
|
|
868
|
+
return raw ? JSON.parse(raw) : void 0;
|
|
869
|
+
}
|
|
870
|
+
return await response[parseAs]();
|
|
871
|
+
};
|
|
872
|
+
return {
|
|
873
|
+
data: await getResponseData(),
|
|
874
|
+
response
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
let error = await response.text();
|
|
878
|
+
try {
|
|
879
|
+
error = JSON.parse(error);
|
|
880
|
+
} catch {}
|
|
881
|
+
return {
|
|
882
|
+
error,
|
|
883
|
+
response
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
return {
|
|
887
|
+
request(method, url, init) {
|
|
888
|
+
return coreFetch(url, {
|
|
889
|
+
...init,
|
|
890
|
+
method: method.toUpperCase()
|
|
891
|
+
});
|
|
892
|
+
},
|
|
893
|
+
GET(url, init) {
|
|
894
|
+
return coreFetch(url, {
|
|
895
|
+
...init,
|
|
896
|
+
method: "GET"
|
|
897
|
+
});
|
|
898
|
+
},
|
|
899
|
+
PUT(url, init) {
|
|
900
|
+
return coreFetch(url, {
|
|
901
|
+
...init,
|
|
902
|
+
method: "PUT"
|
|
903
|
+
});
|
|
904
|
+
},
|
|
905
|
+
POST(url, init) {
|
|
906
|
+
return coreFetch(url, {
|
|
907
|
+
...init,
|
|
908
|
+
method: "POST"
|
|
909
|
+
});
|
|
910
|
+
},
|
|
911
|
+
DELETE(url, init) {
|
|
912
|
+
return coreFetch(url, {
|
|
913
|
+
...init,
|
|
914
|
+
method: "DELETE"
|
|
915
|
+
});
|
|
916
|
+
},
|
|
917
|
+
OPTIONS(url, init) {
|
|
918
|
+
return coreFetch(url, {
|
|
919
|
+
...init,
|
|
920
|
+
method: "OPTIONS"
|
|
921
|
+
});
|
|
922
|
+
},
|
|
923
|
+
HEAD(url, init) {
|
|
924
|
+
return coreFetch(url, {
|
|
925
|
+
...init,
|
|
926
|
+
method: "HEAD"
|
|
927
|
+
});
|
|
928
|
+
},
|
|
929
|
+
PATCH(url, init) {
|
|
930
|
+
return coreFetch(url, {
|
|
931
|
+
...init,
|
|
932
|
+
method: "PATCH"
|
|
933
|
+
});
|
|
934
|
+
},
|
|
935
|
+
TRACE(url, init) {
|
|
936
|
+
return coreFetch(url, {
|
|
937
|
+
...init,
|
|
938
|
+
method: "TRACE"
|
|
939
|
+
});
|
|
940
|
+
},
|
|
941
|
+
use(...middleware) {
|
|
942
|
+
for (const m of middleware) {
|
|
943
|
+
if (!m) continue;
|
|
944
|
+
if (typeof m !== "object" || !("onRequest" in m || "onResponse" in m || "onError" in m)) throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
|
|
945
|
+
globalMiddlewares.push(m);
|
|
946
|
+
}
|
|
947
|
+
},
|
|
948
|
+
eject(...middleware) {
|
|
949
|
+
for (const m of middleware) {
|
|
950
|
+
const i = globalMiddlewares.indexOf(m);
|
|
951
|
+
if (i !== -1) globalMiddlewares.splice(i, 1);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
};
|
|
947
955
|
}
|
|
948
|
-
function
|
|
949
|
-
if (value === void 0) return
|
|
950
|
-
if (
|
|
951
|
-
return value
|
|
956
|
+
function serializePrimitiveParam(name, value, options) {
|
|
957
|
+
if (value === void 0 || value === null) return "";
|
|
958
|
+
if (typeof value === "object") throw new Error("Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.");
|
|
959
|
+
return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;
|
|
952
960
|
}
|
|
953
|
-
function
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
+
function serializeObjectParam(name, value, options) {
|
|
962
|
+
if (!value || typeof value !== "object") return "";
|
|
963
|
+
const values = [];
|
|
964
|
+
const joiner = {
|
|
965
|
+
simple: ",",
|
|
966
|
+
label: ".",
|
|
967
|
+
matrix: ";"
|
|
968
|
+
}[options.style] || "&";
|
|
969
|
+
if (options.style !== "deepObject" && options.explode === false) {
|
|
970
|
+
for (const k in value) values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k]));
|
|
971
|
+
const final2 = values.join(",");
|
|
972
|
+
switch (options.style) {
|
|
973
|
+
case "form": return `${name}=${final2}`;
|
|
974
|
+
case "label": return `.${final2}`;
|
|
975
|
+
case "matrix": return `;${name}=${final2}`;
|
|
976
|
+
default: return final2;
|
|
977
|
+
}
|
|
961
978
|
}
|
|
962
|
-
|
|
963
|
-
const
|
|
964
|
-
|
|
965
|
-
type: "team",
|
|
966
|
-
teamId: team.teamId
|
|
967
|
-
};
|
|
979
|
+
for (const k in value) {
|
|
980
|
+
const finalName = options.style === "deepObject" ? `${name}[${k}]` : k;
|
|
981
|
+
values.push(serializePrimitiveParam(finalName, value[k], options));
|
|
968
982
|
}
|
|
969
|
-
|
|
970
|
-
}
|
|
971
|
-
function validateInputActions(value) {
|
|
972
|
-
const actions = captureArray(value);
|
|
973
|
-
if (actions.length < 1 || actions.length > PERMISSION_ACTIONS.length || new Set(actions).size !== actions.length || !actions.every((action) => PERMISSION_ACTIONS.includes(action))) throw new DriveError("invalid_input");
|
|
974
|
-
return actions;
|
|
983
|
+
const final = values.join(joiner);
|
|
984
|
+
return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
|
|
975
985
|
}
|
|
976
|
-
function
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
const
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
+
function serializeArrayParam(name, value, options) {
|
|
987
|
+
if (!Array.isArray(value)) return "";
|
|
988
|
+
if (options.explode === false) {
|
|
989
|
+
const joiner2 = {
|
|
990
|
+
form: ",",
|
|
991
|
+
spaceDelimited: "%20",
|
|
992
|
+
pipeDelimited: "|"
|
|
993
|
+
}[options.style] || ",";
|
|
994
|
+
const final = (options.allowReserved === true ? value : value.map((v) => encodeURIComponent(v))).join(joiner2);
|
|
995
|
+
switch (options.style) {
|
|
996
|
+
case "simple": return final;
|
|
997
|
+
case "label": return `.${final}`;
|
|
998
|
+
case "matrix": return `;${name}=${final}`;
|
|
999
|
+
default: return `${name}=${final}`;
|
|
986
1000
|
}
|
|
987
|
-
if (Reflect.ownKeys(descriptors).length !== value.length + 1) throw new DriveError("invalid_input");
|
|
988
|
-
return result;
|
|
989
|
-
} catch (error) {
|
|
990
|
-
if (error instanceof DriveError) throw error;
|
|
991
|
-
throw new DriveError("invalid_input");
|
|
992
1001
|
}
|
|
1002
|
+
const joiner = {
|
|
1003
|
+
simple: ",",
|
|
1004
|
+
label: ".",
|
|
1005
|
+
matrix: ";"
|
|
1006
|
+
}[options.style] || "&";
|
|
1007
|
+
const values = [];
|
|
1008
|
+
for (const v of value) if (options.style === "simple" || options.style === "label") values.push(options.allowReserved === true ? v : encodeURIComponent(v));
|
|
1009
|
+
else values.push(serializePrimitiveParam(name, v, options));
|
|
1010
|
+
return options.style === "label" || options.style === "matrix" ? `${joiner}${values.join(joiner)}` : values.join(joiner);
|
|
993
1011
|
}
|
|
994
|
-
function
|
|
995
|
-
return
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1012
|
+
function createQuerySerializer(options) {
|
|
1013
|
+
return function querySerializer(queryParams) {
|
|
1014
|
+
const search = [];
|
|
1015
|
+
if (queryParams && typeof queryParams === "object") for (const name in queryParams) {
|
|
1016
|
+
const value = queryParams[name];
|
|
1017
|
+
if (value === void 0 || value === null) continue;
|
|
1018
|
+
if (Array.isArray(value)) {
|
|
1019
|
+
if (value.length === 0) continue;
|
|
1020
|
+
search.push(serializeArrayParam(name, value, {
|
|
1021
|
+
style: "form",
|
|
1022
|
+
explode: true,
|
|
1023
|
+
...options?.array,
|
|
1024
|
+
allowReserved: options?.allowReserved || false
|
|
1025
|
+
}));
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
if (typeof value === "object") {
|
|
1029
|
+
search.push(serializeObjectParam(name, value, {
|
|
1030
|
+
style: "deepObject",
|
|
1031
|
+
explode: true,
|
|
1032
|
+
...options?.object,
|
|
1033
|
+
allowReserved: options?.allowReserved || false
|
|
1034
|
+
}));
|
|
1035
|
+
continue;
|
|
1036
|
+
}
|
|
1037
|
+
search.push(serializePrimitiveParam(name, value, options));
|
|
1038
|
+
}
|
|
1039
|
+
return search.join("&");
|
|
1010
1040
|
};
|
|
1011
1041
|
}
|
|
1012
|
-
function
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
if (typeof envelope.code !== "string" || !DRIVE_API_ERROR_CODES.includes(envelope.code) || envelope.message !== DRIVE_API_ERROR_MESSAGES[envelope.code] || !REQUEST_ID.test(String(envelope.requestId)) || envelope.requestId !== headerRequestId || !isExactRecord(envelope.details, []) || !errorStatusMatches(envelope.code, response.status, preconditionStatus, allowsQuotaExceeded) || parsed.text !== JSON.stringify(value)) return new DriveError("invalid_response", {
|
|
1038
|
-
status: response.status,
|
|
1039
|
-
requestId: headerRequestId
|
|
1040
|
-
});
|
|
1041
|
-
return new DriveError(envelope.code, {
|
|
1042
|
-
status: response.status,
|
|
1043
|
-
requestId: envelope.requestId
|
|
1044
|
-
});
|
|
1045
|
-
}
|
|
1046
|
-
function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded) {
|
|
1047
|
-
if (code === "quota_exceeded" && !allowsQuotaExceeded) return false;
|
|
1048
|
-
return {
|
|
1049
|
-
authentication_required: [401],
|
|
1050
|
-
identity_authority_unavailable: [503],
|
|
1051
|
-
permission_denied: [403],
|
|
1052
|
-
resource_not_found: [404],
|
|
1053
|
-
invalid_request: [422],
|
|
1054
|
-
invalid_pagination_cursor: [422],
|
|
1055
|
-
invalid_idempotency_key: [422],
|
|
1056
|
-
precondition_failed: [preconditionStatus],
|
|
1057
|
-
idempotency_conflict: [409],
|
|
1058
|
-
quota_exceeded: [409],
|
|
1059
|
-
service_unavailable: [503],
|
|
1060
|
-
internal_error: [500]
|
|
1061
|
-
}[code].includes(status);
|
|
1062
|
-
}
|
|
1063
|
-
async function parseBoundedJson(response, maximumBytes, status, requestId, signal) {
|
|
1064
|
-
if (!response.body) throw new DriveError("invalid_response", {
|
|
1065
|
-
status,
|
|
1066
|
-
requestId
|
|
1067
|
-
});
|
|
1068
|
-
const reader = response.body.getReader();
|
|
1069
|
-
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
1070
|
-
let size = 0;
|
|
1071
|
-
let chunks = 0;
|
|
1072
|
-
let text = "";
|
|
1073
|
-
const contentLength = response.headers.get("content-length");
|
|
1074
|
-
if (contentLength !== null && (!/^(?:0|[1-9][0-9]*)$/.test(contentLength) || Number(contentLength) > maximumBytes)) {
|
|
1075
|
-
reader.cancel().catch(() => {});
|
|
1076
|
-
throw new DriveError("invalid_response", {
|
|
1077
|
-
status,
|
|
1078
|
-
requestId
|
|
1079
|
-
});
|
|
1080
|
-
}
|
|
1081
|
-
const deadline = new AbortController();
|
|
1082
|
-
const timeout = setTimeout(() => deadline.abort(), RESPONSE_DEADLINE_MILLISECONDS);
|
|
1083
|
-
try {
|
|
1084
|
-
while (true) {
|
|
1085
|
-
if (signal?.aborted) throw new DriveError("aborted");
|
|
1086
|
-
const { done, value } = await readResponseChunk(reader, signal, deadline.signal);
|
|
1087
|
-
if (done) break;
|
|
1088
|
-
chunks += 1;
|
|
1089
|
-
size += value.byteLength;
|
|
1090
|
-
if (chunks > RESPONSE_CHUNK_LIMIT || size > maximumBytes) throw new DriveError("invalid_response", {
|
|
1091
|
-
status,
|
|
1092
|
-
requestId
|
|
1093
|
-
});
|
|
1094
|
-
text += decoder.decode(value, { stream: true });
|
|
1042
|
+
function defaultPathSerializer(pathname, pathParams) {
|
|
1043
|
+
let nextURL = pathname;
|
|
1044
|
+
for (const match of pathname.match(PATH_PARAM_RE) ?? []) {
|
|
1045
|
+
let name = match.substring(1, match.length - 1);
|
|
1046
|
+
let explode = false;
|
|
1047
|
+
let style = "simple";
|
|
1048
|
+
if (name.endsWith("*")) {
|
|
1049
|
+
explode = true;
|
|
1050
|
+
name = name.substring(0, name.length - 1);
|
|
1051
|
+
}
|
|
1052
|
+
if (name.startsWith(".")) {
|
|
1053
|
+
style = "label";
|
|
1054
|
+
name = name.substring(1);
|
|
1055
|
+
} else if (name.startsWith(";")) {
|
|
1056
|
+
style = "matrix";
|
|
1057
|
+
name = name.substring(1);
|
|
1058
|
+
}
|
|
1059
|
+
if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) continue;
|
|
1060
|
+
const value = pathParams[name];
|
|
1061
|
+
if (Array.isArray(value)) {
|
|
1062
|
+
nextURL = nextURL.replace(match, serializeArrayParam(name, value, {
|
|
1063
|
+
style,
|
|
1064
|
+
explode
|
|
1065
|
+
}));
|
|
1066
|
+
continue;
|
|
1095
1067
|
}
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
if (error instanceof DriveError) {
|
|
1103
|
-
if (error.code === "aborted" || signal?.aborted) throw new DriveError("aborted");
|
|
1104
|
-
throw error;
|
|
1068
|
+
if (typeof value === "object") {
|
|
1069
|
+
nextURL = nextURL.replace(match, serializeObjectParam(name, value, {
|
|
1070
|
+
style,
|
|
1071
|
+
explode
|
|
1072
|
+
}));
|
|
1073
|
+
continue;
|
|
1105
1074
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
clearTimeout(timeout);
|
|
1112
|
-
reader.cancel().catch(() => {});
|
|
1075
|
+
if (style === "matrix") {
|
|
1076
|
+
nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);
|
|
1077
|
+
continue;
|
|
1078
|
+
}
|
|
1079
|
+
nextURL = nextURL.replace(match, style === "label" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));
|
|
1113
1080
|
}
|
|
1081
|
+
return nextURL;
|
|
1114
1082
|
}
|
|
1115
|
-
|
|
1116
|
-
if (
|
|
1117
|
-
if (
|
|
1118
|
-
|
|
1119
|
-
let removeDeadlineAbort = () => {};
|
|
1120
|
-
const operationAbort = new Promise((_, reject) => {
|
|
1121
|
-
if (!operationSignal) return;
|
|
1122
|
-
const onAbort = () => reject(new DriveError("aborted"));
|
|
1123
|
-
operationSignal.addEventListener("abort", onAbort, { once: true });
|
|
1124
|
-
removeOperationAbort = () => operationSignal.removeEventListener("abort", onAbort);
|
|
1125
|
-
});
|
|
1126
|
-
const deadlineAbort = new Promise((_, reject) => {
|
|
1127
|
-
const onAbort = () => reject(new DriveError("invalid_response"));
|
|
1128
|
-
deadlineSignal.addEventListener("abort", onAbort, { once: true });
|
|
1129
|
-
removeDeadlineAbort = () => deadlineSignal.removeEventListener("abort", onAbort);
|
|
1130
|
-
});
|
|
1131
|
-
try {
|
|
1132
|
-
return await Promise.race([
|
|
1133
|
-
reader.read(),
|
|
1134
|
-
operationAbort,
|
|
1135
|
-
deadlineAbort
|
|
1136
|
-
]);
|
|
1137
|
-
} finally {
|
|
1138
|
-
removeOperationAbort();
|
|
1139
|
-
removeDeadlineAbort();
|
|
1083
|
+
function defaultBodySerializer(body, headers) {
|
|
1084
|
+
if (body instanceof FormData) return body;
|
|
1085
|
+
if (headers) {
|
|
1086
|
+
if ((headers.get instanceof Function ? headers.get("Content-Type") ?? headers.get("content-type") : headers["Content-Type"] ?? headers["content-type"]) === "application/x-www-form-urlencoded") return new URLSearchParams(body).toString();
|
|
1140
1087
|
}
|
|
1088
|
+
return JSON.stringify(body);
|
|
1141
1089
|
}
|
|
1142
|
-
function
|
|
1143
|
-
|
|
1090
|
+
function createFinalURL(pathname, options) {
|
|
1091
|
+
let finalURL = `${options.baseUrl}${pathname}`;
|
|
1092
|
+
if (options.params?.path) finalURL = options.pathSerializer(finalURL, options.params.path);
|
|
1093
|
+
let search = options.querySerializer(options.params.query ?? {});
|
|
1094
|
+
if (search.startsWith("?")) search = search.substring(1);
|
|
1095
|
+
if (search) finalURL += `?${search}`;
|
|
1096
|
+
return finalURL;
|
|
1144
1097
|
}
|
|
1145
|
-
function
|
|
1146
|
-
|
|
1098
|
+
function mergeHeaders(...allHeaders) {
|
|
1099
|
+
const finalHeaders = new Headers();
|
|
1100
|
+
for (const h of allHeaders) {
|
|
1101
|
+
if (!h || typeof h !== "object") continue;
|
|
1102
|
+
const iterator = h instanceof Headers ? h.entries() : Object.entries(h);
|
|
1103
|
+
for (const [k, v] of iterator) if (v === null) finalHeaders.delete(k);
|
|
1104
|
+
else if (Array.isArray(v)) for (const v2 of v) finalHeaders.append(k, v2);
|
|
1105
|
+
else if (v !== void 0) finalHeaders.set(k, v);
|
|
1106
|
+
}
|
|
1107
|
+
return finalHeaders;
|
|
1147
1108
|
}
|
|
1148
|
-
function
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
const permissionGrantEtag = headers.get("drive-permission-grant-etag");
|
|
1152
|
-
return Object.freeze({
|
|
1153
|
-
...etag !== null && LIST_ETAG.test(etag) ? { etag } : {},
|
|
1154
|
-
...permissionCollectionEtag !== null && parseCollectionEtag(permissionCollectionEtag) !== void 0 ? { permissionCollectionEtag } : {},
|
|
1155
|
-
...permissionGrantEtag !== null && parseGrantEtag(permissionGrantEtag) !== void 0 ? { permissionGrantEtag } : {}
|
|
1156
|
-
});
|
|
1109
|
+
function removeTrailingSlash(url) {
|
|
1110
|
+
if (url.endsWith("/")) return url.substring(0, url.length - 1);
|
|
1111
|
+
return url;
|
|
1157
1112
|
}
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1113
|
+
String.fromCharCode;
|
|
1114
|
+
const TRAILING_SLASH_RE = /\/$|\/\?|\/#/;
|
|
1115
|
+
const JOIN_LEADING_SLASH_RE = /^\.?\//;
|
|
1116
|
+
function hasTrailingSlash(input = "", respectQueryAndFragment) {
|
|
1117
|
+
if (!respectQueryAndFragment) return input.endsWith("/");
|
|
1118
|
+
return TRAILING_SLASH_RE.test(input);
|
|
1161
1119
|
}
|
|
1162
|
-
function
|
|
1163
|
-
return
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1120
|
+
function withTrailingSlash(input = "", respectQueryAndFragment) {
|
|
1121
|
+
if (!respectQueryAndFragment) return input.endsWith("/") ? input : input + "/";
|
|
1122
|
+
if (hasTrailingSlash(input, true)) return input || "/";
|
|
1123
|
+
let path = input;
|
|
1124
|
+
let fragment = "";
|
|
1125
|
+
const fragmentIndex = input.indexOf("#");
|
|
1126
|
+
if (fragmentIndex !== -1) {
|
|
1127
|
+
path = input.slice(0, fragmentIndex);
|
|
1128
|
+
fragment = input.slice(fragmentIndex);
|
|
1129
|
+
if (!path) return fragment;
|
|
1130
|
+
}
|
|
1131
|
+
const [s0, ...s] = path.split("?");
|
|
1132
|
+
return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
1173
1133
|
}
|
|
1174
|
-
function
|
|
1175
|
-
|
|
1176
|
-
"items",
|
|
1177
|
-
"nextCursor",
|
|
1178
|
-
"collectionRevision",
|
|
1179
|
-
"collectionEtag"
|
|
1180
|
-
]) && Array.isArray(value.items) && value.items.length <= 50 && value.items.every(isPermissionGrant) && (value.nextCursor === null || typeof value.nextCursor === "string" && value.nextCursor.length <= 699 && CURSOR.test(value.nextCursor)) && isSafeInteger(value.collectionRevision) && typeof value.collectionEtag === "string" && parseCollectionEtag(value.collectionEtag) === value.collectionRevision)) return false;
|
|
1181
|
-
const collectionHeader = headers.get("drive-permission-collection-etag");
|
|
1182
|
-
const representationEtag = headers.get("etag");
|
|
1183
|
-
const collectionRevision = value.collectionRevision;
|
|
1184
|
-
if (!isSafeInteger(collectionRevision)) return false;
|
|
1185
|
-
return collectionHeader === value.collectionEtag && representationEtag !== null && LIST_ETAG.test(representationEtag) && value.items.every((grant) => (grant.source === "direct" ? grant.sourceItemId === targetItemId : grant.sourceItemId !== targetItemId) && grant.etag === permissionGrantEtag(collectionRevision, grant.revision)) && isStrictlyOrdered(value.items, (grant) => `${grant.sourceItemId}\0${grant.grantId}`);
|
|
1134
|
+
function isNonEmptyURL(url) {
|
|
1135
|
+
return url && url !== "/";
|
|
1186
1136
|
}
|
|
1187
|
-
function
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
"
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
"availability",
|
|
1195
|
-
"expiresAtEpochMilliseconds",
|
|
1196
|
-
"revision",
|
|
1197
|
-
"etag"
|
|
1198
|
-
]) && (value.source === "direct" || value.source === "inherited") && typeof value.sourceItemId === "string" && ITEM_ID.test(value.sourceItemId) && typeof value.grantId === "string" && GRANT_ID.test(value.grantId) && isGrantee(value.grantee) && isPermissionActions(value.actions) && [
|
|
1199
|
-
"active",
|
|
1200
|
-
"expired",
|
|
1201
|
-
"revoked"
|
|
1202
|
-
].includes(String(value.availability)) && (value.expiresAtEpochMilliseconds === null || isSafeInteger(value.expiresAtEpochMilliseconds)) && isSafeInteger(value.revision) && typeof value.etag === "string" && GRANT_ETAG.test(value.etag);
|
|
1137
|
+
function joinURL(base, ...input) {
|
|
1138
|
+
let url = base || "";
|
|
1139
|
+
for (const segment of input.filter((url2) => isNonEmptyURL(url2))) if (url) {
|
|
1140
|
+
const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
|
|
1141
|
+
url = withTrailingSlash(url) + _segment;
|
|
1142
|
+
} else url = segment;
|
|
1143
|
+
return url;
|
|
1203
1144
|
}
|
|
1204
|
-
|
|
1205
|
-
|
|
1145
|
+
//#endregion
|
|
1146
|
+
//#region src/internal/client/transport.ts
|
|
1147
|
+
const DEFAULT_REQUEST_TIMEOUT_MILLISECONDS = 3e4;
|
|
1148
|
+
const MAX_REQUEST_TIMEOUT_MILLISECONDS = 12e4;
|
|
1149
|
+
function createClientRuntime(config) {
|
|
1150
|
+
let runtime;
|
|
1151
|
+
try {
|
|
1152
|
+
runtime = Object.freeze({
|
|
1153
|
+
baseUrl: parseBaseUrl(config.baseUrl),
|
|
1154
|
+
fetchImplementation: config.fetch ?? globalThis.fetch,
|
|
1155
|
+
getCredential: config.getCredential,
|
|
1156
|
+
timeoutMilliseconds: parseTimeoutMilliseconds(config.timeoutMilliseconds)
|
|
1157
|
+
});
|
|
1158
|
+
} catch {
|
|
1159
|
+
throw new DriveError("invalid_input");
|
|
1160
|
+
}
|
|
1161
|
+
if (typeof runtime.fetchImplementation !== "function" || typeof runtime.getCredential !== "function") throw new DriveError("invalid_input");
|
|
1162
|
+
return runtime;
|
|
1206
1163
|
}
|
|
1207
|
-
function
|
|
1208
|
-
|
|
1164
|
+
async function execute(runtime, signal, preconditionStatus, send, successStatuses, guard, allowsQuotaExceeded = false, allowedErrorCodes) {
|
|
1165
|
+
const operation = createOperationSignal(signal, runtime.timeoutMilliseconds);
|
|
1166
|
+
try {
|
|
1167
|
+
const operationSignal = operation.signal;
|
|
1168
|
+
throwIfAborted(operationSignal);
|
|
1169
|
+
const credential = await obtainCredential(runtime.getCredential, operationSignal);
|
|
1170
|
+
let capturedResponse;
|
|
1171
|
+
await send(createClient({
|
|
1172
|
+
baseUrl: runtime.baseUrl,
|
|
1173
|
+
fetch: async (request) => {
|
|
1174
|
+
try {
|
|
1175
|
+
const response = await raceWithAbort(runtime.fetchImplementation(request), operationSignal);
|
|
1176
|
+
if (!(response instanceof Response)) throw new DriveError("invalid_response");
|
|
1177
|
+
capturedResponse = response;
|
|
1178
|
+
} catch (error) {
|
|
1179
|
+
if (error instanceof DriveError) throw error;
|
|
1180
|
+
throw operationSignal.aborted ? new DriveError("aborted") : new DriveError("network_error");
|
|
1181
|
+
}
|
|
1182
|
+
return new Response(null, { status: 204 });
|
|
1183
|
+
}
|
|
1184
|
+
}), {
|
|
1185
|
+
cache: "no-store",
|
|
1186
|
+
credentials: "omit",
|
|
1187
|
+
headers: new Headers({ authorization: `Bearer ${credential}` }),
|
|
1188
|
+
signal: operationSignal
|
|
1189
|
+
});
|
|
1190
|
+
if (!capturedResponse) throw new DriveError("network_error");
|
|
1191
|
+
return await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes);
|
|
1192
|
+
} catch (error) {
|
|
1193
|
+
if (operation.didTimeout()) throw new DriveError("timeout");
|
|
1194
|
+
if (error instanceof DriveError) throw error;
|
|
1195
|
+
throw operation.signal.aborted ? new DriveError("aborted") : new DriveError("network_error");
|
|
1196
|
+
} finally {
|
|
1197
|
+
operation.dispose();
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
function parseTimeoutMilliseconds(value) {
|
|
1201
|
+
if (value === void 0) return DEFAULT_REQUEST_TIMEOUT_MILLISECONDS;
|
|
1202
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > MAX_REQUEST_TIMEOUT_MILLISECONDS) throw new DriveError("invalid_input");
|
|
1203
|
+
return value;
|
|
1204
|
+
}
|
|
1205
|
+
function createOperationSignal(callerSignal, timeoutMilliseconds) {
|
|
1206
|
+
const controller = new AbortController();
|
|
1207
|
+
let timedOut = false;
|
|
1208
|
+
const onAbort = () => controller.abort();
|
|
1209
|
+
if (callerSignal?.aborted) controller.abort();
|
|
1210
|
+
else callerSignal?.addEventListener("abort", onAbort, { once: true });
|
|
1211
|
+
const timeout = setTimeout(() => {
|
|
1212
|
+
timedOut = true;
|
|
1213
|
+
controller.abort();
|
|
1214
|
+
}, timeoutMilliseconds);
|
|
1215
|
+
return {
|
|
1216
|
+
signal: controller.signal,
|
|
1217
|
+
didTimeout: () => timedOut,
|
|
1218
|
+
dispose: () => {
|
|
1219
|
+
clearTimeout(timeout);
|
|
1220
|
+
callerSignal?.removeEventListener("abort", onAbort);
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
function parseBaseUrl(value) {
|
|
1225
|
+
if (typeof value !== "string") throw new TypeError("Drive base URL is invalid");
|
|
1226
|
+
let url;
|
|
1227
|
+
try {
|
|
1228
|
+
url = new URL(value);
|
|
1229
|
+
} catch {
|
|
1230
|
+
throw new TypeError("Drive base URL is invalid");
|
|
1231
|
+
}
|
|
1232
|
+
const localHttp = url.protocol === "http:" && [
|
|
1233
|
+
"localhost",
|
|
1234
|
+
"127.0.0.1",
|
|
1235
|
+
"[::1]"
|
|
1236
|
+
].includes(url.hostname);
|
|
1237
|
+
if (url.protocol !== "https:" && !localHttp || url.username || url.password || url.search || url.hash || !url.host) throw new TypeError("Drive base URL is invalid");
|
|
1238
|
+
return joinURL(url.origin, url.pathname);
|
|
1239
|
+
}
|
|
1240
|
+
async function obtainCredential(provider, signal) {
|
|
1241
|
+
throwIfAborted(signal);
|
|
1242
|
+
let credential;
|
|
1243
|
+
try {
|
|
1244
|
+
credential = await raceWithAbort(provider({ signal }), signal);
|
|
1245
|
+
} catch (error) {
|
|
1246
|
+
if (error instanceof DriveError && error.code === "aborted") throw error;
|
|
1247
|
+
throw signal.aborted ? new DriveError("aborted") : new DriveError("credential_unavailable");
|
|
1248
|
+
}
|
|
1249
|
+
if (typeof credential !== "string" || credential.length < 1 || credential.length > 16384 || !/^[\x21-\x7e]+$/.test(credential)) throw new DriveError("credential_unavailable");
|
|
1250
|
+
return credential;
|
|
1209
1251
|
}
|
|
1210
|
-
function
|
|
1211
|
-
if (
|
|
1212
|
-
"outcome",
|
|
1213
|
-
"grant",
|
|
1214
|
-
"collectionRevision"
|
|
1215
|
-
]) || value.outcome !== "committed" && value.outcome !== "replayed" || !isSafeInteger(value.collectionRevision)) return false;
|
|
1216
|
-
const grant = value.grant;
|
|
1217
|
-
return isExactRecord(grant, [
|
|
1218
|
-
"source",
|
|
1219
|
-
"sourceItemId",
|
|
1220
|
-
"grantId",
|
|
1221
|
-
"grantee",
|
|
1222
|
-
"actions",
|
|
1223
|
-
"availability",
|
|
1224
|
-
"expiresAtEpochMilliseconds",
|
|
1225
|
-
"revision"
|
|
1226
|
-
]) && grant.source === "direct" && typeof grant.sourceItemId === "string" && grant.sourceItemId === targetItemId && typeof grant.grantId === "string" && GRANT_ID.test(grant.grantId) && (expectedGrantId === void 0 || grant.grantId === expectedGrantId) && isGrantee(grant.grantee) && isPermissionActions(grant.actions) && [
|
|
1227
|
-
"active",
|
|
1228
|
-
"expired",
|
|
1229
|
-
"revoked"
|
|
1230
|
-
].includes(String(grant.availability)) && (grant.expiresAtEpochMilliseconds === null || isSafeInteger(grant.expiresAtEpochMilliseconds)) && isSafeInteger(grant.revision);
|
|
1252
|
+
function throwIfAborted(signal) {
|
|
1253
|
+
if (signal.aborted) throw new DriveError("aborted");
|
|
1231
1254
|
}
|
|
1232
|
-
function
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
"restricted_administrator_bypass",
|
|
1245
|
-
"direct_grant",
|
|
1246
|
-
"inherited_grant"
|
|
1247
|
-
].includes(String(action.basis))) || !(action.sourceItemId === null || typeof action.sourceItemId === "string" && ITEM_ID.test(action.sourceItemId)) || !(action.grantId === null || typeof action.grantId === "string" && GRANT_ID.test(action.grantId)) || !effectiveSourceIsCoherent(action, targetItemId)) return false;
|
|
1255
|
+
async function raceWithAbort(promise, signal) {
|
|
1256
|
+
throwIfAborted(signal);
|
|
1257
|
+
let removeAbort = () => {};
|
|
1258
|
+
const aborted = new Promise((_, reject) => {
|
|
1259
|
+
const onAbort = () => reject(new DriveError("aborted"));
|
|
1260
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1261
|
+
removeAbort = () => signal.removeEventListener("abort", onAbort);
|
|
1262
|
+
});
|
|
1263
|
+
try {
|
|
1264
|
+
return await Promise.race([promise, aborted]);
|
|
1265
|
+
} finally {
|
|
1266
|
+
removeAbort();
|
|
1248
1267
|
}
|
|
1249
|
-
return true;
|
|
1250
1268
|
}
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1269
|
+
//#endregion
|
|
1270
|
+
//#region src/internal/client/operations.ts
|
|
1271
|
+
const CURRENT_WORKSPACE_ERROR_CODES = Object.freeze([
|
|
1272
|
+
"authentication_required",
|
|
1273
|
+
"identity_authority_unavailable",
|
|
1274
|
+
"permission_denied",
|
|
1275
|
+
"resource_not_found",
|
|
1276
|
+
"invalid_request",
|
|
1277
|
+
"service_unavailable"
|
|
1278
|
+
]);
|
|
1279
|
+
function createDriveClientInternal(config) {
|
|
1280
|
+
const runtime = createClientRuntime(config);
|
|
1281
|
+
return Object.freeze({
|
|
1282
|
+
getCurrentWorkspace: (input) => getCurrentWorkspace(runtime, input),
|
|
1283
|
+
listFolderChildren: (input) => listFolderChildren(runtime, input),
|
|
1284
|
+
createFolder: (input) => createFolder(runtime, input),
|
|
1285
|
+
listItemPermissions: (input) => listItemPermissions(runtime, input),
|
|
1286
|
+
readEffectiveItemPermissions: (input) => readEffectiveItemPermissions(runtime, input),
|
|
1287
|
+
createItemPermission: (input) => createItemPermission(runtime, input),
|
|
1288
|
+
updateItemPermission: (input) => updateItemPermission(runtime, input),
|
|
1289
|
+
revokeItemPermission: (input) => revokeItemPermission(runtime, input),
|
|
1290
|
+
createUpload: (input) => createUpload(runtime, input),
|
|
1291
|
+
abortUpload: (input) => abortUpload(runtime, input)
|
|
1292
|
+
});
|
|
1263
1293
|
}
|
|
1264
|
-
function
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
return false;
|
|
1294
|
+
async function getCurrentWorkspace(runtime, input) {
|
|
1295
|
+
return execute(runtime, validateCurrentWorkspaceInput(input).signal, null, (api, requestOptions) => api.GET("/api/v1/workspaces/current", {
|
|
1296
|
+
...operationOptions("getCurrentWorkspace", { params: {} }),
|
|
1297
|
+
...requestOptions
|
|
1298
|
+
}), [200], isCurrentWorkspace, false, CURRENT_WORKSPACE_ERROR_CODES);
|
|
1270
1299
|
}
|
|
1271
|
-
function
|
|
1272
|
-
const
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1300
|
+
async function listFolderChildren(runtime, input) {
|
|
1301
|
+
const validated = validatePageInput(input);
|
|
1302
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/children", {
|
|
1303
|
+
...operationOptions("listFolderChildren", { params: {
|
|
1304
|
+
path: resourcePath(validated),
|
|
1305
|
+
query: pageQuery(validated)
|
|
1306
|
+
} }),
|
|
1307
|
+
...requestOptions
|
|
1308
|
+
}), [200], (value) => isFolderPage(value, validated.workspaceId, validated.itemId));
|
|
1279
1309
|
}
|
|
1280
|
-
function
|
|
1281
|
-
const
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1310
|
+
async function createFolder(runtime, input) {
|
|
1311
|
+
const validated = validateCreateFolderInput(input);
|
|
1312
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/items/{itemId}/children", {
|
|
1313
|
+
...operationOptions("createFolder", {
|
|
1314
|
+
params: {
|
|
1315
|
+
path: resourcePath(validated),
|
|
1316
|
+
header: { "Idempotency-Key": validated.idempotencyKey }
|
|
1317
|
+
},
|
|
1318
|
+
body: { name: validated.name }
|
|
1319
|
+
}),
|
|
1320
|
+
...requestOptions
|
|
1321
|
+
}), [200, 201], (value) => isFolderItem(value) && value.workspaceId === validated.workspaceId && value.parentItemId === validated.itemId && value.kind === "folder" && value.name === validated.name);
|
|
1285
1322
|
}
|
|
1286
|
-
function
|
|
1287
|
-
const
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1323
|
+
async function listItemPermissions(runtime, input) {
|
|
1324
|
+
const validated = validatePageInput(input);
|
|
1325
|
+
return execute(runtime, validated.signal, 412, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/permissions", {
|
|
1326
|
+
...operationOptions("listItemPermissions", { params: {
|
|
1327
|
+
path: resourcePath(validated),
|
|
1328
|
+
query: pageQuery(validated)
|
|
1329
|
+
} }),
|
|
1330
|
+
...requestOptions
|
|
1331
|
+
}), [200], (value, _status, headers) => isPermissionPage(value, headers, validated.itemId));
|
|
1292
1332
|
}
|
|
1293
|
-
function
|
|
1294
|
-
|
|
1333
|
+
async function readEffectiveItemPermissions(runtime, input) {
|
|
1334
|
+
const validated = validateResourceInput(input);
|
|
1335
|
+
return execute(runtime, validated.signal, 412, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/permissions/effective", {
|
|
1336
|
+
...operationOptions("readEffectiveItemPermissions", { params: { path: resourcePath(validated) } }),
|
|
1337
|
+
...requestOptions
|
|
1338
|
+
}), [200], (value) => isEffectivePermissionResponse(value, validated.itemId));
|
|
1295
1339
|
}
|
|
1296
|
-
function
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1340
|
+
async function createItemPermission(runtime, input) {
|
|
1341
|
+
const validated = validateCreatePermissionInput(input);
|
|
1342
|
+
return execute(runtime, validated.signal, 412, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/items/{itemId}/permissions", {
|
|
1343
|
+
...operationOptions("createItemPermission", {
|
|
1344
|
+
params: {
|
|
1345
|
+
path: resourcePath(validated),
|
|
1346
|
+
header: {
|
|
1347
|
+
"Idempotency-Key": validated.idempotencyKey,
|
|
1348
|
+
"If-Match": validated.ifMatch
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
body: {
|
|
1352
|
+
grantee: validated.grantee,
|
|
1353
|
+
actions: validated.actions,
|
|
1354
|
+
expiresAtEpochMilliseconds: validated.expiresAtEpochMilliseconds
|
|
1355
|
+
}
|
|
1356
|
+
}),
|
|
1357
|
+
...requestOptions
|
|
1358
|
+
}), [200, 201], (value, status, headers) => isPermissionMutation(value, validated.itemId) && (status === 201 && value.outcome === "committed" || status === 200 && value.outcome === "replayed") && (status === 200 || value.grant.availability !== "revoked") && mutationValidatorsAreCoherent(headers));
|
|
1308
1359
|
}
|
|
1309
|
-
function
|
|
1310
|
-
const
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
"
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1360
|
+
async function updateItemPermission(runtime, input) {
|
|
1361
|
+
const validated = validateUpdatePermissionInput(input);
|
|
1362
|
+
const body = {};
|
|
1363
|
+
if (validated.actions !== void 0) body.actions = validated.actions;
|
|
1364
|
+
if (validated.expiresAtEpochMilliseconds !== void 0) body.expiresAtEpochMilliseconds = validated.expiresAtEpochMilliseconds;
|
|
1365
|
+
return execute(runtime, validated.signal, 412, (api, requestOptions) => api.PATCH("/api/v1/workspaces/{workspaceId}/items/{itemId}/permissions/{grantId}", {
|
|
1366
|
+
...operationOptions("updateItemPermission", {
|
|
1367
|
+
params: {
|
|
1368
|
+
path: {
|
|
1369
|
+
...resourcePath(validated),
|
|
1370
|
+
grantId: validated.grantId
|
|
1371
|
+
},
|
|
1372
|
+
header: {
|
|
1373
|
+
"Idempotency-Key": validated.idempotencyKey,
|
|
1374
|
+
"If-Match": validated.ifMatch
|
|
1375
|
+
}
|
|
1376
|
+
},
|
|
1377
|
+
body
|
|
1378
|
+
}),
|
|
1379
|
+
...requestOptions
|
|
1380
|
+
}), [200], (value, _status, headers) => isPermissionMutation(value, validated.itemId, validated.grantId) && value.grant.availability !== "revoked" && mutationValidatorsAreCoherent(headers));
|
|
1320
1381
|
}
|
|
1321
|
-
function
|
|
1322
|
-
|
|
1382
|
+
async function revokeItemPermission(runtime, input) {
|
|
1383
|
+
const validated = validateGrantMutationInput(input);
|
|
1384
|
+
return execute(runtime, validated.signal, 412, (api, requestOptions) => api.DELETE("/api/v1/workspaces/{workspaceId}/items/{itemId}/permissions/{grantId}", {
|
|
1385
|
+
...operationOptions("revokeItemPermission", { params: {
|
|
1386
|
+
path: {
|
|
1387
|
+
...resourcePath(validated),
|
|
1388
|
+
grantId: validated.grantId
|
|
1389
|
+
},
|
|
1390
|
+
header: {
|
|
1391
|
+
"Idempotency-Key": validated.idempotencyKey,
|
|
1392
|
+
"If-Match": validated.ifMatch
|
|
1393
|
+
}
|
|
1394
|
+
} }),
|
|
1395
|
+
...requestOptions
|
|
1396
|
+
}), [200], (value, _status, headers) => isPermissionMutation(value, validated.itemId, validated.grantId) && value.grant.availability === "revoked" && parseCollectionEtag(headers.get("drive-permission-collection-etag") ?? "") !== void 0 && headers.get("drive-permission-grant-etag") === null);
|
|
1323
1397
|
}
|
|
1324
|
-
function
|
|
1325
|
-
|
|
1398
|
+
async function createUpload(runtime, input) {
|
|
1399
|
+
const validated = validateCreateUploadInput(input);
|
|
1400
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.POST("/api/v1/workspaces/{workspaceId}/uploads", {
|
|
1401
|
+
...operationOptions("createUpload", {
|
|
1402
|
+
params: {
|
|
1403
|
+
path: { workspaceId: validated.workspaceId },
|
|
1404
|
+
header: { "Idempotency-Key": validated.idempotencyKey }
|
|
1405
|
+
},
|
|
1406
|
+
body: {
|
|
1407
|
+
parentItemId: validated.parentItemId,
|
|
1408
|
+
expectedByteLength: validated.expectedByteLength
|
|
1409
|
+
}
|
|
1410
|
+
}),
|
|
1411
|
+
...requestOptions
|
|
1412
|
+
}), [200, 201], (value) => isUploadQuotaReservation(value) && value.workspaceId === validated.workspaceId && value.parentItemId === validated.parentItemId && value.expectedByteLength === validated.expectedByteLength && value.state === "reserved" && value.terminalReason === null && value.terminalAtEpochMilliseconds === null, true);
|
|
1326
1413
|
}
|
|
1327
|
-
function
|
|
1328
|
-
|
|
1329
|
-
return
|
|
1414
|
+
async function abortUpload(runtime, input) {
|
|
1415
|
+
const validated = validateAbortUploadInput(input);
|
|
1416
|
+
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.DELETE("/api/v1/workspaces/{workspaceId}/uploads/{uploadId}", {
|
|
1417
|
+
...operationOptions("abortUpload", { params: { path: {
|
|
1418
|
+
workspaceId: validated.workspaceId,
|
|
1419
|
+
uploadId: validated.uploadId
|
|
1420
|
+
} } }),
|
|
1421
|
+
...requestOptions
|
|
1422
|
+
}), [200], (value) => isUploadQuotaReservation(value) && value.workspaceId === validated.workspaceId && value.uploadId === validated.uploadId && value.state === "released" && value.terminalReason === "aborted" && value.terminalAtEpochMilliseconds !== null);
|
|
1330
1423
|
}
|
|
1331
1424
|
//#endregion
|
|
1332
1425
|
//#region src/server.ts
|