@finueva/drive 0.1.1 → 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 +6 -0
- package/README.md +16 -12
- package/dist/client.d.ts +2 -2
- package/dist/client.js +38 -8
- package/dist/contract.d.ts +141 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +38 -8
- package/dist/server.d.ts +2 -2
- package/dist/server.js +38 -8
- package/dist/types.d.ts +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
# `@finueva/drive`
|
|
2
2
|
|
|
3
|
-
The public TypeScript client for Finueva Drive.
|
|
3
|
+
The public TypeScript client for Finueva Drive. The package is published to npm; the API remains Local Experimental.
|
|
4
4
|
|
|
5
5
|
The package is ESM-only. Node.js 22 is the exact minimum; package CI qualifies Node.js 22 and 24. Modern browsers and Cloudflare Workers use Web Fetch, Streams, URL, and AbortSignal.
|
|
6
6
|
|
|
7
7
|
## Exports
|
|
8
8
|
|
|
9
|
-
| Import | Runtime
|
|
10
|
-
| ----------------------- |
|
|
11
|
-
| `@finueva/drive` | Browser-safe client factory, errors, and curated types
|
|
12
|
-
| `@finueva/drive/client` | Browser-safe client factory
|
|
13
|
-
| `@finueva/drive/server` | Request-scoped Worker and Node client factory
|
|
14
|
-
| `@finueva/drive/core` | Reviewed error values only
|
|
15
|
-
| `@finueva/drive/types` | Curated folder, permission, and upload quota types
|
|
9
|
+
| Import | Runtime |
|
|
10
|
+
| ----------------------- | ------------------------------------------------------------- |
|
|
11
|
+
| `@finueva/drive` | Browser-safe client factory, errors, and curated types |
|
|
12
|
+
| `@finueva/drive/client` | Browser-safe client factory |
|
|
13
|
+
| `@finueva/drive/server` | Request-scoped Worker and Node client factory |
|
|
14
|
+
| `@finueva/drive/core` | Reviewed error values only |
|
|
15
|
+
| `@finueva/drive/types` | Curated workspace, folder, permission, and upload quota types |
|
|
16
16
|
|
|
17
17
|
## Browser
|
|
18
18
|
|
|
@@ -25,9 +25,10 @@ const drive = createDriveClient({
|
|
|
25
25
|
timeoutMilliseconds: 30_000,
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
const { data: workspace } = await drive.getCurrentWorkspace();
|
|
28
29
|
const page = await drive.listFolderChildren({
|
|
29
|
-
workspaceId,
|
|
30
|
-
itemId,
|
|
30
|
+
workspaceId: workspace.workspaceId,
|
|
31
|
+
itemId: workspace.rootItemId,
|
|
31
32
|
limit: 50,
|
|
32
33
|
});
|
|
33
34
|
```
|
|
@@ -51,6 +52,7 @@ Create a client per request when using user authority. A fixed `credential` stri
|
|
|
51
52
|
|
|
52
53
|
Methods use the Native API operation IDs:
|
|
53
54
|
|
|
55
|
+
- `getCurrentWorkspace`
|
|
54
56
|
- `listFolderChildren`
|
|
55
57
|
- `createFolder`
|
|
56
58
|
- `listItemPermissions`
|
|
@@ -61,6 +63,8 @@ Methods use the Native API operation IDs:
|
|
|
61
63
|
- `createUpload`
|
|
62
64
|
- `abortUpload`
|
|
63
65
|
|
|
66
|
+
`getCurrentWorkspace` maps the credential's selected Auth context to the provisioned Drive workspace and canonical managed root. It accepts only an optional `{ signal }` input, never provisions as a side effect, and returns no entitlement, credential, or private persistence fields.
|
|
67
|
+
|
|
64
68
|
Every mutation requires the API's explicit idempotency key when the operation defines one and, for grants, a precondition validator. Mutations are never retried automatically. Sparse updates omit `undefined` properties and preserve explicit `null` expiry.
|
|
65
69
|
|
|
66
70
|
Successful calls return `{ data, status, requestId, validators }`. A successful response must carry one valid `X-Request-ID`; canonical API errors must carry the same request ID in their header and body. Any missing, malformed, or mismatched value is an `invalid_response`. The only exposed validators are `etag`, `permissionCollectionEtag`, and `permissionGrantEtag`.
|
|
@@ -86,6 +90,6 @@ Use an absolute HTTPS URL. Plain HTTP is accepted only for `localhost`, `127.0.0
|
|
|
86
90
|
|
|
87
91
|
## Release Status
|
|
88
92
|
|
|
89
|
-
|
|
93
|
+
Releases are selected by reviewed Changesets. Qualification builds the exact compiled Drive Worker, obtains `/api/v1/openapi.json` through Miniflare, checks generated types byte-for-byte, packs the package, and installs that tarball into clean external projects with lifecycle scripts disabled.
|
|
90
94
|
|
|
91
|
-
`@finueva/drive`
|
|
95
|
+
`@finueva/drive` is published on npm. The source repository is private, so public provenance is unavailable. ADR 0016 records the completed maintainer-2FA bootstrap; later releases use the protected OIDC workflow and npm approval without a stored npm token.
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as UploadQuotaReservation, D as ReservedUploadQuota, _ as FolderPage, a as CreateUploadInput, c as DriveClientConfig, g as FolderItem, n as AbortedUploadQuota, o as CurrentWorkspace, s as DriveClient, t as AbortUploadInput, u as DriveCredentialProvider, v as GetCurrentWorkspaceInput, y as ListFolderChildrenInput } from "./contract.js";
|
|
2
2
|
//#region src/client.d.ts
|
|
3
3
|
declare function createDriveClient(config: DriveClientConfig): DriveClient;
|
|
4
4
|
//#endregion
|
|
5
|
-
export { type AbortUploadInput, type AbortedUploadQuota, type CreateUploadInput, type DriveClient, type DriveClientConfig, type DriveCredentialProvider, type ReservedUploadQuota, type UploadQuotaReservation, createDriveClient };
|
|
5
|
+
export { type AbortUploadInput, type AbortedUploadQuota, type CreateUploadInput, type CurrentWorkspace, type DriveClient, type DriveClientConfig, type DriveCredentialProvider, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type ListFolderChildrenInput, type ReservedUploadQuota, type UploadQuotaReservation, createDriveClient };
|
package/dist/client.js
CHANGED
|
@@ -59,13 +59,13 @@ const REQUEST_ID = /^[A-Za-z0-9_-]{16,128}$/;
|
|
|
59
59
|
const COLLECTION_ETAG = /^"drive\.permission-collection\.v1\.(0|[1-9][0-9]*)"$/;
|
|
60
60
|
const GRANT_ETAG$1 = /^"drive\.permission-grant\.v1\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"$/;
|
|
61
61
|
const LIST_ETAG$1 = /^"drive\.permission-list\.v1\.[0-9a-f]{64}"$/;
|
|
62
|
-
async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded) {
|
|
62
|
+
async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes) {
|
|
63
63
|
const requestId = safeRequestId(response.headers.get("x-request-id"));
|
|
64
64
|
if (requestId === null) {
|
|
65
65
|
cancelResponse(response);
|
|
66
66
|
throw new DriveError("invalid_response", { status: response.status });
|
|
67
67
|
}
|
|
68
|
-
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded);
|
|
68
|
+
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes);
|
|
69
69
|
const { value } = await parseBoundedJson(response, SUCCESS_BODY_LIMIT, response.status, requestId, operationSignal);
|
|
70
70
|
const status = response.status;
|
|
71
71
|
if (!guard(value, status, response.headers)) throw new DriveError("invalid_response", {
|
|
@@ -92,7 +92,7 @@ function parseGrantEtag(value) {
|
|
|
92
92
|
const grantRevision = Number(match[2]);
|
|
93
93
|
return Number.isSafeInteger(collectionRevision) && Number.isSafeInteger(grantRevision) ? [collectionRevision, grantRevision] : void 0;
|
|
94
94
|
}
|
|
95
|
-
async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded) {
|
|
95
|
+
async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
|
|
96
96
|
let parsed;
|
|
97
97
|
try {
|
|
98
98
|
parsed = await parseBoundedJson(response, ERROR_BODY_LIMIT, response.status, headerRequestId, signal);
|
|
@@ -114,7 +114,7 @@ async function normalizeError(response, headerRequestId, signal, preconditionSta
|
|
|
114
114
|
requestId: headerRequestId
|
|
115
115
|
});
|
|
116
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) || parsed.text !== JSON.stringify(value)) return new DriveError("invalid_response", {
|
|
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
118
|
status: response.status,
|
|
119
119
|
requestId: headerRequestId
|
|
120
120
|
});
|
|
@@ -123,7 +123,8 @@ async function normalizeError(response, headerRequestId, signal, preconditionSta
|
|
|
123
123
|
requestId: envelope.requestId
|
|
124
124
|
});
|
|
125
125
|
}
|
|
126
|
-
function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded) {
|
|
126
|
+
function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
|
|
127
|
+
if (allowedErrorCodes && !allowedErrorCodes.includes(code)) return false;
|
|
127
128
|
if (code === "quota_exceeded" && !allowsQuotaExceeded) return false;
|
|
128
129
|
return {
|
|
129
130
|
authentication_required: [401],
|
|
@@ -133,7 +134,7 @@ function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceede
|
|
|
133
134
|
invalid_request: [422],
|
|
134
135
|
invalid_pagination_cursor: [422],
|
|
135
136
|
invalid_idempotency_key: [422],
|
|
136
|
-
precondition_failed: [preconditionStatus],
|
|
137
|
+
precondition_failed: preconditionStatus === null ? [] : [preconditionStatus],
|
|
137
138
|
idempotency_conflict: [409],
|
|
138
139
|
quota_exceeded: [409],
|
|
139
140
|
service_unavailable: [503],
|
|
@@ -269,6 +270,16 @@ const EFFECTIVE_ACTIONS = Object.freeze([
|
|
|
269
270
|
]);
|
|
270
271
|
const MAX_UPLOAD_BYTE_LENGTH$1 = 33554432e4;
|
|
271
272
|
const UPLOAD_QUOTA_EXPIRY_MILLISECONDS = 864e5;
|
|
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);
|
|
282
|
+
}
|
|
272
283
|
function isFolderPage(value, workspaceId, parentItemId) {
|
|
273
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;
|
|
274
285
|
return value.items.every((item) => item.workspaceId === workspaceId && item.parentItemId === parentItemId) && isStrictlyOrdered(value.items, (item) => item.itemId);
|
|
@@ -447,6 +458,10 @@ const PERMISSION_ACTIONS = Object.freeze([
|
|
|
447
458
|
]);
|
|
448
459
|
const IDEMPOTENCY_KEY = /^[A-Za-z0-9_-]{16,128}$/;
|
|
449
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 };
|
|
464
|
+
}
|
|
450
465
|
function validateResourceInput(value) {
|
|
451
466
|
const input = captureRecord(value, ["workspaceId", "itemId"], ["signal"]);
|
|
452
467
|
const workspaceId = input.workspaceId;
|
|
@@ -1146,7 +1161,7 @@ function createClientRuntime(config) {
|
|
|
1146
1161
|
if (typeof runtime.fetchImplementation !== "function" || typeof runtime.getCredential !== "function") throw new DriveError("invalid_input");
|
|
1147
1162
|
return runtime;
|
|
1148
1163
|
}
|
|
1149
|
-
async function execute(runtime, signal, preconditionStatus, send, successStatuses, guard, allowsQuotaExceeded = false) {
|
|
1164
|
+
async function execute(runtime, signal, preconditionStatus, send, successStatuses, guard, allowsQuotaExceeded = false, allowedErrorCodes) {
|
|
1150
1165
|
const operation = createOperationSignal(signal, runtime.timeoutMilliseconds);
|
|
1151
1166
|
try {
|
|
1152
1167
|
const operationSignal = operation.signal;
|
|
@@ -1173,7 +1188,7 @@ async function execute(runtime, signal, preconditionStatus, send, successStatuse
|
|
|
1173
1188
|
signal: operationSignal
|
|
1174
1189
|
});
|
|
1175
1190
|
if (!capturedResponse) throw new DriveError("network_error");
|
|
1176
|
-
return await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded);
|
|
1191
|
+
return await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes);
|
|
1177
1192
|
} catch (error) {
|
|
1178
1193
|
if (operation.didTimeout()) throw new DriveError("timeout");
|
|
1179
1194
|
if (error instanceof DriveError) throw error;
|
|
@@ -1253,9 +1268,18 @@ async function raceWithAbort(promise, signal) {
|
|
|
1253
1268
|
}
|
|
1254
1269
|
//#endregion
|
|
1255
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
|
+
]);
|
|
1256
1279
|
function createDriveClientInternal(config) {
|
|
1257
1280
|
const runtime = createClientRuntime(config);
|
|
1258
1281
|
return Object.freeze({
|
|
1282
|
+
getCurrentWorkspace: (input) => getCurrentWorkspace(runtime, input),
|
|
1259
1283
|
listFolderChildren: (input) => listFolderChildren(runtime, input),
|
|
1260
1284
|
createFolder: (input) => createFolder(runtime, input),
|
|
1261
1285
|
listItemPermissions: (input) => listItemPermissions(runtime, input),
|
|
@@ -1267,6 +1291,12 @@ function createDriveClientInternal(config) {
|
|
|
1267
1291
|
abortUpload: (input) => abortUpload(runtime, input)
|
|
1268
1292
|
});
|
|
1269
1293
|
}
|
|
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);
|
|
1299
|
+
}
|
|
1270
1300
|
async function listFolderChildren(runtime, input) {
|
|
1271
1301
|
const validated = validatePageInput(input);
|
|
1272
1302
|
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/children", {
|
package/dist/contract.d.ts
CHANGED
|
@@ -1,5 +1,137 @@
|
|
|
1
1
|
//#region src/generated/openapi.d.ts
|
|
2
2
|
interface operations {
|
|
3
|
+
getCurrentWorkspace: {
|
|
4
|
+
parameters: {
|
|
5
|
+
query?: never;
|
|
6
|
+
header?: never;
|
|
7
|
+
path?: never;
|
|
8
|
+
cookie?: never;
|
|
9
|
+
};
|
|
10
|
+
requestBody?: never;
|
|
11
|
+
responses: {
|
|
12
|
+
/** @description The exact managed workspace and canonical root selected by the Drive credential. */
|
|
13
|
+
200: {
|
|
14
|
+
headers: {
|
|
15
|
+
[name: string]: unknown;
|
|
16
|
+
};
|
|
17
|
+
content: {
|
|
18
|
+
"application/json": {
|
|
19
|
+
rootItemId: string;
|
|
20
|
+
rootVolumeId: string;
|
|
21
|
+
workspaceId: string;
|
|
22
|
+
workspaceReference: {
|
|
23
|
+
/** @enum {string} */
|
|
24
|
+
type: "personal";
|
|
25
|
+
userId: string;
|
|
26
|
+
} | {
|
|
27
|
+
organizationId: string;
|
|
28
|
+
/** @enum {string} */
|
|
29
|
+
type: "organization";
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
/** @description A valid Drive user bearer credential is required. */
|
|
35
|
+
401: {
|
|
36
|
+
headers: {
|
|
37
|
+
[name: string]: unknown;
|
|
38
|
+
};
|
|
39
|
+
content: {
|
|
40
|
+
"application/json": {
|
|
41
|
+
error: {
|
|
42
|
+
/** @enum {string} */
|
|
43
|
+
code: "authentication_required";
|
|
44
|
+
details: Record<string, never>;
|
|
45
|
+
/** @enum {string} */
|
|
46
|
+
message: "Authentication is required.";
|
|
47
|
+
requestId: string;
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
/** @description Managed storage is disabled for the current workspace. */
|
|
53
|
+
403: {
|
|
54
|
+
headers: {
|
|
55
|
+
[name: string]: unknown;
|
|
56
|
+
};
|
|
57
|
+
content: {
|
|
58
|
+
"application/json": {
|
|
59
|
+
error: {
|
|
60
|
+
/** @enum {string} */
|
|
61
|
+
code: "permission_denied";
|
|
62
|
+
details: Record<string, never>;
|
|
63
|
+
/** @enum {string} */
|
|
64
|
+
message: "The requested action is not permitted.";
|
|
65
|
+
requestId: string;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
/** @description The selected Auth workspace is not provisioned or is not available to this User. */
|
|
71
|
+
404: {
|
|
72
|
+
headers: {
|
|
73
|
+
[name: string]: unknown;
|
|
74
|
+
};
|
|
75
|
+
content: {
|
|
76
|
+
"application/json": {
|
|
77
|
+
error: {
|
|
78
|
+
/** @enum {string} */
|
|
79
|
+
code: "resource_not_found";
|
|
80
|
+
details: Record<string, never>;
|
|
81
|
+
/** @enum {string} */
|
|
82
|
+
message: "The requested resource was not found.";
|
|
83
|
+
requestId: string;
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
/** @description The request contains unsupported query input. */
|
|
89
|
+
422: {
|
|
90
|
+
headers: {
|
|
91
|
+
[name: string]: unknown;
|
|
92
|
+
};
|
|
93
|
+
content: {
|
|
94
|
+
"application/json": {
|
|
95
|
+
error: {
|
|
96
|
+
/** @enum {string} */
|
|
97
|
+
code: "invalid_request";
|
|
98
|
+
details: Record<string, never>;
|
|
99
|
+
/** @enum {string} */
|
|
100
|
+
message: "The request is invalid.";
|
|
101
|
+
requestId: string;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
/** @description Identity authority, D1, or the canonical managed root is unavailable. */
|
|
107
|
+
503: {
|
|
108
|
+
headers: {
|
|
109
|
+
[name: string]: unknown;
|
|
110
|
+
};
|
|
111
|
+
content: {
|
|
112
|
+
"application/json": {
|
|
113
|
+
error: {
|
|
114
|
+
/** @enum {string} */
|
|
115
|
+
code: "identity_authority_unavailable";
|
|
116
|
+
details: Record<string, never>;
|
|
117
|
+
/** @enum {string} */
|
|
118
|
+
message: "Authentication is temporarily unavailable.";
|
|
119
|
+
requestId: string;
|
|
120
|
+
};
|
|
121
|
+
} | {
|
|
122
|
+
error: {
|
|
123
|
+
/** @enum {string} */
|
|
124
|
+
code: "service_unavailable";
|
|
125
|
+
details: Record<string, never>;
|
|
126
|
+
/** @enum {string} */
|
|
127
|
+
message: "The service is temporarily unavailable.";
|
|
128
|
+
requestId: string;
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
};
|
|
3
135
|
listFolderChildren: {
|
|
4
136
|
parameters: {
|
|
5
137
|
query?: {
|
|
@@ -1754,6 +1886,10 @@ type CreateUploadPath = operations["createUpload"]["parameters"]["path"];
|
|
|
1754
1886
|
type CreateUploadHeaders = operations["createUpload"]["parameters"]["header"];
|
|
1755
1887
|
type CreateUploadBody = JsonRequest<"createUpload">;
|
|
1756
1888
|
type AbortUploadPath = operations["abortUpload"]["parameters"]["path"];
|
|
1889
|
+
type GeneratedCurrentWorkspace = JsonResponse<"getCurrentWorkspace", 200>;
|
|
1890
|
+
type CurrentWorkspace = Readonly<Omit<GeneratedCurrentWorkspace, "workspaceReference"> & {
|
|
1891
|
+
readonly workspaceReference: Readonly<GeneratedCurrentWorkspace["workspaceReference"]>;
|
|
1892
|
+
}>;
|
|
1757
1893
|
type FolderItem = Readonly<JsonResponse<"createFolder", 201>>;
|
|
1758
1894
|
type ReservedUploadQuota = Readonly<JsonResponse<"createUpload", 201>>;
|
|
1759
1895
|
type AbortedUploadQuota = Readonly<JsonResponse<"abortUpload", 200>>;
|
|
@@ -1841,7 +1977,11 @@ type CreateUploadInput = Readonly<CreateUploadPath> & Readonly<CreateUploadBody>
|
|
|
1841
1977
|
type AbortUploadInput = Readonly<AbortUploadPath> & {
|
|
1842
1978
|
readonly signal?: AbortSignal;
|
|
1843
1979
|
};
|
|
1980
|
+
interface GetCurrentWorkspaceInput {
|
|
1981
|
+
readonly signal?: AbortSignal;
|
|
1982
|
+
}
|
|
1844
1983
|
interface DriveClient {
|
|
1984
|
+
getCurrentWorkspace(input?: GetCurrentWorkspaceInput): Promise<DriveOperationResult<CurrentWorkspace, 200>>;
|
|
1845
1985
|
listFolderChildren(input: ListFolderChildrenInput): Promise<DriveOperationResult<FolderPage, 200>>;
|
|
1846
1986
|
createFolder(input: CreateFolderInput): Promise<DriveOperationResult<FolderItem, 200 | 201>>;
|
|
1847
1987
|
listItemPermissions(input: ListItemPermissionsInput): Promise<DriveOperationResult<PermissionPage, 200>>;
|
|
@@ -1853,4 +1993,4 @@ interface DriveClient {
|
|
|
1853
1993
|
abortUpload(input: AbortUploadInput): Promise<DriveOperationResult<AbortedUploadQuota, 200>>;
|
|
1854
1994
|
}
|
|
1855
1995
|
//#endregion
|
|
1856
|
-
export {
|
|
1996
|
+
export { UploadQuotaReservation as A, PermissionGrantee as C, ReservedUploadQuota as D, ReadEffectiveItemPermissionsInput as E, RevokeItemPermissionInput as O, PermissionGrant as S, PermissionPage as T, FolderPage as _, CreateUploadInput as a, ListItemPermissionsInput as b, DriveClientConfig as c, DriveOperationResult as d, DriveResponseValidators as f, FolderItem as g, EffectivePermissionResponse as h, CreateItemPermissionInput as i, UpdateItemPermissionInput as k, DriveCredentialContext as l, EffectivePermissionAction as m, AbortedUploadQuota as n, CurrentWorkspace as o, DriveServerClientConfig as p, CreateFolderInput as r, DriveClient as s, AbortUploadInput as t, DriveCredentialProvider as u, GetCurrentWorkspaceInput as v, PermissionMutation as w, PermissionAction as x, ListFolderChildrenInput as y };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as UploadQuotaReservation, C as PermissionGrantee, D as ReservedUploadQuota, E as ReadEffectiveItemPermissionsInput, O as RevokeItemPermissionInput, S as PermissionGrant, _ as FolderPage, a as CreateUploadInput, b as ListItemPermissionsInput, c as DriveClientConfig, d as DriveOperationResult, f as DriveResponseValidators, g as FolderItem, i as CreateItemPermissionInput, k as UpdateItemPermissionInput, m as EffectivePermissionAction, n as AbortedUploadQuota, o as CurrentWorkspace, r as CreateFolderInput, s as DriveClient, t as AbortUploadInput, u as DriveCredentialProvider, v as GetCurrentWorkspaceInput, w as PermissionMutation, x as PermissionAction, y as ListFolderChildrenInput } from "./contract.js";
|
|
2
2
|
import { createDriveClient } from "./client.js";
|
|
3
3
|
import { DRIVE_API_ERROR_CODES, DRIVE_API_ERROR_MESSAGES, DriveApiErrorCode, DriveError, DriveErrorCode, DriveSdkErrorCode } from "./core.js";
|
|
4
|
-
export { type AbortUploadInput, type AbortedUploadQuota, type CreateFolderInput, type CreateItemPermissionInput, type CreateUploadInput, DRIVE_API_ERROR_CODES, DRIVE_API_ERROR_MESSAGES, type DriveApiErrorCode, type DriveClient, type DriveClientConfig, type DriveCredentialProvider, DriveError, type DriveErrorCode, type DriveOperationResult, type DriveResponseValidators, type DriveSdkErrorCode, type EffectivePermissionAction, type FolderItem, type ListFolderChildrenInput, type ListItemPermissionsInput, type PermissionAction, type PermissionGrant, type PermissionGrantee, type PermissionMutation, type ReadEffectiveItemPermissionsInput, type ReservedUploadQuota, type RevokeItemPermissionInput, type UpdateItemPermissionInput, type UploadQuotaReservation, createDriveClient };
|
|
4
|
+
export { type AbortUploadInput, type AbortedUploadQuota, type CreateFolderInput, type CreateItemPermissionInput, type CreateUploadInput, type CurrentWorkspace, DRIVE_API_ERROR_CODES, DRIVE_API_ERROR_MESSAGES, type DriveApiErrorCode, type DriveClient, type DriveClientConfig, type DriveCredentialProvider, DriveError, type DriveErrorCode, type DriveOperationResult, type DriveResponseValidators, type DriveSdkErrorCode, type EffectivePermissionAction, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type ListFolderChildrenInput, type ListItemPermissionsInput, type PermissionAction, type PermissionGrant, type PermissionGrantee, type PermissionMutation, type ReadEffectiveItemPermissionsInput, type ReservedUploadQuota, type RevokeItemPermissionInput, type UpdateItemPermissionInput, type UploadQuotaReservation, createDriveClient };
|
package/dist/index.js
CHANGED
|
@@ -59,13 +59,13 @@ const REQUEST_ID = /^[A-Za-z0-9_-]{16,128}$/;
|
|
|
59
59
|
const COLLECTION_ETAG = /^"drive\.permission-collection\.v1\.(0|[1-9][0-9]*)"$/;
|
|
60
60
|
const GRANT_ETAG$1 = /^"drive\.permission-grant\.v1\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"$/;
|
|
61
61
|
const LIST_ETAG$1 = /^"drive\.permission-list\.v1\.[0-9a-f]{64}"$/;
|
|
62
|
-
async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded) {
|
|
62
|
+
async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes) {
|
|
63
63
|
const requestId = safeRequestId(response.headers.get("x-request-id"));
|
|
64
64
|
if (requestId === null) {
|
|
65
65
|
cancelResponse(response);
|
|
66
66
|
throw new DriveError("invalid_response", { status: response.status });
|
|
67
67
|
}
|
|
68
|
-
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded);
|
|
68
|
+
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes);
|
|
69
69
|
const { value } = await parseBoundedJson(response, SUCCESS_BODY_LIMIT, response.status, requestId, operationSignal);
|
|
70
70
|
const status = response.status;
|
|
71
71
|
if (!guard(value, status, response.headers)) throw new DriveError("invalid_response", {
|
|
@@ -92,7 +92,7 @@ function parseGrantEtag(value) {
|
|
|
92
92
|
const grantRevision = Number(match[2]);
|
|
93
93
|
return Number.isSafeInteger(collectionRevision) && Number.isSafeInteger(grantRevision) ? [collectionRevision, grantRevision] : void 0;
|
|
94
94
|
}
|
|
95
|
-
async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded) {
|
|
95
|
+
async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
|
|
96
96
|
let parsed;
|
|
97
97
|
try {
|
|
98
98
|
parsed = await parseBoundedJson(response, ERROR_BODY_LIMIT, response.status, headerRequestId, signal);
|
|
@@ -114,7 +114,7 @@ async function normalizeError(response, headerRequestId, signal, preconditionSta
|
|
|
114
114
|
requestId: headerRequestId
|
|
115
115
|
});
|
|
116
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) || parsed.text !== JSON.stringify(value)) return new DriveError("invalid_response", {
|
|
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
118
|
status: response.status,
|
|
119
119
|
requestId: headerRequestId
|
|
120
120
|
});
|
|
@@ -123,7 +123,8 @@ async function normalizeError(response, headerRequestId, signal, preconditionSta
|
|
|
123
123
|
requestId: envelope.requestId
|
|
124
124
|
});
|
|
125
125
|
}
|
|
126
|
-
function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded) {
|
|
126
|
+
function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
|
|
127
|
+
if (allowedErrorCodes && !allowedErrorCodes.includes(code)) return false;
|
|
127
128
|
if (code === "quota_exceeded" && !allowsQuotaExceeded) return false;
|
|
128
129
|
return {
|
|
129
130
|
authentication_required: [401],
|
|
@@ -133,7 +134,7 @@ function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceede
|
|
|
133
134
|
invalid_request: [422],
|
|
134
135
|
invalid_pagination_cursor: [422],
|
|
135
136
|
invalid_idempotency_key: [422],
|
|
136
|
-
precondition_failed: [preconditionStatus],
|
|
137
|
+
precondition_failed: preconditionStatus === null ? [] : [preconditionStatus],
|
|
137
138
|
idempotency_conflict: [409],
|
|
138
139
|
quota_exceeded: [409],
|
|
139
140
|
service_unavailable: [503],
|
|
@@ -269,6 +270,16 @@ const EFFECTIVE_ACTIONS = Object.freeze([
|
|
|
269
270
|
]);
|
|
270
271
|
const MAX_UPLOAD_BYTE_LENGTH$1 = 33554432e4;
|
|
271
272
|
const UPLOAD_QUOTA_EXPIRY_MILLISECONDS = 864e5;
|
|
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);
|
|
282
|
+
}
|
|
272
283
|
function isFolderPage(value, workspaceId, parentItemId) {
|
|
273
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;
|
|
274
285
|
return value.items.every((item) => item.workspaceId === workspaceId && item.parentItemId === parentItemId) && isStrictlyOrdered(value.items, (item) => item.itemId);
|
|
@@ -447,6 +458,10 @@ const PERMISSION_ACTIONS = Object.freeze([
|
|
|
447
458
|
]);
|
|
448
459
|
const IDEMPOTENCY_KEY = /^[A-Za-z0-9_-]{16,128}$/;
|
|
449
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 };
|
|
464
|
+
}
|
|
450
465
|
function validateResourceInput(value) {
|
|
451
466
|
const input = captureRecord(value, ["workspaceId", "itemId"], ["signal"]);
|
|
452
467
|
const workspaceId = input.workspaceId;
|
|
@@ -1146,7 +1161,7 @@ function createClientRuntime(config) {
|
|
|
1146
1161
|
if (typeof runtime.fetchImplementation !== "function" || typeof runtime.getCredential !== "function") throw new DriveError("invalid_input");
|
|
1147
1162
|
return runtime;
|
|
1148
1163
|
}
|
|
1149
|
-
async function execute(runtime, signal, preconditionStatus, send, successStatuses, guard, allowsQuotaExceeded = false) {
|
|
1164
|
+
async function execute(runtime, signal, preconditionStatus, send, successStatuses, guard, allowsQuotaExceeded = false, allowedErrorCodes) {
|
|
1150
1165
|
const operation = createOperationSignal(signal, runtime.timeoutMilliseconds);
|
|
1151
1166
|
try {
|
|
1152
1167
|
const operationSignal = operation.signal;
|
|
@@ -1173,7 +1188,7 @@ async function execute(runtime, signal, preconditionStatus, send, successStatuse
|
|
|
1173
1188
|
signal: operationSignal
|
|
1174
1189
|
});
|
|
1175
1190
|
if (!capturedResponse) throw new DriveError("network_error");
|
|
1176
|
-
return await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded);
|
|
1191
|
+
return await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes);
|
|
1177
1192
|
} catch (error) {
|
|
1178
1193
|
if (operation.didTimeout()) throw new DriveError("timeout");
|
|
1179
1194
|
if (error instanceof DriveError) throw error;
|
|
@@ -1253,9 +1268,18 @@ async function raceWithAbort(promise, signal) {
|
|
|
1253
1268
|
}
|
|
1254
1269
|
//#endregion
|
|
1255
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
|
+
]);
|
|
1256
1279
|
function createDriveClientInternal(config) {
|
|
1257
1280
|
const runtime = createClientRuntime(config);
|
|
1258
1281
|
return Object.freeze({
|
|
1282
|
+
getCurrentWorkspace: (input) => getCurrentWorkspace(runtime, input),
|
|
1259
1283
|
listFolderChildren: (input) => listFolderChildren(runtime, input),
|
|
1260
1284
|
createFolder: (input) => createFolder(runtime, input),
|
|
1261
1285
|
listItemPermissions: (input) => listItemPermissions(runtime, input),
|
|
@@ -1267,6 +1291,12 @@ function createDriveClientInternal(config) {
|
|
|
1267
1291
|
abortUpload: (input) => abortUpload(runtime, input)
|
|
1268
1292
|
});
|
|
1269
1293
|
}
|
|
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);
|
|
1299
|
+
}
|
|
1270
1300
|
async function listFolderChildren(runtime, input) {
|
|
1271
1301
|
const validated = validatePageInput(input);
|
|
1272
1302
|
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/children", {
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as UploadQuotaReservation, D as ReservedUploadQuota, _ as FolderPage, a as CreateUploadInput, g as FolderItem, n as AbortedUploadQuota, o as CurrentWorkspace, p as DriveServerClientConfig, s as DriveClient, t as AbortUploadInput, v as GetCurrentWorkspaceInput, y as ListFolderChildrenInput } from "./contract.js";
|
|
2
2
|
//#region src/server.d.ts
|
|
3
3
|
declare function createDriveServerClient(config: DriveServerClientConfig): DriveClient;
|
|
4
4
|
//#endregion
|
|
5
|
-
export { type AbortUploadInput, type AbortedUploadQuota, type CreateUploadInput, type DriveClient, type DriveServerClientConfig, type ReservedUploadQuota, type UploadQuotaReservation, createDriveServerClient };
|
|
5
|
+
export { type AbortUploadInput, type AbortedUploadQuota, type CreateUploadInput, type CurrentWorkspace, type DriveClient, type DriveServerClientConfig, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type ListFolderChildrenInput, type ReservedUploadQuota, type UploadQuotaReservation, createDriveServerClient };
|
package/dist/server.js
CHANGED
|
@@ -59,13 +59,13 @@ const REQUEST_ID = /^[A-Za-z0-9_-]{16,128}$/;
|
|
|
59
59
|
const COLLECTION_ETAG = /^"drive\.permission-collection\.v1\.(0|[1-9][0-9]*)"$/;
|
|
60
60
|
const GRANT_ETAG$1 = /^"drive\.permission-grant\.v1\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)"$/;
|
|
61
61
|
const LIST_ETAG$1 = /^"drive\.permission-list\.v1\.[0-9a-f]{64}"$/;
|
|
62
|
-
async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded) {
|
|
62
|
+
async function parseResponse(response, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes) {
|
|
63
63
|
const requestId = safeRequestId(response.headers.get("x-request-id"));
|
|
64
64
|
if (requestId === null) {
|
|
65
65
|
cancelResponse(response);
|
|
66
66
|
throw new DriveError("invalid_response", { status: response.status });
|
|
67
67
|
}
|
|
68
|
-
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded);
|
|
68
|
+
if (!successStatuses.includes(response.status)) throw await normalizeError(response, requestId, operationSignal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes);
|
|
69
69
|
const { value } = await parseBoundedJson(response, SUCCESS_BODY_LIMIT, response.status, requestId, operationSignal);
|
|
70
70
|
const status = response.status;
|
|
71
71
|
if (!guard(value, status, response.headers)) throw new DriveError("invalid_response", {
|
|
@@ -92,7 +92,7 @@ function parseGrantEtag(value) {
|
|
|
92
92
|
const grantRevision = Number(match[2]);
|
|
93
93
|
return Number.isSafeInteger(collectionRevision) && Number.isSafeInteger(grantRevision) ? [collectionRevision, grantRevision] : void 0;
|
|
94
94
|
}
|
|
95
|
-
async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded) {
|
|
95
|
+
async function normalizeError(response, headerRequestId, signal, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
|
|
96
96
|
let parsed;
|
|
97
97
|
try {
|
|
98
98
|
parsed = await parseBoundedJson(response, ERROR_BODY_LIMIT, response.status, headerRequestId, signal);
|
|
@@ -114,7 +114,7 @@ async function normalizeError(response, headerRequestId, signal, preconditionSta
|
|
|
114
114
|
requestId: headerRequestId
|
|
115
115
|
});
|
|
116
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) || parsed.text !== JSON.stringify(value)) return new DriveError("invalid_response", {
|
|
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
118
|
status: response.status,
|
|
119
119
|
requestId: headerRequestId
|
|
120
120
|
});
|
|
@@ -123,7 +123,8 @@ async function normalizeError(response, headerRequestId, signal, preconditionSta
|
|
|
123
123
|
requestId: envelope.requestId
|
|
124
124
|
});
|
|
125
125
|
}
|
|
126
|
-
function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded) {
|
|
126
|
+
function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceeded, allowedErrorCodes) {
|
|
127
|
+
if (allowedErrorCodes && !allowedErrorCodes.includes(code)) return false;
|
|
127
128
|
if (code === "quota_exceeded" && !allowsQuotaExceeded) return false;
|
|
128
129
|
return {
|
|
129
130
|
authentication_required: [401],
|
|
@@ -133,7 +134,7 @@ function errorStatusMatches(code, status, preconditionStatus, allowsQuotaExceede
|
|
|
133
134
|
invalid_request: [422],
|
|
134
135
|
invalid_pagination_cursor: [422],
|
|
135
136
|
invalid_idempotency_key: [422],
|
|
136
|
-
precondition_failed: [preconditionStatus],
|
|
137
|
+
precondition_failed: preconditionStatus === null ? [] : [preconditionStatus],
|
|
137
138
|
idempotency_conflict: [409],
|
|
138
139
|
quota_exceeded: [409],
|
|
139
140
|
service_unavailable: [503],
|
|
@@ -269,6 +270,16 @@ const EFFECTIVE_ACTIONS = Object.freeze([
|
|
|
269
270
|
]);
|
|
270
271
|
const MAX_UPLOAD_BYTE_LENGTH$1 = 33554432e4;
|
|
271
272
|
const UPLOAD_QUOTA_EXPIRY_MILLISECONDS = 864e5;
|
|
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);
|
|
282
|
+
}
|
|
272
283
|
function isFolderPage(value, workspaceId, parentItemId) {
|
|
273
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;
|
|
274
285
|
return value.items.every((item) => item.workspaceId === workspaceId && item.parentItemId === parentItemId) && isStrictlyOrdered(value.items, (item) => item.itemId);
|
|
@@ -447,6 +458,10 @@ const PERMISSION_ACTIONS = Object.freeze([
|
|
|
447
458
|
]);
|
|
448
459
|
const IDEMPOTENCY_KEY = /^[A-Za-z0-9_-]{16,128}$/;
|
|
449
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 };
|
|
464
|
+
}
|
|
450
465
|
function validateResourceInput(value) {
|
|
451
466
|
const input = captureRecord(value, ["workspaceId", "itemId"], ["signal"]);
|
|
452
467
|
const workspaceId = input.workspaceId;
|
|
@@ -1146,7 +1161,7 @@ function createClientRuntime(config) {
|
|
|
1146
1161
|
if (typeof runtime.fetchImplementation !== "function" || typeof runtime.getCredential !== "function") throw new DriveError("invalid_input");
|
|
1147
1162
|
return runtime;
|
|
1148
1163
|
}
|
|
1149
|
-
async function execute(runtime, signal, preconditionStatus, send, successStatuses, guard, allowsQuotaExceeded = false) {
|
|
1164
|
+
async function execute(runtime, signal, preconditionStatus, send, successStatuses, guard, allowsQuotaExceeded = false, allowedErrorCodes) {
|
|
1150
1165
|
const operation = createOperationSignal(signal, runtime.timeoutMilliseconds);
|
|
1151
1166
|
try {
|
|
1152
1167
|
const operationSignal = operation.signal;
|
|
@@ -1173,7 +1188,7 @@ async function execute(runtime, signal, preconditionStatus, send, successStatuse
|
|
|
1173
1188
|
signal: operationSignal
|
|
1174
1189
|
});
|
|
1175
1190
|
if (!capturedResponse) throw new DriveError("network_error");
|
|
1176
|
-
return await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded);
|
|
1191
|
+
return await parseResponse(capturedResponse, operationSignal, preconditionStatus, successStatuses, guard, allowsQuotaExceeded, allowedErrorCodes);
|
|
1177
1192
|
} catch (error) {
|
|
1178
1193
|
if (operation.didTimeout()) throw new DriveError("timeout");
|
|
1179
1194
|
if (error instanceof DriveError) throw error;
|
|
@@ -1253,9 +1268,18 @@ async function raceWithAbort(promise, signal) {
|
|
|
1253
1268
|
}
|
|
1254
1269
|
//#endregion
|
|
1255
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
|
+
]);
|
|
1256
1279
|
function createDriveClientInternal(config) {
|
|
1257
1280
|
const runtime = createClientRuntime(config);
|
|
1258
1281
|
return Object.freeze({
|
|
1282
|
+
getCurrentWorkspace: (input) => getCurrentWorkspace(runtime, input),
|
|
1259
1283
|
listFolderChildren: (input) => listFolderChildren(runtime, input),
|
|
1260
1284
|
createFolder: (input) => createFolder(runtime, input),
|
|
1261
1285
|
listItemPermissions: (input) => listItemPermissions(runtime, input),
|
|
@@ -1267,6 +1291,12 @@ function createDriveClientInternal(config) {
|
|
|
1267
1291
|
abortUpload: (input) => abortUpload(runtime, input)
|
|
1268
1292
|
});
|
|
1269
1293
|
}
|
|
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);
|
|
1299
|
+
}
|
|
1270
1300
|
async function listFolderChildren(runtime, input) {
|
|
1271
1301
|
const validated = validatePageInput(input);
|
|
1272
1302
|
return execute(runtime, validated.signal, 409, (api, requestOptions) => api.GET("/api/v1/workspaces/{workspaceId}/items/{itemId}/children", {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as
|
|
2
|
-
export { AbortUploadInput, AbortedUploadQuota, CreateFolderInput, CreateItemPermissionInput, CreateUploadInput, DriveClient, DriveClientConfig, DriveCredentialContext, DriveCredentialProvider, DriveOperationResult, DriveResponseValidators, DriveServerClientConfig, EffectivePermissionAction, EffectivePermissionResponse, FolderItem, FolderPage, ListFolderChildrenInput, ListItemPermissionsInput, PermissionAction, PermissionGrant, PermissionGrantee, PermissionMutation, PermissionPage, ReadEffectiveItemPermissionsInput, ReservedUploadQuota, RevokeItemPermissionInput, UpdateItemPermissionInput, UploadQuotaReservation };
|
|
1
|
+
import { A as UploadQuotaReservation, C as PermissionGrantee, D as ReservedUploadQuota, E as ReadEffectiveItemPermissionsInput, O as RevokeItemPermissionInput, S as PermissionGrant, T as PermissionPage, _ as FolderPage, a as CreateUploadInput, b as ListItemPermissionsInput, c as DriveClientConfig, d as DriveOperationResult, f as DriveResponseValidators, g as FolderItem, h as EffectivePermissionResponse, i as CreateItemPermissionInput, k as UpdateItemPermissionInput, l as DriveCredentialContext, m as EffectivePermissionAction, n as AbortedUploadQuota, o as CurrentWorkspace, p as DriveServerClientConfig, r as CreateFolderInput, s as DriveClient, t as AbortUploadInput, u as DriveCredentialProvider, v as GetCurrentWorkspaceInput, w as PermissionMutation, x as PermissionAction, y as ListFolderChildrenInput } from "./contract.js";
|
|
2
|
+
export { AbortUploadInput, AbortedUploadQuota, CreateFolderInput, CreateItemPermissionInput, CreateUploadInput, CurrentWorkspace, DriveClient, DriveClientConfig, DriveCredentialContext, DriveCredentialProvider, DriveOperationResult, DriveResponseValidators, DriveServerClientConfig, EffectivePermissionAction, EffectivePermissionResponse, FolderItem, FolderPage, GetCurrentWorkspaceInput, ListFolderChildrenInput, ListItemPermissionsInput, PermissionAction, PermissionGrant, PermissionGrantee, PermissionMutation, PermissionPage, ReadEffectiveItemPermissionsInput, ReservedUploadQuota, RevokeItemPermissionInput, UpdateItemPermissionInput, UploadQuotaReservation };
|