@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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @finueva/drive
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8e472b7: Add `getCurrentWorkspace` for resolving the authenticated Drive workspace and canonical managed root.
8
+
3
9
  ## 0.1.1
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -1,18 +1,18 @@
1
1
  # `@finueva/drive`
2
2
 
3
- The public TypeScript client for Finueva Drive. Version `0.1.0` is published to npm; the initial API remains Local Experimental.
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
- This release prepares `0.1.0` from the reviewed minor 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.
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` does not yet exist on npm. The source repository is private, so public provenance is unavailable. First publication must follow ADR 0016's exact retained-artifact maintainer-2FA bootstrap. The protected OIDC workflow stages only later releases after npm trusts the exact workflow; it has no npm token and cannot bootstrap the package itself.
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 { O as UploadQuotaReservation, T as ReservedUploadQuota, a as CreateUploadInput, l as DriveCredentialProvider, n as AbortedUploadQuota, o as DriveClient, s as DriveClientConfig, t as AbortUploadInput } from "./contract.js";
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", {
@@ -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 { PermissionPage as C, UpdateItemPermissionInput as D, RevokeItemPermissionInput as E, UploadQuotaReservation as O, PermissionMutation as S, ReservedUploadQuota as T, ListFolderChildrenInput as _, CreateUploadInput as a, PermissionGrant as b, DriveCredentialContext as c, DriveResponseValidators as d, DriveServerClientConfig as f, FolderPage as g, FolderItem as h, CreateItemPermissionInput as i, DriveCredentialProvider as l, EffectivePermissionResponse as m, AbortedUploadQuota as n, DriveClient as o, EffectivePermissionAction as p, CreateFolderInput as r, DriveClientConfig as s, AbortUploadInput as t, DriveOperationResult as u, ListItemPermissionsInput as v, ReadEffectiveItemPermissionsInput as w, PermissionGrantee as x, PermissionAction as y };
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 { D as UpdateItemPermissionInput, E as RevokeItemPermissionInput, O as UploadQuotaReservation, S as PermissionMutation, T as ReservedUploadQuota, _ as ListFolderChildrenInput, a as CreateUploadInput, b as PermissionGrant, d as DriveResponseValidators, h as FolderItem, i as CreateItemPermissionInput, l as DriveCredentialProvider, n as AbortedUploadQuota, o as DriveClient, p as EffectivePermissionAction, r as CreateFolderInput, s as DriveClientConfig, t as AbortUploadInput, u as DriveOperationResult, v as ListItemPermissionsInput, w as ReadEffectiveItemPermissionsInput, x as PermissionGrantee, y as PermissionAction } from "./contract.js";
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 { O as UploadQuotaReservation, T as ReservedUploadQuota, a as CreateUploadInput, f as DriveServerClientConfig, n as AbortedUploadQuota, o as DriveClient, t as AbortUploadInput } from "./contract.js";
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 PermissionPage, D as UpdateItemPermissionInput, E as RevokeItemPermissionInput, O as UploadQuotaReservation, S as PermissionMutation, T as ReservedUploadQuota, _ as ListFolderChildrenInput, a as CreateUploadInput, b as PermissionGrant, c as DriveCredentialContext, d as DriveResponseValidators, f as DriveServerClientConfig, g as FolderPage, h as FolderItem, i as CreateItemPermissionInput, l as DriveCredentialProvider, m as EffectivePermissionResponse, n as AbortedUploadQuota, o as DriveClient, p as EffectivePermissionAction, r as CreateFolderInput, s as DriveClientConfig, t as AbortUploadInput, u as DriveOperationResult, v as ListItemPermissionsInput, w as ReadEffectiveItemPermissionsInput, x as PermissionGrantee, y as PermissionAction } from "./contract.js";
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finueva/drive",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Public browser, Worker, and Node client for Finueva Drive",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",