@darseen/vaze 2.4.0 → 2.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/README.md CHANGED
@@ -10,6 +10,8 @@
10
10
 
11
11
  **@darseen/vaze** The official JavaScript/TypeScript SDK for Vaze, a self-hosted, local-first file storage and hosting service. This SDK provides a simple and type-safe way to interact with your Vaze instance's API from your Node.js backend or frontend applications.
12
12
 
13
+ **[Website](https://vaze.darseen.dev)**  |  **[SDK documentation](https://vaze.darseen.dev/docs/sdk)**
14
+
13
15
  ## </div>
14
16
 
15
17
  # Installation
@@ -301,7 +303,7 @@ if (data) {
301
303
 
302
304
  # Account and Stats
303
305
 
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.
306
+ `vaze.me()` returns the caller's account and the scopes it may use. `vaze.stats()` returns the dashboard's numbers: storage, files added per day, public hosting traffic, API key usage, accounts and alerts, with each section `null` when the caller lacks its scope. Fields added in later server versions, such as `hosting` and `alerts`, are absent on older servers.
305
307
 
306
308
  ```ts
307
309
  const { data } = await vaze.me();
@@ -312,4 +314,4 @@ Failed requests carry the HTTP status in `error.status`, such as `401` once a se
312
314
 
313
315
  # Types
314
316
 
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`.
317
+ 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`, `Stats`, `StatsAlert`, `TrafficDay`, `ApiKeyUsage`, `ApiResponse`, `ListOptions`, and `VazeOptions`.
package/dist/index.cjs CHANGED
@@ -286,7 +286,7 @@ var Files = class extends Base {
286
286
  }
287
287
  async upload(data) {
288
288
  const { files, folder, visibility } = data;
289
- const url = this.apiUrl("/api/files");
289
+ const url = this.uploadUrl();
290
290
  const formData = new FormData();
291
291
  if (folder) formData.append("folder", folder);
292
292
  if (visibility) formData.append("visibility", visibility);
@@ -304,6 +304,18 @@ var Files = class extends Base {
304
304
  } : null
305
305
  };
306
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
+ }
307
319
  async download(id) {
308
320
  return await this.requestBlob(this.downloadUrl(id));
309
321
  }
@@ -317,9 +329,11 @@ var Files = class extends Base {
317
329
  }
318
330
  /** Download several files as one zip, with paths below their shared folder. */
319
331
  async downloadMany(ids) {
320
- return await this.requestBlob(this.apiUrl("/api/files/download"), "POST", {
321
- ids
322
- });
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");
323
337
  }
324
338
  async rename(data) {
325
339
  return await this.request("PUT", this.apiUrl("/api/files"), data);
@@ -403,9 +417,11 @@ var Folders = class extends Base {
403
417
  }
404
418
  /** Download a folder and everything below it as a zip; the root by default. */
405
419
  async download(options) {
406
- return await this.requestBlob(
407
- this.apiUrl("/api/folders/download", options)
408
- );
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);
409
425
  }
410
426
  async create(folder) {
411
427
  return await this.request(
@@ -577,33 +593,50 @@ var Vaze = class extends Base {
577
593
  this.apiUrl("/api/health")
578
594
  );
579
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
+ }
580
603
  /** The caller's account and the scopes it may use. */
581
604
  async me() {
582
605
  return await this.request("GET", this.apiUrl("/api/me"));
583
606
  }
584
607
  /** Dashboard numbers, with each section limited to the caller's scopes. */
585
608
  async stats() {
586
- const { data, error } = await this.request(
609
+ const response = await this.request(
587
610
  "GET",
588
611
  this.apiUrl("/api/stats")
589
612
  );
590
- const files = _optionalChain([data, 'optionalAccess', _7 => _7.files]);
613
+ if (response.data === null) return response;
614
+ const { files, hosting } = response.data;
615
+ const vazeUrl = this.vazeUrl;
616
+ const withUrl = (file) => ({
617
+ ...file,
618
+ url: constructFileUrls({ vazeUrl, files: [file] })[0].url
619
+ });
591
620
  return {
592
- error,
593
- data: data ? {
594
- ...data,
621
+ error: null,
622
+ data: {
623
+ ...response.data,
595
624
  files: files ? {
596
625
  ...files,
597
- largest: constructFileUrls({
598
- vazeUrl: this.vazeUrl,
599
- files: files.largest
600
- }),
601
- recent: constructFileUrls({
602
- vazeUrl: this.vazeUrl,
603
- files: files.recent
604
- })
605
- } : null
606
- } : null
626
+ largest: constructFileUrls({ vazeUrl, files: files.largest }),
627
+ recent: constructFileUrls({ vazeUrl, files: files.recent })
628
+ } : null,
629
+ // servers that predate traffic leave `hosting` out, so keep it out
630
+ ...hosting ? {
631
+ hosting: {
632
+ ...hosting,
633
+ top: hosting.top.map((entry) => ({
634
+ ...entry,
635
+ file: withUrl(entry.file)
636
+ }))
637
+ }
638
+ } : {}
639
+ }
607
640
  };
608
641
  }
609
642
  };
package/dist/index.d.cts CHANGED
@@ -1144,14 +1144,76 @@ type InstanceSettings = {
1144
1144
  visibilityCounts: Record<Visibility, number>;
1145
1145
  limits: Limits;
1146
1146
  };
1147
+ /** One API key's share of the week's requests. */
1148
+ type ApiKeyUsage = {
1149
+ id: string;
1150
+ name: string;
1151
+ /** Requests over the same seven UTC days as `Stats["apiKeys"]["requests"]`. */
1152
+ requests: number;
1153
+ lastUsed: string | null;
1154
+ expiresAt: string | null;
1155
+ };
1156
+ /** Public hosting traffic for one UTC day. */
1157
+ type TrafficDay = {
1158
+ date: string;
1159
+ /** Responses that served a file: 200, 206 and 304. */
1160
+ requests: number;
1161
+ /** Body bytes streamed out. */
1162
+ bytes: number;
1163
+ /** Requests for keys that matched no file the caller could read. */
1164
+ notFound: number;
1165
+ };
1166
+ /** Something on the instance worth acting on. */
1167
+ type StatsAlert =
1168
+ /** The data volume has less than a tenth of its space left. */
1169
+ {
1170
+ type: "storage-low";
1171
+ available: number;
1172
+ capacity: number;
1173
+ }
1174
+ /** The caller's own uploads that failed over the last seven days. */
1175
+ | {
1176
+ type: "uploads-failed";
1177
+ count: number;
1178
+ latest: string;
1179
+ }
1180
+ /** The caller's own file and folder deletes that failed over the last seven days. */
1181
+ | {
1182
+ type: "deletes-failed";
1183
+ count: number;
1184
+ latest: string;
1185
+ }
1186
+ /** The caller's keys past their expiry date, which no longer work. */
1187
+ | {
1188
+ type: "keys-expired";
1189
+ count: number;
1190
+ }
1191
+ /** The caller's keys that expire within seven days. */
1192
+ | {
1193
+ type: "keys-expiring";
1194
+ count: number;
1195
+ }
1196
+ /** The caller's keys not used for 30 days. */
1197
+ | {
1198
+ type: "keys-unused";
1199
+ count: number;
1200
+ };
1201
+ /**
1202
+ * Fields marked optional were added after the first release of this endpoint.
1203
+ * Servers that predate them leave them out, so check before reading.
1204
+ */
1147
1205
  type Stats = {
1148
1206
  /** Present when the caller holds `files:read`. */
1149
1207
  files: {
1150
1208
  total: number;
1151
1209
  folders: number;
1152
1210
  storage: {
1211
+ /** Bytes taken by stored files. */
1153
1212
  used: number;
1213
+ /** Bytes free on the data volume. */
1154
1214
  available: number;
1215
+ /** Usable size of the data volume, which other data may share. */
1216
+ capacity?: number;
1155
1217
  };
1156
1218
  types: {
1157
1219
  mimeType: string;
@@ -1160,6 +1222,20 @@ type Stats = {
1160
1222
  }[];
1161
1223
  largest: FileWithUrl[];
1162
1224
  recent: FileWithUrl[];
1225
+ /** Files and bytes per visibility. */
1226
+ visibility?: Record<Visibility, {
1227
+ count: number;
1228
+ size: number;
1229
+ }>;
1230
+ /**
1231
+ * Files added per UTC day over the last 30 days, oldest first. Only files
1232
+ * still stored count, so deleting a file removes it from its day.
1233
+ */
1234
+ added?: {
1235
+ date: string;
1236
+ count: number;
1237
+ size: number;
1238
+ }[];
1163
1239
  } | null;
1164
1240
  /** Present for signed-in users holding `api-keys:manage`. */
1165
1241
  apiKeys: {
@@ -1169,7 +1245,36 @@ type Stats = {
1169
1245
  date: string;
1170
1246
  count: number;
1171
1247
  }[];
1248
+ /**
1249
+ * Every key with its requests over the same days, busiest first. Requests
1250
+ * made with keys deleted since count in `requests` but in no key here.
1251
+ */
1252
+ keys?: ApiKeyUsage[];
1253
+ } | null;
1254
+ /**
1255
+ * Public hosting traffic over the last 30 UTC days. Present when the caller
1256
+ * holds `files:read`. Requests made from a signed-in dashboard or app
1257
+ * session aren't counted.
1258
+ */
1259
+ hosting?: {
1260
+ /** Oldest first. */
1261
+ days: TrafficDay[];
1262
+ /** The five files requested most over those days. */
1263
+ top: {
1264
+ file: FileWithUrl;
1265
+ requests: number;
1266
+ bytes: number;
1267
+ }[];
1268
+ } | null;
1269
+ /** Present for signed-in users holding `users:manage`. */
1270
+ users?: {
1271
+ total: number;
1272
+ disabled: number;
1273
+ /** Devices signed in across every account. */
1274
+ sessions: number;
1172
1275
  } | null;
1276
+ /** Empty when nothing needs attention. New types may be added later. */
1277
+ alerts?: StatsAlert[];
1173
1278
  };
1174
1279
 
1175
1280
  /** The caller's activity history. These calls need a session, not a key. */
@@ -1237,6 +1342,10 @@ declare class Files extends Base {
1237
1342
  files: any[];
1238
1343
  } | null;
1239
1344
  }>;
1345
+ /** Where `upload` posts its form, for upload managers that report progress. */
1346
+ uploadUrl(): string;
1347
+ /** Record uploads canceled before they were sent, in the activity history. */
1348
+ reportCanceled(names: string[]): Promise<ApiResponse<null>>;
1240
1349
  download(id: string): Promise<ApiResponse<{
1241
1350
  blob: Blob;
1242
1351
  filename: string | null;
@@ -1252,6 +1361,8 @@ declare class Files extends Base {
1252
1361
  filename: string | null;
1253
1362
  contentType: string;
1254
1363
  }>>;
1364
+ /** Where `downloadMany` posts `{ ids }`; stream it yourself with `authHeaders()`. */
1365
+ downloadManyUrl(): string;
1255
1366
  rename(data: {
1256
1367
  id: string;
1257
1368
  name: string;
@@ -1326,6 +1437,11 @@ declare class Folders extends Base {
1326
1437
  filename: string | null;
1327
1438
  contentType: string;
1328
1439
  }>>;
1440
+ /** Where `download` reads from; fetch it yourself with `authHeaders()`. */
1441
+ downloadUrl(options?: {
1442
+ id?: string;
1443
+ key?: string;
1444
+ }): string;
1329
1445
  create(folder: string): Promise<ApiResponse<{
1330
1446
  folder: Folder;
1331
1447
  }>>;
@@ -1551,39 +1667,14 @@ declare class Vaze extends Base implements IVaze {
1551
1667
  health(): Promise<ApiResponse<{
1552
1668
  message: string;
1553
1669
  }>>;
1670
+ /** Whether the instance still needs its first account, which becomes the admin. */
1671
+ setupStatus(): Promise<ApiResponse<{
1672
+ needed: boolean;
1673
+ }>>;
1554
1674
  /** The caller's account and the scopes it may use. */
1555
1675
  me(): Promise<ApiResponse<Me>>;
1556
1676
  /** Dashboard numbers, with each section limited to the caller's scopes. */
1557
- stats(): Promise<{
1558
- error: {
1559
- message: string;
1560
- status?: number;
1561
- } | null;
1562
- data: {
1563
- files: {
1564
- largest: any[];
1565
- recent: any[];
1566
- total: number;
1567
- folders: number;
1568
- storage: {
1569
- used: number;
1570
- available: number;
1571
- };
1572
- types: {
1573
- mimeType: string;
1574
- size: number;
1575
- count: number;
1576
- }[];
1577
- } | null;
1578
- apiKeys: {
1579
- total: number;
1580
- requests: {
1581
- date: string;
1582
- count: number;
1583
- }[];
1584
- } | null;
1585
- } | null;
1586
- }>;
1677
+ stats(): Promise<ApiResponse<Stats>>;
1587
1678
  }
1588
1679
 
1589
- export { type ActivityEntry as Activity, type ActivityType, type ApiKeySummary as ApiKey, type ApiResponse, type BulkDeleteResult, type BulkMoveResult, type CreatedApiKey, type FileWithUrl as File, type FileReference, type Folder, type InstanceSettings, type Limits, type ListOptions, type Me, type MoveDestination, type NewKeyOptions, type NewUserOptions, type PasswordChange, type ProfileChanges, type Role, type Scope, type SessionSummary as Session, type SettingsChanges, type SignOptions, type SignedUrl, type Stats, type UserSummary as User, type UserAccess, type VazeHeaders, type VazeOptions, type Visibility, Vaze as default };
1680
+ export { type ActivityEntry as Activity, type ActivityType, type ApiKeySummary as ApiKey, type ApiKeyUsage, type ApiResponse, type BulkDeleteResult, type BulkMoveResult, type CreatedApiKey, type FileWithUrl as File, type FileReference, type Folder, type InstanceSettings, type Limits, type ListOptions, type Me, type MoveDestination, type NewKeyOptions, type NewUserOptions, type PasswordChange, type ProfileChanges, type Role, type Scope, type SessionSummary as Session, type SettingsChanges, type SignOptions, type SignedUrl, type Stats, type StatsAlert, type TrafficDay, type UserSummary as User, type UserAccess, type VazeHeaders, type VazeOptions, type Visibility, Vaze as default };
package/dist/index.d.ts CHANGED
@@ -1144,14 +1144,76 @@ type InstanceSettings = {
1144
1144
  visibilityCounts: Record<Visibility, number>;
1145
1145
  limits: Limits;
1146
1146
  };
1147
+ /** One API key's share of the week's requests. */
1148
+ type ApiKeyUsage = {
1149
+ id: string;
1150
+ name: string;
1151
+ /** Requests over the same seven UTC days as `Stats["apiKeys"]["requests"]`. */
1152
+ requests: number;
1153
+ lastUsed: string | null;
1154
+ expiresAt: string | null;
1155
+ };
1156
+ /** Public hosting traffic for one UTC day. */
1157
+ type TrafficDay = {
1158
+ date: string;
1159
+ /** Responses that served a file: 200, 206 and 304. */
1160
+ requests: number;
1161
+ /** Body bytes streamed out. */
1162
+ bytes: number;
1163
+ /** Requests for keys that matched no file the caller could read. */
1164
+ notFound: number;
1165
+ };
1166
+ /** Something on the instance worth acting on. */
1167
+ type StatsAlert =
1168
+ /** The data volume has less than a tenth of its space left. */
1169
+ {
1170
+ type: "storage-low";
1171
+ available: number;
1172
+ capacity: number;
1173
+ }
1174
+ /** The caller's own uploads that failed over the last seven days. */
1175
+ | {
1176
+ type: "uploads-failed";
1177
+ count: number;
1178
+ latest: string;
1179
+ }
1180
+ /** The caller's own file and folder deletes that failed over the last seven days. */
1181
+ | {
1182
+ type: "deletes-failed";
1183
+ count: number;
1184
+ latest: string;
1185
+ }
1186
+ /** The caller's keys past their expiry date, which no longer work. */
1187
+ | {
1188
+ type: "keys-expired";
1189
+ count: number;
1190
+ }
1191
+ /** The caller's keys that expire within seven days. */
1192
+ | {
1193
+ type: "keys-expiring";
1194
+ count: number;
1195
+ }
1196
+ /** The caller's keys not used for 30 days. */
1197
+ | {
1198
+ type: "keys-unused";
1199
+ count: number;
1200
+ };
1201
+ /**
1202
+ * Fields marked optional were added after the first release of this endpoint.
1203
+ * Servers that predate them leave them out, so check before reading.
1204
+ */
1147
1205
  type Stats = {
1148
1206
  /** Present when the caller holds `files:read`. */
1149
1207
  files: {
1150
1208
  total: number;
1151
1209
  folders: number;
1152
1210
  storage: {
1211
+ /** Bytes taken by stored files. */
1153
1212
  used: number;
1213
+ /** Bytes free on the data volume. */
1154
1214
  available: number;
1215
+ /** Usable size of the data volume, which other data may share. */
1216
+ capacity?: number;
1155
1217
  };
1156
1218
  types: {
1157
1219
  mimeType: string;
@@ -1160,6 +1222,20 @@ type Stats = {
1160
1222
  }[];
1161
1223
  largest: FileWithUrl[];
1162
1224
  recent: FileWithUrl[];
1225
+ /** Files and bytes per visibility. */
1226
+ visibility?: Record<Visibility, {
1227
+ count: number;
1228
+ size: number;
1229
+ }>;
1230
+ /**
1231
+ * Files added per UTC day over the last 30 days, oldest first. Only files
1232
+ * still stored count, so deleting a file removes it from its day.
1233
+ */
1234
+ added?: {
1235
+ date: string;
1236
+ count: number;
1237
+ size: number;
1238
+ }[];
1163
1239
  } | null;
1164
1240
  /** Present for signed-in users holding `api-keys:manage`. */
1165
1241
  apiKeys: {
@@ -1169,7 +1245,36 @@ type Stats = {
1169
1245
  date: string;
1170
1246
  count: number;
1171
1247
  }[];
1248
+ /**
1249
+ * Every key with its requests over the same days, busiest first. Requests
1250
+ * made with keys deleted since count in `requests` but in no key here.
1251
+ */
1252
+ keys?: ApiKeyUsage[];
1253
+ } | null;
1254
+ /**
1255
+ * Public hosting traffic over the last 30 UTC days. Present when the caller
1256
+ * holds `files:read`. Requests made from a signed-in dashboard or app
1257
+ * session aren't counted.
1258
+ */
1259
+ hosting?: {
1260
+ /** Oldest first. */
1261
+ days: TrafficDay[];
1262
+ /** The five files requested most over those days. */
1263
+ top: {
1264
+ file: FileWithUrl;
1265
+ requests: number;
1266
+ bytes: number;
1267
+ }[];
1268
+ } | null;
1269
+ /** Present for signed-in users holding `users:manage`. */
1270
+ users?: {
1271
+ total: number;
1272
+ disabled: number;
1273
+ /** Devices signed in across every account. */
1274
+ sessions: number;
1172
1275
  } | null;
1276
+ /** Empty when nothing needs attention. New types may be added later. */
1277
+ alerts?: StatsAlert[];
1173
1278
  };
1174
1279
 
1175
1280
  /** The caller's activity history. These calls need a session, not a key. */
@@ -1237,6 +1342,10 @@ declare class Files extends Base {
1237
1342
  files: any[];
1238
1343
  } | null;
1239
1344
  }>;
1345
+ /** Where `upload` posts its form, for upload managers that report progress. */
1346
+ uploadUrl(): string;
1347
+ /** Record uploads canceled before they were sent, in the activity history. */
1348
+ reportCanceled(names: string[]): Promise<ApiResponse<null>>;
1240
1349
  download(id: string): Promise<ApiResponse<{
1241
1350
  blob: Blob;
1242
1351
  filename: string | null;
@@ -1252,6 +1361,8 @@ declare class Files extends Base {
1252
1361
  filename: string | null;
1253
1362
  contentType: string;
1254
1363
  }>>;
1364
+ /** Where `downloadMany` posts `{ ids }`; stream it yourself with `authHeaders()`. */
1365
+ downloadManyUrl(): string;
1255
1366
  rename(data: {
1256
1367
  id: string;
1257
1368
  name: string;
@@ -1326,6 +1437,11 @@ declare class Folders extends Base {
1326
1437
  filename: string | null;
1327
1438
  contentType: string;
1328
1439
  }>>;
1440
+ /** Where `download` reads from; fetch it yourself with `authHeaders()`. */
1441
+ downloadUrl(options?: {
1442
+ id?: string;
1443
+ key?: string;
1444
+ }): string;
1329
1445
  create(folder: string): Promise<ApiResponse<{
1330
1446
  folder: Folder;
1331
1447
  }>>;
@@ -1551,39 +1667,14 @@ declare class Vaze extends Base implements IVaze {
1551
1667
  health(): Promise<ApiResponse<{
1552
1668
  message: string;
1553
1669
  }>>;
1670
+ /** Whether the instance still needs its first account, which becomes the admin. */
1671
+ setupStatus(): Promise<ApiResponse<{
1672
+ needed: boolean;
1673
+ }>>;
1554
1674
  /** The caller's account and the scopes it may use. */
1555
1675
  me(): Promise<ApiResponse<Me>>;
1556
1676
  /** Dashboard numbers, with each section limited to the caller's scopes. */
1557
- stats(): Promise<{
1558
- error: {
1559
- message: string;
1560
- status?: number;
1561
- } | null;
1562
- data: {
1563
- files: {
1564
- largest: any[];
1565
- recent: any[];
1566
- total: number;
1567
- folders: number;
1568
- storage: {
1569
- used: number;
1570
- available: number;
1571
- };
1572
- types: {
1573
- mimeType: string;
1574
- size: number;
1575
- count: number;
1576
- }[];
1577
- } | null;
1578
- apiKeys: {
1579
- total: number;
1580
- requests: {
1581
- date: string;
1582
- count: number;
1583
- }[];
1584
- } | null;
1585
- } | null;
1586
- }>;
1677
+ stats(): Promise<ApiResponse<Stats>>;
1587
1678
  }
1588
1679
 
1589
- export { type ActivityEntry as Activity, type ActivityType, type ApiKeySummary as ApiKey, type ApiResponse, type BulkDeleteResult, type BulkMoveResult, type CreatedApiKey, type FileWithUrl as File, type FileReference, type Folder, type InstanceSettings, type Limits, type ListOptions, type Me, type MoveDestination, type NewKeyOptions, type NewUserOptions, type PasswordChange, type ProfileChanges, type Role, type Scope, type SessionSummary as Session, type SettingsChanges, type SignOptions, type SignedUrl, type Stats, type UserSummary as User, type UserAccess, type VazeHeaders, type VazeOptions, type Visibility, Vaze as default };
1680
+ export { type ActivityEntry as Activity, type ActivityType, type ApiKeySummary as ApiKey, type ApiKeyUsage, type ApiResponse, type BulkDeleteResult, type BulkMoveResult, type CreatedApiKey, type FileWithUrl as File, type FileReference, type Folder, type InstanceSettings, type Limits, type ListOptions, type Me, type MoveDestination, type NewKeyOptions, type NewUserOptions, type PasswordChange, type ProfileChanges, type Role, type Scope, type SessionSummary as Session, type SettingsChanges, type SignOptions, type SignedUrl, type Stats, type StatsAlert, type TrafficDay, type UserSummary as User, type UserAccess, type VazeHeaders, type VazeOptions, type Visibility, Vaze as default };
package/dist/index.js CHANGED
@@ -286,7 +286,7 @@ var Files = class extends Base {
286
286
  }
287
287
  async upload(data) {
288
288
  const { files, folder, visibility } = data;
289
- const url = this.apiUrl("/api/files");
289
+ const url = this.uploadUrl();
290
290
  const formData = new FormData();
291
291
  if (folder) formData.append("folder", folder);
292
292
  if (visibility) formData.append("visibility", visibility);
@@ -304,6 +304,18 @@ var Files = class extends Base {
304
304
  } : null
305
305
  };
306
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
+ }
307
319
  async download(id) {
308
320
  return await this.requestBlob(this.downloadUrl(id));
309
321
  }
@@ -317,9 +329,11 @@ var Files = class extends Base {
317
329
  }
318
330
  /** Download several files as one zip, with paths below their shared folder. */
319
331
  async downloadMany(ids) {
320
- return await this.requestBlob(this.apiUrl("/api/files/download"), "POST", {
321
- ids
322
- });
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");
323
337
  }
324
338
  async rename(data) {
325
339
  return await this.request("PUT", this.apiUrl("/api/files"), data);
@@ -403,9 +417,11 @@ var Folders = class extends Base {
403
417
  }
404
418
  /** Download a folder and everything below it as a zip; the root by default. */
405
419
  async download(options) {
406
- return await this.requestBlob(
407
- this.apiUrl("/api/folders/download", options)
408
- );
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);
409
425
  }
410
426
  async create(folder) {
411
427
  return await this.request(
@@ -577,33 +593,50 @@ var Vaze = class extends Base {
577
593
  this.apiUrl("/api/health")
578
594
  );
579
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
+ }
580
603
  /** The caller's account and the scopes it may use. */
581
604
  async me() {
582
605
  return await this.request("GET", this.apiUrl("/api/me"));
583
606
  }
584
607
  /** Dashboard numbers, with each section limited to the caller's scopes. */
585
608
  async stats() {
586
- const { data, error } = await this.request(
609
+ const response = await this.request(
587
610
  "GET",
588
611
  this.apiUrl("/api/stats")
589
612
  );
590
- const files = data?.files;
613
+ if (response.data === null) return response;
614
+ const { files, hosting } = response.data;
615
+ const vazeUrl = this.vazeUrl;
616
+ const withUrl = (file) => ({
617
+ ...file,
618
+ url: constructFileUrls({ vazeUrl, files: [file] })[0].url
619
+ });
591
620
  return {
592
- error,
593
- data: data ? {
594
- ...data,
621
+ error: null,
622
+ data: {
623
+ ...response.data,
595
624
  files: files ? {
596
625
  ...files,
597
- largest: constructFileUrls({
598
- vazeUrl: this.vazeUrl,
599
- files: files.largest
600
- }),
601
- recent: constructFileUrls({
602
- vazeUrl: this.vazeUrl,
603
- files: files.recent
604
- })
605
- } : null
606
- } : null
626
+ largest: constructFileUrls({ vazeUrl, files: files.largest }),
627
+ recent: constructFileUrls({ vazeUrl, files: files.recent })
628
+ } : null,
629
+ // servers that predate traffic leave `hosting` out, so keep it out
630
+ ...hosting ? {
631
+ hosting: {
632
+ ...hosting,
633
+ top: hosting.top.map((entry) => ({
634
+ ...entry,
635
+ file: withUrl(entry.file)
636
+ }))
637
+ }
638
+ } : {}
639
+ }
607
640
  };
608
641
  }
609
642
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@darseen/vaze",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "description": "Vaze Self-Hosted file storage and hosting service SDK.",
5
5
  "keywords": [
6
6
  "api",
@@ -12,7 +12,7 @@
12
12
  "file-storage",
13
13
  "vaze"
14
14
  ],
15
- "homepage": "https://github.com/darseen/vaze#readme",
15
+ "homepage": "https://vaze.darseen.dev/docs/sdk",
16
16
  "bugs": {
17
17
  "url": "https://github.com/darseen/vaze/issues"
18
18
  },