@darseen/vaze 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -3
- package/dist/index.cjs +294 -24
- package/dist/index.d.cts +660 -2
- package/dist/index.d.ts +660 -2
- package/dist/index.js +292 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,6 +37,20 @@ const vaze = new Vaze({
|
|
|
37
37
|
});
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
# Acting as a Signed-in User
|
|
41
|
+
|
|
42
|
+
Apps that sign people in can send their session instead of an API key. Pass `headers`, an object or a function called before every request, and an optional `fetch` to replace the global one:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const vaze = new Vaze({
|
|
46
|
+
vazeUrl: "http://your-server-ip:3000",
|
|
47
|
+
headers: async () => ({ cookie: await getSessionCookie() }),
|
|
48
|
+
fetch: (input, init) => fetch(input, { ...init, credentials: "omit" }),
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`vaze.authHeaders()` returns the headers the SDK sends, for clients that fetch an SDK URL themselves, such as `vaze.files.thumbnailUrl(id)` or `vaze.files.downloadUrl(id)`.
|
|
53
|
+
|
|
40
54
|
# Using Environment Variables
|
|
41
55
|
|
|
42
56
|
If you set `VAZE_URL` and `VAZE_API_KEY` in your environment, you can initialize the client without passing arguments:
|
|
@@ -50,7 +64,7 @@ const vaze = new Vaze();
|
|
|
50
64
|
|
|
51
65
|
# API Documentation
|
|
52
66
|
|
|
53
|
-
The SDK
|
|
67
|
+
The SDK's main modules are `files` and `folders`, plus `keys`, `account`, `activity`, `users` and `settings` for signed-in users. All methods are asynchronous and return a standard `ApiResponse` object containing either `data` or an `error`. Files API Access file-related methods via `vaze.files.getAll(options?)` Retrieve a paginated list of all files.
|
|
54
68
|
|
|
55
69
|
- options (optional):
|
|
56
70
|
- `limit`
|
|
@@ -87,7 +101,7 @@ const { data, error } = await vaze.files.getByName("document.pdf", {
|
|
|
87
101
|
`upload(data)` Upload one or multiple files to your Vaze instance.
|
|
88
102
|
|
|
89
103
|
- data:
|
|
90
|
-
- `files` (File[]): An array of standard web [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) objects.
|
|
104
|
+
- `files` (File[]): An array of standard web [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) objects, or in React Native, `{ uri, name, type }` references.
|
|
91
105
|
- `folder?` (string): The path of the target folder, created if it doesn't exist.
|
|
92
106
|
|
|
93
107
|
```ts
|
|
@@ -199,6 +213,80 @@ if (data) {
|
|
|
199
213
|
const { data, error } = await vaze.folders.delete("folder-id");
|
|
200
214
|
```
|
|
201
215
|
|
|
216
|
+
Keys API Manage the caller's API keys via `vaze.keys`. These calls need a client that acts as a signed-in user (`headers`) holding `api-keys:manage`; a client built with an API key gets a `403`.
|
|
217
|
+
|
|
218
|
+
`getAll()` List the caller's keys, newest first.
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
const { data, error } = await vaze.keys.getAll();
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`create(options)` Create a key. The secret in `data.key.key` is only returned this once.
|
|
225
|
+
|
|
226
|
+
- options:
|
|
227
|
+
- `name`: Unique among the caller's keys.
|
|
228
|
+
- `scopes`: Any of `files:read`, `files:write` and `files:delete` the caller holds.
|
|
229
|
+
- `expiresAt` (optional): A `Date` or ISO string; leave it out for a key that never expires.
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
const { data, error } = await vaze.keys.create({
|
|
233
|
+
name: "Backup script",
|
|
234
|
+
scopes: ["files:read", "files:write"],
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
console.log(data?.key.key); // "vz_..."
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
`rename(data)` Rename a key. Scopes and expiry can't change.
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
const { data, error } = await vaze.keys.rename({ id: "key-id", name: "Nightly backup" });
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
`delete(id)` Delete a key, which stops working right away.
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
const { data, error } = await vaze.keys.delete("key-id");
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Account API Change the signed-in user's own account via `vaze.account`. These calls need a client that acts as a signed-in user (`headers`); a client built with an API key gets a `403`.
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
await vaze.account.update({ name: "Dana Scully", email: "dana@example.org" });
|
|
256
|
+
await vaze.account.changePassword({ currentPassword: "old", newPassword: "new-password", revokeOtherSessions: true });
|
|
257
|
+
|
|
258
|
+
const { data } = await vaze.account.getSessions(); // devices, the current one first
|
|
259
|
+
await vaze.account.revokeSession("session-id");
|
|
260
|
+
await vaze.account.revokeOtherSessions();
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Activity API Read and prune the caller's history of uploads, deletions and changes via `vaze.activity`. Needs a signed-in user.
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
const { data } = await vaze.activity.getAll(); // the 200 most recent entries
|
|
267
|
+
await vaze.activity.delete(["activity-id"]);
|
|
268
|
+
await vaze.activity.clear();
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Users API Manage accounts via `vaze.users`. Needs a signed-in admin (`users:manage`). None of the changes work on the caller's own account.
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
const { data } = await vaze.users.getAll();
|
|
275
|
+
await vaze.users.create({ name: "Dana", email: "dana@example.com", password: "a-long-password", role: "viewer" });
|
|
276
|
+
await vaze.users.setAccess({ id: "user-id", role: "custom", scopes: ["files:read"] });
|
|
277
|
+
await vaze.users.resetPassword({ id: "user-id", password: "a-new-password" });
|
|
278
|
+
await vaze.users.setDisabled({ id: "user-id", disabled: true });
|
|
279
|
+
await vaze.users.delete("user-id");
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Settings API Read and change instance-wide settings via `vaze.settings`. Needs a signed-in user holding `settings:manage`.
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
const { data } = await vaze.settings.get(); // defaultVisibility, visibilityCounts, limits
|
|
286
|
+
await vaze.settings.update({ defaultVisibility: "private", limits: { activityRetentionDays: 30 } });
|
|
287
|
+
await vaze.settings.applyVisibility("private"); // every existing file
|
|
288
|
+
```
|
|
289
|
+
|
|
202
290
|
# Health Check
|
|
203
291
|
|
|
204
292
|
`vaze.health()` pings the instance to verify connectivity.
|
|
@@ -211,6 +299,17 @@ if (data) {
|
|
|
211
299
|
}
|
|
212
300
|
```
|
|
213
301
|
|
|
302
|
+
# Account and Stats
|
|
303
|
+
|
|
304
|
+
`vaze.me()` returns the caller's account and the scopes it may use. `vaze.stats()` returns the dashboard's numbers, with each section `null` when the caller lacks its scope.
|
|
305
|
+
|
|
306
|
+
```ts
|
|
307
|
+
const { data } = await vaze.me();
|
|
308
|
+
const canUpload = data?.scopes.includes("files:write");
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Failed requests carry the HTTP status in `error.status`, such as `401` once a session expires.
|
|
312
|
+
|
|
214
313
|
# Types
|
|
215
314
|
|
|
216
|
-
This SDK is built with TypeScript and exports all necessary types to ensure type safety in your applications. Types such as `File`, `Folder`, `ApiResponse`, `ListOptions`, and `VazeOptions`.
|
|
315
|
+
This SDK is built with TypeScript and exports all necessary types to ensure type safety in your applications. Types such as `File`, `Folder`, `ApiKey`, `Activity`, `User`, `Session`, `InstanceSettings`, `ApiResponse`, `ListOptions`, and `VazeOptions`.
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/utils/index.ts
|
|
2
|
+
function env(name) {
|
|
3
|
+
return typeof process === "undefined" ? void 0 : _optionalChain([process, 'access', _ => _.env, 'optionalAccess', _2 => _2[name]]);
|
|
4
|
+
}
|
|
2
5
|
function constructFileUrls({
|
|
3
6
|
vazeUrl,
|
|
4
7
|
files
|
|
@@ -12,34 +15,39 @@ function constructFileUrls({
|
|
|
12
15
|
function parseContentDispositionFilename(header) {
|
|
13
16
|
if (!header) return null;
|
|
14
17
|
const utf8Match = header.match(/filename\*=UTF-8''([^;]+)/i);
|
|
15
|
-
if (_optionalChain([utf8Match, 'optionalAccess',
|
|
18
|
+
if (_optionalChain([utf8Match, 'optionalAccess', _3 => _3[1]])) {
|
|
16
19
|
try {
|
|
17
20
|
return decodeURIComponent(utf8Match[1]);
|
|
18
21
|
} catch (e) {
|
|
19
22
|
}
|
|
20
23
|
}
|
|
21
24
|
const plainMatch = header.match(/filename="([^"]*)"/i);
|
|
22
|
-
return _nullishCoalesce(_optionalChain([plainMatch, 'optionalAccess',
|
|
25
|
+
return _nullishCoalesce(_optionalChain([plainMatch, 'optionalAccess', _4 => _4[1]]), () => ( null));
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
// src/base.ts
|
|
26
29
|
var Base = class {
|
|
27
30
|
|
|
28
31
|
|
|
32
|
+
// wrapped so the global fetch is never called with this class as `this`
|
|
33
|
+
|
|
34
|
+
|
|
29
35
|
constructor(options = {}) {
|
|
30
|
-
const vazeUrl = options.vazeUrl ||
|
|
31
|
-
const apiKey = options.apiKey ||
|
|
36
|
+
const vazeUrl = options.vazeUrl || env("VAZE_URL");
|
|
37
|
+
const apiKey = options.apiKey || env("VAZE_API_KEY");
|
|
32
38
|
if (!vazeUrl) {
|
|
33
39
|
throw new Error(
|
|
34
40
|
"You must provide a Vaze URL or set the VAZE_URL environment variable."
|
|
35
41
|
);
|
|
36
42
|
}
|
|
37
|
-
if (!apiKey) {
|
|
43
|
+
if (!apiKey && !options.headers) {
|
|
38
44
|
throw new Error(
|
|
39
|
-
"You must provide an API key or set the VAZE_API_KEY environment variable."
|
|
45
|
+
"You must provide an API key or headers, or set the VAZE_API_KEY environment variable."
|
|
40
46
|
);
|
|
41
47
|
}
|
|
42
48
|
this.apiKey = apiKey;
|
|
49
|
+
this.headers = options.headers;
|
|
50
|
+
this.fetch = _nullishCoalesce(options.fetch, () => ( ((input, init) => fetch(input, init))));
|
|
43
51
|
this.vazeUrl = vazeUrl.endsWith("/") ? vazeUrl : `${vazeUrl}/`;
|
|
44
52
|
}
|
|
45
53
|
apiUrl(path, params) {
|
|
@@ -51,35 +59,45 @@ var Base = class {
|
|
|
51
59
|
}
|
|
52
60
|
return url.toString();
|
|
53
61
|
}
|
|
62
|
+
/** The headers every request carries, for clients fetching an SDK URL themselves. */
|
|
63
|
+
async authHeaders() {
|
|
64
|
+
const headers = typeof this.headers === "function" ? await this.headers() : this.headers;
|
|
65
|
+
return this.apiKey ? { ...headers, "API-Key": this.apiKey } : { ...headers };
|
|
66
|
+
}
|
|
54
67
|
async request(method, url, body, headers) {
|
|
55
68
|
try {
|
|
56
69
|
const fetchHeaders = {
|
|
57
|
-
|
|
70
|
+
...await this.authHeaders(),
|
|
58
71
|
...headers
|
|
59
72
|
};
|
|
60
73
|
const isFormData = body instanceof FormData;
|
|
61
74
|
if (body !== void 0 && !isFormData && !fetchHeaders["Content-Type"]) {
|
|
62
75
|
fetchHeaders["Content-Type"] = "application/json";
|
|
63
76
|
}
|
|
64
|
-
const response = await fetch(url, {
|
|
77
|
+
const response = await this.fetch(url, {
|
|
65
78
|
method,
|
|
66
79
|
headers: fetchHeaders,
|
|
67
80
|
body: isFormData ? body : body !== void 0 ? JSON.stringify(body) : null
|
|
68
81
|
});
|
|
82
|
+
const { status } = response;
|
|
69
83
|
const contentType = _nullishCoalesce(response.headers.get("content-type"), () => ( ""));
|
|
70
84
|
if (!contentType.includes("application/json")) {
|
|
71
85
|
return {
|
|
72
86
|
data: null,
|
|
73
87
|
error: {
|
|
74
|
-
message: `Unexpected non-JSON response from server (status ${
|
|
88
|
+
message: `Unexpected non-JSON response from server (status ${status}).`,
|
|
89
|
+
status
|
|
75
90
|
}
|
|
76
91
|
};
|
|
77
92
|
}
|
|
78
93
|
const result = await response.json();
|
|
79
|
-
if (!response.ok
|
|
94
|
+
if (!response.ok) {
|
|
80
95
|
return {
|
|
81
96
|
data: null,
|
|
82
|
-
error: {
|
|
97
|
+
error: {
|
|
98
|
+
message: _nullishCoalesce(_optionalChain([result, 'access', _5 => _5.error, 'optionalAccess', _6 => _6.message]), () => ( `Request failed with status ${status}.`)),
|
|
99
|
+
status
|
|
100
|
+
}
|
|
83
101
|
};
|
|
84
102
|
}
|
|
85
103
|
return result;
|
|
@@ -94,22 +112,25 @@ var Base = class {
|
|
|
94
112
|
}
|
|
95
113
|
async requestBlob(url, method = "GET", body) {
|
|
96
114
|
try {
|
|
97
|
-
const headers =
|
|
115
|
+
const headers = await this.authHeaders();
|
|
98
116
|
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
99
|
-
const response = await fetch(url, {
|
|
117
|
+
const response = await this.fetch(url, {
|
|
100
118
|
method,
|
|
101
119
|
headers,
|
|
102
120
|
body: body !== void 0 ? JSON.stringify(body) : null
|
|
103
121
|
});
|
|
122
|
+
const { status } = response;
|
|
104
123
|
const contentType = _nullishCoalesce(response.headers.get("content-type"), () => ( ""));
|
|
105
124
|
if (!response.ok) {
|
|
106
125
|
if (contentType.includes("application/json")) {
|
|
107
126
|
const result = await response.json();
|
|
108
|
-
if (result.error)
|
|
127
|
+
if (result.error) {
|
|
128
|
+
return { data: null, error: { ...result.error, status } };
|
|
129
|
+
}
|
|
109
130
|
}
|
|
110
131
|
return {
|
|
111
132
|
data: null,
|
|
112
|
-
error: { message: `Request failed with status ${
|
|
133
|
+
error: { message: `Request failed with status ${status}.`, status }
|
|
113
134
|
};
|
|
114
135
|
}
|
|
115
136
|
return {
|
|
@@ -133,6 +154,70 @@ var Base = class {
|
|
|
133
154
|
}
|
|
134
155
|
};
|
|
135
156
|
|
|
157
|
+
// src/account.ts
|
|
158
|
+
var Account = class extends Base {
|
|
159
|
+
/** Changes the display name, the sign-in email, or both. */
|
|
160
|
+
async update(changes) {
|
|
161
|
+
return await this.request("PUT", this.apiUrl("/api/me"), changes);
|
|
162
|
+
}
|
|
163
|
+
async changePassword({
|
|
164
|
+
currentPassword,
|
|
165
|
+
newPassword,
|
|
166
|
+
revokeOtherSessions = false
|
|
167
|
+
}) {
|
|
168
|
+
return await this.request("PUT", this.apiUrl("/api/me/password"), {
|
|
169
|
+
currentPassword,
|
|
170
|
+
newPassword,
|
|
171
|
+
revokeOtherSessions
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
/** Every device signed in to the account, the current one first. */
|
|
175
|
+
async getSessions() {
|
|
176
|
+
return await this.request(
|
|
177
|
+
"GET",
|
|
178
|
+
this.apiUrl("/api/me/sessions")
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
/** Signs out another device. The current session ends with a sign-out instead. */
|
|
182
|
+
async revokeSession(id) {
|
|
183
|
+
return await this.request("DELETE", this.apiUrl("/api/me/sessions"), {
|
|
184
|
+
id
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
/** Signs out every device but the current one. */
|
|
188
|
+
async revokeOtherSessions() {
|
|
189
|
+
return await this.request("DELETE", this.apiUrl("/api/me/sessions"), {
|
|
190
|
+
others: true
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
// src/activity.ts
|
|
196
|
+
var Activity = class extends Base {
|
|
197
|
+
/** The most recent entries, newest first. */
|
|
198
|
+
async getAll() {
|
|
199
|
+
return await this.request(
|
|
200
|
+
"GET",
|
|
201
|
+
this.apiUrl("/api/activity")
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
async delete(ids) {
|
|
205
|
+
return await this.request(
|
|
206
|
+
"DELETE",
|
|
207
|
+
this.apiUrl("/api/activity"),
|
|
208
|
+
{ ids }
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
/** Deletes every entry. Files, keys and accounts are not affected. */
|
|
212
|
+
async clear() {
|
|
213
|
+
return await this.request(
|
|
214
|
+
"DELETE",
|
|
215
|
+
this.apiUrl("/api/activity"),
|
|
216
|
+
{ all: true }
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
136
221
|
// src/files.ts
|
|
137
222
|
var Files = class extends Base {
|
|
138
223
|
async getAll(options) {
|
|
@@ -201,7 +286,7 @@ var Files = class extends Base {
|
|
|
201
286
|
}
|
|
202
287
|
async upload(data) {
|
|
203
288
|
const { files, folder, visibility } = data;
|
|
204
|
-
const url = this.
|
|
289
|
+
const url = this.uploadUrl();
|
|
205
290
|
const formData = new FormData();
|
|
206
291
|
if (folder) formData.append("folder", folder);
|
|
207
292
|
if (visibility) formData.append("visibility", visibility);
|
|
@@ -219,15 +304,36 @@ var Files = class extends Base {
|
|
|
219
304
|
} : null
|
|
220
305
|
};
|
|
221
306
|
}
|
|
307
|
+
/** Where `upload` posts its form, for upload managers that report progress. */
|
|
308
|
+
uploadUrl() {
|
|
309
|
+
return this.apiUrl("/api/files");
|
|
310
|
+
}
|
|
311
|
+
/** Record uploads canceled before they were sent, in the activity history. */
|
|
312
|
+
async reportCanceled(names) {
|
|
313
|
+
return await this.request(
|
|
314
|
+
"POST",
|
|
315
|
+
this.apiUrl("/api/files/canceled"),
|
|
316
|
+
{ names }
|
|
317
|
+
);
|
|
318
|
+
}
|
|
222
319
|
async download(id) {
|
|
223
|
-
|
|
224
|
-
|
|
320
|
+
return await this.requestBlob(this.downloadUrl(id));
|
|
321
|
+
}
|
|
322
|
+
/** Where `download` reads from; fetch it yourself with `authHeaders()`. */
|
|
323
|
+
downloadUrl(id) {
|
|
324
|
+
return this.apiUrl(`/api/files/download/${encodeURIComponent(id)}`);
|
|
325
|
+
}
|
|
326
|
+
/** A WebP thumbnail of an image file; fetch it with `authHeaders()`. */
|
|
327
|
+
thumbnailUrl(id) {
|
|
328
|
+
return this.apiUrl(`/api/files/thumbnail/${encodeURIComponent(id)}`);
|
|
225
329
|
}
|
|
226
330
|
/** Download several files as one zip, with paths below their shared folder. */
|
|
227
331
|
async downloadMany(ids) {
|
|
228
|
-
return await this.requestBlob(this.
|
|
229
|
-
|
|
230
|
-
|
|
332
|
+
return await this.requestBlob(this.downloadManyUrl(), "POST", { ids });
|
|
333
|
+
}
|
|
334
|
+
/** Where `downloadMany` posts `{ ids }`; stream it yourself with `authHeaders()`. */
|
|
335
|
+
downloadManyUrl() {
|
|
336
|
+
return this.apiUrl("/api/files/download");
|
|
231
337
|
}
|
|
232
338
|
async rename(data) {
|
|
233
339
|
return await this.request("PUT", this.apiUrl("/api/files"), data);
|
|
@@ -311,9 +417,11 @@ var Folders = class extends Base {
|
|
|
311
417
|
}
|
|
312
418
|
/** Download a folder and everything below it as a zip; the root by default. */
|
|
313
419
|
async download(options) {
|
|
314
|
-
return await this.requestBlob(
|
|
315
|
-
|
|
316
|
-
|
|
420
|
+
return await this.requestBlob(this.downloadUrl(options));
|
|
421
|
+
}
|
|
422
|
+
/** Where `download` reads from; fetch it yourself with `authHeaders()`. */
|
|
423
|
+
downloadUrl(options) {
|
|
424
|
+
return this.apiUrl("/api/folders/download", options);
|
|
317
425
|
}
|
|
318
426
|
async create(folder) {
|
|
319
427
|
return await this.request(
|
|
@@ -344,14 +452,140 @@ var Folders = class extends Base {
|
|
|
344
452
|
}
|
|
345
453
|
};
|
|
346
454
|
|
|
455
|
+
// src/keys.ts
|
|
456
|
+
var Keys = class extends Base {
|
|
457
|
+
/** Every key the caller owns, newest first. */
|
|
458
|
+
async getAll() {
|
|
459
|
+
return await this.request(
|
|
460
|
+
"GET",
|
|
461
|
+
this.apiUrl("/api/keys")
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
/** The response holds the key's secret, which can't be read again later. */
|
|
465
|
+
async create({ name, scopes, expiresAt }) {
|
|
466
|
+
return await this.request(
|
|
467
|
+
"POST",
|
|
468
|
+
this.apiUrl("/api/keys"),
|
|
469
|
+
{
|
|
470
|
+
name,
|
|
471
|
+
scopes,
|
|
472
|
+
expiresAt: expiresAt instanceof Date ? expiresAt.toISOString() : expiresAt
|
|
473
|
+
}
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
async rename(data) {
|
|
477
|
+
return await this.request("PUT", this.apiUrl("/api/keys"), data);
|
|
478
|
+
}
|
|
479
|
+
/** Revokes the key at once for anything using it. */
|
|
480
|
+
async delete(id) {
|
|
481
|
+
return await this.request("DELETE", this.apiUrl("/api/keys"), {
|
|
482
|
+
id
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
// src/settings.ts
|
|
488
|
+
var Settings = class extends Base {
|
|
489
|
+
async get() {
|
|
490
|
+
return await this.request(
|
|
491
|
+
"GET",
|
|
492
|
+
this.apiUrl("/api/settings")
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
/** Limits left out keep their current values. */
|
|
496
|
+
async update(changes) {
|
|
497
|
+
return await this.request(
|
|
498
|
+
"PUT",
|
|
499
|
+
this.apiUrl("/api/settings"),
|
|
500
|
+
changes
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
/** Gives every existing file this visibility. */
|
|
504
|
+
async applyVisibility(visibility) {
|
|
505
|
+
return await this.request(
|
|
506
|
+
"POST",
|
|
507
|
+
this.apiUrl("/api/settings/apply-visibility"),
|
|
508
|
+
{ visibility }
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
// src/users.ts
|
|
514
|
+
var Users = class extends Base {
|
|
515
|
+
/** Every account, oldest first. */
|
|
516
|
+
async getAll() {
|
|
517
|
+
return await this.request(
|
|
518
|
+
"GET",
|
|
519
|
+
this.apiUrl("/api/users")
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
async create(options) {
|
|
523
|
+
return await this.request(
|
|
524
|
+
"POST",
|
|
525
|
+
this.apiUrl("/api/users"),
|
|
526
|
+
options
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
/** Applies right away, to the user's sessions and API keys alike. */
|
|
530
|
+
async setAccess({
|
|
531
|
+
id,
|
|
532
|
+
role,
|
|
533
|
+
scopes = []
|
|
534
|
+
}) {
|
|
535
|
+
return await this.request(
|
|
536
|
+
"PUT",
|
|
537
|
+
this.apiUrl("/api/users"),
|
|
538
|
+
{ id, role, scopes }
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
/** Also signs the user out of every device. */
|
|
542
|
+
async resetPassword({
|
|
543
|
+
id,
|
|
544
|
+
password
|
|
545
|
+
}) {
|
|
546
|
+
return await this.request(
|
|
547
|
+
"PUT",
|
|
548
|
+
this.apiUrl("/api/users"),
|
|
549
|
+
{ id, password }
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
/** A disabled user is signed out and their API keys stop until re-enabled. */
|
|
553
|
+
async setDisabled({
|
|
554
|
+
id,
|
|
555
|
+
disabled
|
|
556
|
+
}) {
|
|
557
|
+
return await this.request(
|
|
558
|
+
"PUT",
|
|
559
|
+
this.apiUrl("/api/users"),
|
|
560
|
+
{ id, disabled }
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
/** Removes the account, its API keys and its history. Files stay. */
|
|
564
|
+
async delete(id) {
|
|
565
|
+
return await this.request("DELETE", this.apiUrl("/api/users"), {
|
|
566
|
+
id
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
|
|
347
571
|
// src/index.ts
|
|
348
572
|
var Vaze = class extends Base {
|
|
349
573
|
|
|
350
574
|
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
|
|
351
580
|
constructor(options = {}) {
|
|
352
581
|
super(options);
|
|
353
582
|
this.files = new Files(options);
|
|
354
583
|
this.folders = new Folders(options);
|
|
584
|
+
this.keys = new Keys(options);
|
|
585
|
+
this.account = new Account(options);
|
|
586
|
+
this.activity = new Activity(options);
|
|
587
|
+
this.users = new Users(options);
|
|
588
|
+
this.settings = new Settings(options);
|
|
355
589
|
}
|
|
356
590
|
async health() {
|
|
357
591
|
return await this.request(
|
|
@@ -359,6 +593,42 @@ var Vaze = class extends Base {
|
|
|
359
593
|
this.apiUrl("/api/health")
|
|
360
594
|
);
|
|
361
595
|
}
|
|
596
|
+
/** Whether the instance still needs its first account, which becomes the admin. */
|
|
597
|
+
async setupStatus() {
|
|
598
|
+
return await this.request(
|
|
599
|
+
"GET",
|
|
600
|
+
this.apiUrl("/api/setup")
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
/** The caller's account and the scopes it may use. */
|
|
604
|
+
async me() {
|
|
605
|
+
return await this.request("GET", this.apiUrl("/api/me"));
|
|
606
|
+
}
|
|
607
|
+
/** Dashboard numbers, with each section limited to the caller's scopes. */
|
|
608
|
+
async stats() {
|
|
609
|
+
const { data, error } = await this.request(
|
|
610
|
+
"GET",
|
|
611
|
+
this.apiUrl("/api/stats")
|
|
612
|
+
);
|
|
613
|
+
const files = _optionalChain([data, 'optionalAccess', _7 => _7.files]);
|
|
614
|
+
return {
|
|
615
|
+
error,
|
|
616
|
+
data: data ? {
|
|
617
|
+
...data,
|
|
618
|
+
files: files ? {
|
|
619
|
+
...files,
|
|
620
|
+
largest: constructFileUrls({
|
|
621
|
+
vazeUrl: this.vazeUrl,
|
|
622
|
+
files: files.largest
|
|
623
|
+
}),
|
|
624
|
+
recent: constructFileUrls({
|
|
625
|
+
vazeUrl: this.vazeUrl,
|
|
626
|
+
files: files.recent
|
|
627
|
+
})
|
|
628
|
+
} : null
|
|
629
|
+
} : null
|
|
630
|
+
};
|
|
631
|
+
}
|
|
362
632
|
};
|
|
363
633
|
|
|
364
634
|
|