@finueva/drive 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +22 -11
- package/dist/client.js +1 -1
- package/dist/contract.d.ts +224 -1
- package/dist/index.js +1 -1
- package/dist/server.d.ts +20 -2
- package/dist/server.js +77 -2
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @finueva/drive
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5f0a6b1: Add a separate server-entry-point workspace provisioning client with explicit environment and entitlement validation, bounded service credential transport, and strict replay response checks.
|
|
8
|
+
|
|
9
|
+
## 0.5.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- b54eff9: Bind the default Fetch implementation to its global receiver so browser requests do not fail with an illegal invocation. Custom Fetch implementations and request policies are unchanged.
|
|
14
|
+
|
|
3
15
|
## 0.5.0
|
|
4
16
|
|
|
5
17
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -6,22 +6,29 @@ The package is ESM-only. Node.js 22 is the exact minimum; package CI qualifies N
|
|
|
6
6
|
|
|
7
7
|
## Exports
|
|
8
8
|
|
|
9
|
-
| Import | Runtime
|
|
10
|
-
| ----------------------- |
|
|
11
|
-
| `@finueva/drive` | Browser
|
|
12
|
-
| `@finueva/drive/client` | Browser
|
|
13
|
-
| `@finueva/drive/server` |
|
|
14
|
-
| `@finueva/drive/core` |
|
|
15
|
-
| `@finueva/drive/types` |
|
|
9
|
+
| Import | Runtime |
|
|
10
|
+
| ----------------------- | ------------------------------------ |
|
|
11
|
+
| `@finueva/drive` | Browser client, errors, types |
|
|
12
|
+
| `@finueva/drive/client` | Browser client |
|
|
13
|
+
| `@finueva/drive/server` | Worker/Node user and service clients |
|
|
14
|
+
| `@finueva/drive/core` | Error values |
|
|
15
|
+
| `@finueva/drive/types` | Public operation types |
|
|
16
16
|
|
|
17
17
|
## Browser
|
|
18
18
|
|
|
19
|
+
Approved ecosystem servers can separately use `createDriveProvisioningClient` from `/server` to call `provisionWorkspace(command)`. Configure an exact environment and `getProvisioningCredential` provider using Auth service credentials, not User credentials. Commands require a stable provisioning ID, exact workspace reference, and explicit versioned storage entitlement. The client does not infer quotas, follow redirects, or retry. See [Workspace Provisioning](../../apps/developer/docs/sdk/provisioning.md) for ownership and recovery boundaries.
|
|
20
|
+
|
|
19
21
|
```ts
|
|
20
22
|
import { createDriveClient } from "@finueva/drive";
|
|
21
23
|
|
|
22
24
|
const drive = createDriveClient({
|
|
23
25
|
baseUrl: "https://drive.example.com",
|
|
24
|
-
getCredential: ({ signal }) =>
|
|
26
|
+
getCredential: async ({ signal }) => {
|
|
27
|
+
signal.throwIfAborted();
|
|
28
|
+
const credential = await auth.getDriveCredential({ workspace: { type: "personal" } });
|
|
29
|
+
signal.throwIfAborted();
|
|
30
|
+
return credential.token;
|
|
31
|
+
},
|
|
25
32
|
timeoutMilliseconds: 30_000,
|
|
26
33
|
});
|
|
27
34
|
|
|
@@ -53,6 +60,10 @@ const uploaded = await drive.uploadFile({
|
|
|
53
60
|
|
|
54
61
|
The provider runs once for every request. The SDK sends its result only as `Authorization: Bearer`, always sets `credentials: "omit"` and `cache: "no-store"`, and never reads cookies. Configuration does not accept default headers. Credential acquisition, Fetch, and response handling share one bounded request deadline: 30 seconds by default, configurable from 1 millisecond through 120 seconds.
|
|
55
62
|
|
|
63
|
+
`auth` is a configured `@finueva/auth` client. Select the exact personal or organization workspace. Native Fetch needs no wrapper.
|
|
64
|
+
|
|
65
|
+
Approve the exact application origin in Drive's `DRIVE_BROWSER_ORIGINS` policy and configure archive CORS separately. API responses must expose `X-Request-ID` and `ETag`. See [browser setup](https://github.com/Ifkafin/drive/blob/main/apps/developer/docs/architecture/configuration.md#native-api-browser-origins).
|
|
66
|
+
|
|
56
67
|
## Worker And Node
|
|
57
68
|
|
|
58
69
|
```ts
|
|
@@ -101,9 +112,9 @@ Methods use the Native API operation IDs:
|
|
|
101
112
|
|
|
102
113
|
`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.
|
|
103
114
|
|
|
104
|
-
`getItem`
|
|
115
|
+
`getItem` requires `items:metadata:read`. Absent, unauthorized, tombstoned, or unpublished items are concealed. Folders have `currentVersion: null`; files expose their current version. The strong ETag matches the item revision. Media type and protection classification are untrusted metadata, not content authority. Internal storage/provider state is never exposed.
|
|
105
116
|
|
|
106
|
-
`searchWorkspaceItems`
|
|
117
|
+
`searchWorkspaceItems` matches NFC, case-sensitive name prefixes: 1-64 Unicode code points, at most 255 UTF-8 bytes, without C0/C1 controls or U+2028/U+2029. Frozen `{ items, nextCursor }` pages default to 50 rows ordered by binary name then item ID. Results add `volumeId` and `provider: "managed"` to item metadata. An empty page cannot have a cursor.
|
|
107
118
|
|
|
108
119
|
Every mutation requires the API's explicit idempotency key when the operation defines one. Item lifecycle mutations also require the current strong item ETag as `ifMatch`; grant mutations use their documented collection or grant precondition. Mutations are never retried automatically. Sparse updates omit `undefined` properties and preserve explicit `null` expiry.
|
|
109
120
|
|
|
@@ -111,7 +122,7 @@ Successful calls return `{ data, status, requestId, validators }`. A successful
|
|
|
111
122
|
|
|
112
123
|
`updateItem` renames and moves one stable item ID. A move immediately changes inherited-grant ancestry; Drive does not copy grants to the item. `trashItem` retains a 30-day tombstone, `restoreItem` requires the original parent to remain active, and `deleteItem` starts permanent archive cleanup only after retention expires and no hold applies. Permanent deletion is currently bounded to at most 25 subtree items and 25 total versions; larger trees fail unavailable until a durable workflow exists. Exact retries resume retained deletion checkpoints and never trigger blind provider duplication.
|
|
113
124
|
|
|
114
|
-
`listItemVersions`
|
|
125
|
+
`listItemVersions` pages immutable current/superseded versions, at most 50 per page. `getItemVersion` verifies all three workspace/item/version IDs and conceals unavailable history. Malformed retained state fails unavailable. `restoreItemVersion` atomically changes the current version and item revision without copying or overwriting archive bytes.
|
|
115
126
|
|
|
116
127
|
`createDownload` returns a short-lived archive descriptor for the current or an explicit immutable version, one visible `restore-pending` result for cold content, or a no-body `304` operation result whose validators retain the source ETag. Full, closed, open, and suffix ranges use the selected archive object's strong ETag; malformed or multiple ranges are served as full representations, while valid non-overlapping ranges fail with `range_not_satisfiable`. `downloadItem` follows a descriptor with no Drive credential, ambient browser credentials, or referrer and returns the provider body as a backpressured `Response`; it preserves the same `304` and cold-restore results without a provider request. It validates exact status, ETag, identity encoding, length, and `Content-Range`, cancels malformed upstream bodies, and keeps caller cancellation/deadline authority active until the stream closes or is cancelled. It never returns Blob, ArrayBuffer, text, or base64 whole-file convenience values.
|
|
117
128
|
|
package/dist/client.js
CHANGED
|
@@ -1780,7 +1780,7 @@ function createClientRuntime(config) {
|
|
|
1780
1780
|
try {
|
|
1781
1781
|
runtime = Object.freeze({
|
|
1782
1782
|
baseUrl: parseBaseUrl(config.baseUrl),
|
|
1783
|
-
fetchImplementation: config.fetch ?? globalThis.fetch,
|
|
1783
|
+
fetchImplementation: config.fetch ?? globalThis.fetch.bind(globalThis),
|
|
1784
1784
|
getCredential: config.getCredential,
|
|
1785
1785
|
timeoutMilliseconds: parseTimeoutMilliseconds(config.timeoutMilliseconds)
|
|
1786
1786
|
});
|
package/dist/contract.d.ts
CHANGED
|
@@ -1,5 +1,228 @@
|
|
|
1
1
|
//#region src/generated/openapi.d.ts
|
|
2
2
|
interface operations {
|
|
3
|
+
provisionManagedWorkspace: {
|
|
4
|
+
parameters: {
|
|
5
|
+
query?: never;
|
|
6
|
+
header?: never;
|
|
7
|
+
path?: never;
|
|
8
|
+
cookie?: never;
|
|
9
|
+
};
|
|
10
|
+
requestBody: {
|
|
11
|
+
content: {
|
|
12
|
+
"application/json": {
|
|
13
|
+
entitlement: {
|
|
14
|
+
managedStorageByteLimit: number;
|
|
15
|
+
managedStorageEnabled: boolean;
|
|
16
|
+
version: number;
|
|
17
|
+
} & ({
|
|
18
|
+
/** @constant */
|
|
19
|
+
managedStorageByteLimit?: 0;
|
|
20
|
+
/** @constant */
|
|
21
|
+
managedStorageEnabled?: false;
|
|
22
|
+
} | {
|
|
23
|
+
managedStorageByteLimit?: number;
|
|
24
|
+
/** @constant */
|
|
25
|
+
managedStorageEnabled?: true;
|
|
26
|
+
});
|
|
27
|
+
/** @enum {string} */
|
|
28
|
+
environment: "local" | "development" | "staging" | "production";
|
|
29
|
+
provisioningId: string;
|
|
30
|
+
/** @constant */
|
|
31
|
+
version: 1;
|
|
32
|
+
workspaceReference: {
|
|
33
|
+
/** @enum {string} */
|
|
34
|
+
type: "personal";
|
|
35
|
+
userId: string;
|
|
36
|
+
} | {
|
|
37
|
+
organizationId: string;
|
|
38
|
+
/** @enum {string} */
|
|
39
|
+
type: "organization";
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
responses: {
|
|
45
|
+
/** @description The exact request replayed or was superseded by a later entitlement. */
|
|
46
|
+
200: {
|
|
47
|
+
headers: {
|
|
48
|
+
[name: string]: unknown;
|
|
49
|
+
};
|
|
50
|
+
content: {
|
|
51
|
+
"application/json": {
|
|
52
|
+
/** @enum {string} */
|
|
53
|
+
outcome: "replayed" | "superseded";
|
|
54
|
+
workspace: {
|
|
55
|
+
entitlement: {
|
|
56
|
+
managedStorageByteLimit: number;
|
|
57
|
+
managedStorageEnabled: boolean;
|
|
58
|
+
version: number;
|
|
59
|
+
} & ({
|
|
60
|
+
/** @constant */
|
|
61
|
+
managedStorageByteLimit?: 0;
|
|
62
|
+
/** @constant */
|
|
63
|
+
managedStorageEnabled?: false;
|
|
64
|
+
} | {
|
|
65
|
+
managedStorageByteLimit?: number;
|
|
66
|
+
/** @constant */
|
|
67
|
+
managedStorageEnabled?: true;
|
|
68
|
+
});
|
|
69
|
+
rootItemId: string;
|
|
70
|
+
rootVolumeId: string;
|
|
71
|
+
workspaceId: string;
|
|
72
|
+
workspaceReference: {
|
|
73
|
+
/** @enum {string} */
|
|
74
|
+
type: "personal";
|
|
75
|
+
userId: string;
|
|
76
|
+
} | {
|
|
77
|
+
organizationId: string;
|
|
78
|
+
/** @enum {string} */
|
|
79
|
+
type: "organization";
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
/** @description The provisioning state was committed. */
|
|
86
|
+
201: {
|
|
87
|
+
headers: {
|
|
88
|
+
[name: string]: unknown;
|
|
89
|
+
};
|
|
90
|
+
content: {
|
|
91
|
+
"application/json": {
|
|
92
|
+
/** @enum {string} */
|
|
93
|
+
outcome: "committed";
|
|
94
|
+
workspace: {
|
|
95
|
+
entitlement: {
|
|
96
|
+
managedStorageByteLimit: number;
|
|
97
|
+
managedStorageEnabled: boolean;
|
|
98
|
+
version: number;
|
|
99
|
+
} & ({
|
|
100
|
+
/** @constant */
|
|
101
|
+
managedStorageByteLimit?: 0;
|
|
102
|
+
/** @constant */
|
|
103
|
+
managedStorageEnabled?: false;
|
|
104
|
+
} | {
|
|
105
|
+
managedStorageByteLimit?: number;
|
|
106
|
+
/** @constant */
|
|
107
|
+
managedStorageEnabled?: true;
|
|
108
|
+
});
|
|
109
|
+
rootItemId: string;
|
|
110
|
+
rootVolumeId: string;
|
|
111
|
+
workspaceId: string;
|
|
112
|
+
workspaceReference: {
|
|
113
|
+
/** @enum {string} */
|
|
114
|
+
type: "personal";
|
|
115
|
+
userId: string;
|
|
116
|
+
} | {
|
|
117
|
+
organizationId: string;
|
|
118
|
+
/** @enum {string} */
|
|
119
|
+
type: "organization";
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
/** @description A valid ecosystem provisioning bearer credential is required. */
|
|
126
|
+
401: {
|
|
127
|
+
headers: {
|
|
128
|
+
[name: string]: unknown;
|
|
129
|
+
};
|
|
130
|
+
content: {
|
|
131
|
+
"application/json": {
|
|
132
|
+
error: {
|
|
133
|
+
/** @enum {string} */
|
|
134
|
+
code: "authentication_required";
|
|
135
|
+
details: Record<string, never>;
|
|
136
|
+
/** @enum {string} */
|
|
137
|
+
message: "Authentication is required.";
|
|
138
|
+
requestId: string;
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
/** @description The verified principal lacks the exact provisioning capability. */
|
|
144
|
+
403: {
|
|
145
|
+
headers: {
|
|
146
|
+
[name: string]: unknown;
|
|
147
|
+
};
|
|
148
|
+
content: {
|
|
149
|
+
"application/json": {
|
|
150
|
+
error: {
|
|
151
|
+
/** @enum {string} */
|
|
152
|
+
code: "permission_denied";
|
|
153
|
+
details: Record<string, never>;
|
|
154
|
+
/** @enum {string} */
|
|
155
|
+
message: "The requested action is not permitted.";
|
|
156
|
+
requestId: string;
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
/** @description The provisioning identity conflicts with retained state. */
|
|
162
|
+
409: {
|
|
163
|
+
headers: {
|
|
164
|
+
[name: string]: unknown;
|
|
165
|
+
};
|
|
166
|
+
content: {
|
|
167
|
+
"application/json": {
|
|
168
|
+
error: {
|
|
169
|
+
/** @enum {string} */
|
|
170
|
+
code: "idempotency_conflict";
|
|
171
|
+
details: Record<string, never>;
|
|
172
|
+
/** @enum {string} */
|
|
173
|
+
message: "The idempotency key conflicts with an earlier request.";
|
|
174
|
+
requestId: string;
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
};
|
|
178
|
+
};
|
|
179
|
+
/** @description The strict provisioning request is invalid. */
|
|
180
|
+
422: {
|
|
181
|
+
headers: {
|
|
182
|
+
[name: string]: unknown;
|
|
183
|
+
};
|
|
184
|
+
content: {
|
|
185
|
+
"application/json": {
|
|
186
|
+
error: {
|
|
187
|
+
/** @enum {string} */
|
|
188
|
+
code: "invalid_request";
|
|
189
|
+
details: Record<string, never>;
|
|
190
|
+
/** @enum {string} */
|
|
191
|
+
message: "The request is invalid.";
|
|
192
|
+
requestId: string;
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
/** @description Auth authority, D1, or trusted capacity evidence is unavailable. */
|
|
198
|
+
503: {
|
|
199
|
+
headers: {
|
|
200
|
+
[name: string]: unknown;
|
|
201
|
+
};
|
|
202
|
+
content: {
|
|
203
|
+
"application/json": {
|
|
204
|
+
error: {
|
|
205
|
+
/** @enum {string} */
|
|
206
|
+
code: "identity_authority_unavailable";
|
|
207
|
+
details: Record<string, never>;
|
|
208
|
+
/** @enum {string} */
|
|
209
|
+
message: "Authentication is temporarily unavailable.";
|
|
210
|
+
requestId: string;
|
|
211
|
+
};
|
|
212
|
+
} | {
|
|
213
|
+
error: {
|
|
214
|
+
/** @enum {string} */
|
|
215
|
+
code: "service_unavailable";
|
|
216
|
+
details: Record<string, never>;
|
|
217
|
+
/** @enum {string} */
|
|
218
|
+
message: "The service is temporarily unavailable.";
|
|
219
|
+
requestId: string;
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
};
|
|
3
226
|
getCurrentWorkspace: {
|
|
4
227
|
parameters: {
|
|
5
228
|
query?: never;
|
|
@@ -4596,4 +4819,4 @@ interface DriveClient extends DriveOperations {
|
|
|
4596
4819
|
uploadFile(input: UploadFileInput): Promise<DriveOperationResult<ReadyUpload, 200>>;
|
|
4597
4820
|
}
|
|
4598
4821
|
//#endregion
|
|
4599
|
-
export { UpdateItemInput as $, ListItemVersionsInput as A, PermissionGrant as B, FolderPage as C, GetUploadStatusInput as D, GetItemVersionInput as E, ManagedItemVersionPage as F, ReadEffectiveItemPermissionsInput as G, PermissionMutation as H, ManagedItemVersionResource as I, RestoreItemInput as J, ReadyUpload as K, ManagedItemVersionRestoreResult as L, ManagedDownloadRestorePending as M, ManagedItemMetadata as N, ListFolderChildrenInput as O, ManagedItemVersion as P, TrashItemInput as Q, ManagedLifecycleItem as R, FolderItem as S, GetItemInput as T, PermissionPage as U, PermissionGrantee as V, ProtectionClassification as W, RevokeItemPermissionInput as X, RestoreItemVersionInput as Y, SearchWorkspaceItemsInput as Z, DriveResponseValidators as _, CreateItemPermissionInput as a, UploadFileProgressCallback as at, EffectivePermissionAction as b, CurrentWorkspace as c, UploadSession as ct, DriveClient as d, WorkspaceItemSearchPage as dt, UpdateItemPermissionInput as et, DriveClientConfig as f, DriveOperations as g, DriveOperationResult as h, CreateFolderInput as i, UploadFileProgress as it, ManagedDownloadDescriptor as j, ListItemPermissionsInput as k, DeleteItemInput as l, UploadStatus as lt, DriveCredentialProvider as m, CompleteUploadInput as n, UploadFileInput as nt, CreateUploadInput as o, UploadPartDescriptor as ot, DriveCredentialContext as p, RecordUploadPartInput as q, CreateDownloadInput as r, UploadFilePhase as rt, CreateUploadPartDescriptorInput as s, UploadPartResult as st, AbortUploadInput as t, UploadConfirmedPart as tt, DownloadItemResult as u, WorkspaceItemSearchItem as ut, DriveServerClient as v, GetCurrentWorkspaceInput as w, EffectivePermissionResponse as x, DriveServerClientConfig as y, PermissionAction as z };
|
|
4822
|
+
export { UpdateItemInput as $, ListItemVersionsInput as A, PermissionGrant as B, FolderPage as C, GetUploadStatusInput as D, GetItemVersionInput as E, ManagedItemVersionPage as F, ReadEffectiveItemPermissionsInput as G, PermissionMutation as H, ManagedItemVersionResource as I, RestoreItemInput as J, ReadyUpload as K, ManagedItemVersionRestoreResult as L, ManagedDownloadRestorePending as M, ManagedItemMetadata as N, ListFolderChildrenInput as O, ManagedItemVersion as P, TrashItemInput as Q, ManagedLifecycleItem as R, FolderItem as S, GetItemInput as T, PermissionPage as U, PermissionGrantee as V, ProtectionClassification as W, RevokeItemPermissionInput as X, RestoreItemVersionInput as Y, SearchWorkspaceItemsInput as Z, DriveResponseValidators as _, CreateItemPermissionInput as a, UploadFileProgressCallback as at, EffectivePermissionAction as b, CurrentWorkspace as c, UploadSession as ct, DriveClient as d, WorkspaceItemSearchPage as dt, UpdateItemPermissionInput as et, DriveClientConfig as f, operations as ft, DriveOperations as g, DriveOperationResult as h, CreateFolderInput as i, UploadFileProgress as it, ManagedDownloadDescriptor as j, ListItemPermissionsInput as k, DeleteItemInput as l, UploadStatus as lt, DriveCredentialProvider as m, CompleteUploadInput as n, UploadFileInput as nt, CreateUploadInput as o, UploadPartDescriptor as ot, DriveCredentialContext as p, RecordUploadPartInput as q, CreateDownloadInput as r, UploadFilePhase as rt, CreateUploadPartDescriptorInput as s, UploadPartResult as st, AbortUploadInput as t, UploadConfirmedPart as tt, DownloadItemResult as u, WorkspaceItemSearchItem as ut, DriveServerClient as v, GetCurrentWorkspaceInput as w, EffectivePermissionResponse as x, DriveServerClientConfig as y, PermissionAction as z };
|
package/dist/index.js
CHANGED
|
@@ -1780,7 +1780,7 @@ function createClientRuntime(config) {
|
|
|
1780
1780
|
try {
|
|
1781
1781
|
runtime = Object.freeze({
|
|
1782
1782
|
baseUrl: parseBaseUrl(config.baseUrl),
|
|
1783
|
-
fetchImplementation: config.fetch ?? globalThis.fetch,
|
|
1783
|
+
fetchImplementation: config.fetch ?? globalThis.fetch.bind(globalThis),
|
|
1784
1784
|
getCredential: config.getCredential,
|
|
1785
1785
|
timeoutMilliseconds: parseTimeoutMilliseconds(config.timeoutMilliseconds)
|
|
1786
1786
|
});
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
|
-
import { $ as UpdateItemInput, A as ListItemVersionsInput, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, I as ManagedItemVersionResource, J as RestoreItemInput, K as ReadyUpload, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as TrashItemInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, W as ProtectionClassification, Y as RestoreItemVersionInput, Z as SearchWorkspaceItemsInput, c as CurrentWorkspace, ct as UploadSession, dt as WorkspaceItemSearchPage, j as ManagedDownloadDescriptor, l as DeleteItemInput, lt as UploadStatus, n as CompleteUploadInput, o as CreateUploadInput, ot as UploadPartDescriptor, q as RecordUploadPartInput, r as CreateDownloadInput, s as CreateUploadPartDescriptorInput, st as UploadPartResult, t as AbortUploadInput, tt as UploadConfirmedPart, u as DownloadItemResult, ut as WorkspaceItemSearchItem, v as DriveServerClient, w as GetCurrentWorkspaceInput, y as DriveServerClientConfig } from "./contract.js";
|
|
1
|
+
import { $ as UpdateItemInput, A as ListItemVersionsInput, C as FolderPage, D as GetUploadStatusInput, E as GetItemVersionInput, F as ManagedItemVersionPage, I as ManagedItemVersionResource, J as RestoreItemInput, K as ReadyUpload, L as ManagedItemVersionRestoreResult, M as ManagedDownloadRestorePending, N as ManagedItemMetadata, O as ListFolderChildrenInput, P as ManagedItemVersion, Q as TrashItemInput, R as ManagedLifecycleItem, S as FolderItem, T as GetItemInput, W as ProtectionClassification, Y as RestoreItemVersionInput, Z as SearchWorkspaceItemsInput, c as CurrentWorkspace, ct as UploadSession, dt as WorkspaceItemSearchPage, ft as operations, h as DriveOperationResult, j as ManagedDownloadDescriptor, l as DeleteItemInput, lt as UploadStatus, m as DriveCredentialProvider, n as CompleteUploadInput, o as CreateUploadInput, ot as UploadPartDescriptor, q as RecordUploadPartInput, r as CreateDownloadInput, s as CreateUploadPartDescriptorInput, st as UploadPartResult, t as AbortUploadInput, tt as UploadConfirmedPart, u as DownloadItemResult, ut as WorkspaceItemSearchItem, v as DriveServerClient, w as GetCurrentWorkspaceInput, y as DriveServerClientConfig } from "./contract.js";
|
|
2
|
+
//#region src/internal/provisioning.d.ts
|
|
3
|
+
type Operation = operations["provisionManagedWorkspace"];
|
|
4
|
+
type ProvisionWorkspaceCommand = Operation["requestBody"]["content"]["application/json"];
|
|
5
|
+
type ProvisionWorkspaceResult = Operation["responses"][200]["content"]["application/json"] | Operation["responses"][201]["content"]["application/json"];
|
|
6
|
+
interface DriveProvisioningClientConfig {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
environment: ProvisionWorkspaceCommand["environment"];
|
|
9
|
+
getProvisioningCredential: DriveCredentialProvider;
|
|
10
|
+
fetch?: typeof globalThis.fetch;
|
|
11
|
+
timeoutMilliseconds?: number;
|
|
12
|
+
}
|
|
13
|
+
interface DriveProvisioningClient {
|
|
14
|
+
provisionWorkspace(command: ProvisionWorkspaceCommand, options?: {
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
}): Promise<DriveOperationResult<ProvisionWorkspaceResult, 200 | 201>>;
|
|
17
|
+
}
|
|
18
|
+
declare function createDriveProvisioningClient(config: DriveProvisioningClientConfig): DriveProvisioningClient;
|
|
19
|
+
//#endregion
|
|
2
20
|
//#region src/server.d.ts
|
|
3
21
|
declare function createDriveServerClient(config: DriveServerClientConfig): DriveServerClient;
|
|
4
22
|
//#endregion
|
|
5
|
-
export { type AbortUploadInput, type CompleteUploadInput, type CreateDownloadInput, type CreateUploadInput, type CreateUploadPartDescriptorInput, type CurrentWorkspace, type DeleteItemInput, type DownloadItemResult, type DriveServerClient, type DriveServerClientConfig, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type GetItemInput, type GetItemVersionInput, type GetUploadStatusInput, type ListFolderChildrenInput, type ListItemVersionsInput, type ManagedDownloadDescriptor, type ManagedDownloadRestorePending, type ManagedItemMetadata, type ManagedItemVersion, type ManagedItemVersionPage, type ManagedItemVersionResource, type ManagedItemVersionRestoreResult, type ManagedLifecycleItem, type ProtectionClassification, type ReadyUpload, type RecordUploadPartInput, type RestoreItemInput, type RestoreItemVersionInput, type SearchWorkspaceItemsInput, type TrashItemInput, type UpdateItemInput, type UploadConfirmedPart, type UploadPartDescriptor, type UploadPartResult, type UploadSession, type UploadStatus, type WorkspaceItemSearchItem, type WorkspaceItemSearchPage, createDriveServerClient };
|
|
23
|
+
export { type AbortUploadInput, type CompleteUploadInput, type CreateDownloadInput, type CreateUploadInput, type CreateUploadPartDescriptorInput, type CurrentWorkspace, type DeleteItemInput, type DownloadItemResult, type DriveProvisioningClient, type DriveProvisioningClientConfig, type DriveServerClient, type DriveServerClientConfig, type FolderItem, type FolderPage, type GetCurrentWorkspaceInput, type GetItemInput, type GetItemVersionInput, type GetUploadStatusInput, type ListFolderChildrenInput, type ListItemVersionsInput, type ManagedDownloadDescriptor, type ManagedDownloadRestorePending, type ManagedItemMetadata, type ManagedItemVersion, type ManagedItemVersionPage, type ManagedItemVersionResource, type ManagedItemVersionRestoreResult, type ManagedLifecycleItem, type ProtectionClassification, type ProvisionWorkspaceCommand, type ProvisionWorkspaceResult, type ReadyUpload, type RecordUploadPartInput, type RestoreItemInput, type RestoreItemVersionInput, type SearchWorkspaceItemsInput, type TrashItemInput, type UpdateItemInput, type UploadConfirmedPart, type UploadPartDescriptor, type UploadPartResult, type UploadSession, type UploadStatus, type WorkspaceItemSearchItem, type WorkspaceItemSearchPage, createDriveProvisioningClient, createDriveServerClient };
|
package/dist/server.js
CHANGED
|
@@ -1738,7 +1738,7 @@ function createClientRuntime(config) {
|
|
|
1738
1738
|
try {
|
|
1739
1739
|
runtime = Object.freeze({
|
|
1740
1740
|
baseUrl: parseBaseUrl(config.baseUrl),
|
|
1741
|
-
fetchImplementation: config.fetch ?? globalThis.fetch,
|
|
1741
|
+
fetchImplementation: config.fetch ?? globalThis.fetch.bind(globalThis),
|
|
1742
1742
|
getCredential: config.getCredential,
|
|
1743
1743
|
timeoutMilliseconds: parseTimeoutMilliseconds(config.timeoutMilliseconds)
|
|
1744
1744
|
});
|
|
@@ -2459,6 +2459,81 @@ async function abortUpload(runtime, input) {
|
|
|
2459
2459
|
}), [204], null, false, TRANSFER_ERROR_CODES);
|
|
2460
2460
|
}
|
|
2461
2461
|
//#endregion
|
|
2462
|
+
//#region src/internal/provisioning.ts
|
|
2463
|
+
const environments = [
|
|
2464
|
+
"local",
|
|
2465
|
+
"development",
|
|
2466
|
+
"staging",
|
|
2467
|
+
"production"
|
|
2468
|
+
];
|
|
2469
|
+
const identifier = /^[A-Za-z0-9_-]{1,128}$/;
|
|
2470
|
+
function createDriveProvisioningClient(config) {
|
|
2471
|
+
if (!config || !environments.includes(config.environment)) throw new DriveError("invalid_input");
|
|
2472
|
+
const environment = config.environment;
|
|
2473
|
+
const runtime = createClientRuntime({
|
|
2474
|
+
baseUrl: config.baseUrl,
|
|
2475
|
+
getCredential: config.getProvisioningCredential,
|
|
2476
|
+
...config.fetch === void 0 ? {} : { fetch: config.fetch },
|
|
2477
|
+
...config.timeoutMilliseconds === void 0 ? {} : { timeoutMilliseconds: config.timeoutMilliseconds }
|
|
2478
|
+
});
|
|
2479
|
+
return Object.freeze({ async provisionWorkspace(command, options) {
|
|
2480
|
+
if (!exact(command, [
|
|
2481
|
+
"version",
|
|
2482
|
+
"environment",
|
|
2483
|
+
"provisioningId",
|
|
2484
|
+
"workspaceReference",
|
|
2485
|
+
"entitlement"
|
|
2486
|
+
]) || command.version !== 1 || command.environment !== environment || typeof command.provisioningId !== "string" || !identifier.test(command.provisioningId) || !reference(command.workspaceReference) || !entitlement(command.entitlement)) throw new DriveError("invalid_input");
|
|
2487
|
+
const body = {
|
|
2488
|
+
version: command.version,
|
|
2489
|
+
environment: command.environment,
|
|
2490
|
+
provisioningId: command.provisioningId,
|
|
2491
|
+
workspaceReference: { ...command.workspaceReference },
|
|
2492
|
+
entitlement: { ...command.entitlement }
|
|
2493
|
+
};
|
|
2494
|
+
return execute(runtime, options?.signal, null, (api, boundary) => api.POST("/api/v1/platform/workspaces/provision", {
|
|
2495
|
+
...boundary,
|
|
2496
|
+
redirect: "manual",
|
|
2497
|
+
body
|
|
2498
|
+
}), [200, 201], (value, status) => validResult(value, status, body), false, [
|
|
2499
|
+
"authentication_required",
|
|
2500
|
+
"permission_denied",
|
|
2501
|
+
"idempotency_conflict",
|
|
2502
|
+
"invalid_request",
|
|
2503
|
+
"identity_authority_unavailable",
|
|
2504
|
+
"service_unavailable"
|
|
2505
|
+
]);
|
|
2506
|
+
} });
|
|
2507
|
+
}
|
|
2508
|
+
function exact(value, keys) {
|
|
2509
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
2510
|
+
}
|
|
2511
|
+
function reference(value) {
|
|
2512
|
+
return exact(value, ["type", "userId"]) && value.type === "personal" && typeof value.userId === "string" && identifier.test(value.userId) || exact(value, ["type", "organizationId"]) && value.type === "organization" && typeof value.organizationId === "string" && identifier.test(value.organizationId);
|
|
2513
|
+
}
|
|
2514
|
+
function entitlement(value) {
|
|
2515
|
+
return exact(value, [
|
|
2516
|
+
"version",
|
|
2517
|
+
"managedStorageEnabled",
|
|
2518
|
+
"managedStorageByteLimit"
|
|
2519
|
+
]) && typeof value.version === "number" && Number.isSafeInteger(value.version) && value.version >= 0 && typeof value.managedStorageByteLimit === "number" && Number.isSafeInteger(value.managedStorageByteLimit) && (value.managedStorageEnabled === true && value.managedStorageByteLimit > 0 || value.managedStorageEnabled === false && value.managedStorageByteLimit === 0);
|
|
2520
|
+
}
|
|
2521
|
+
function validResult(value, status, command) {
|
|
2522
|
+
if (!exact(value, ["outcome", "workspace"]) || (status === 201 ? value.outcome !== "committed" : value.outcome !== "replayed" && value.outcome !== "superseded") || !exact(value.workspace, [
|
|
2523
|
+
"workspaceId",
|
|
2524
|
+
"rootVolumeId",
|
|
2525
|
+
"rootItemId",
|
|
2526
|
+
"workspaceReference",
|
|
2527
|
+
"entitlement"
|
|
2528
|
+
])) return false;
|
|
2529
|
+
const { entitlement: current, ...workspace } = value.workspace;
|
|
2530
|
+
if (!isCurrentWorkspace(workspace) || !entitlement(current)) return false;
|
|
2531
|
+
const actual = workspace.workspaceReference;
|
|
2532
|
+
const expected = command.workspaceReference;
|
|
2533
|
+
if (!(actual.type === "personal" && expected.type === "personal" && actual.userId === expected.userId) && !(actual.type === "organization" && expected.type === "organization" && actual.organizationId === expected.organizationId)) return false;
|
|
2534
|
+
return value.outcome === "superseded" ? current.version > command.entitlement.version : current.version === command.entitlement.version && current.managedStorageEnabled === command.entitlement.managedStorageEnabled && current.managedStorageByteLimit === command.entitlement.managedStorageByteLimit;
|
|
2535
|
+
}
|
|
2536
|
+
//#endregion
|
|
2462
2537
|
//#region src/server.ts
|
|
2463
2538
|
function createDriveServerClient(config) {
|
|
2464
2539
|
const credential = config.credential;
|
|
@@ -2471,4 +2546,4 @@ function createDriveServerClient(config) {
|
|
|
2471
2546
|
});
|
|
2472
2547
|
}
|
|
2473
2548
|
//#endregion
|
|
2474
|
-
export { createDriveServerClient };
|
|
2549
|
+
export { createDriveProvisioningClient, createDriveServerClient };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finueva/drive",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Public browser, Worker, and Node client for Finueva Drive",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"openapi-fetch": "0.17.0",
|
|
66
66
|
"openapi-typescript": "7.13.0",
|
|
67
67
|
"playwright": "1.62.1",
|
|
68
|
+
"prettier": "^3.9.6",
|
|
68
69
|
"rolldown": "1.2.0",
|
|
69
70
|
"rolldown-plugin-dts": "0.27.14",
|
|
70
71
|
"typescript": "5.9.3",
|