@darseen/vaze 2.5.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
@@ -606,27 +606,37 @@ var Vaze = class extends Base {
606
606
  }
607
607
  /** Dashboard numbers, with each section limited to the caller's scopes. */
608
608
  async stats() {
609
- const { data, error } = await this.request(
609
+ const response = await this.request(
610
610
  "GET",
611
611
  this.apiUrl("/api/stats")
612
612
  );
613
- 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
+ });
614
620
  return {
615
- error,
616
- data: data ? {
617
- ...data,
621
+ error: null,
622
+ data: {
623
+ ...response.data,
618
624
  files: files ? {
619
625
  ...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
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
+ }
630
640
  };
631
641
  }
632
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[];
1172
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;
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. */
@@ -1569,36 +1674,7 @@ declare class Vaze extends Base implements IVaze {
1569
1674
  /** The caller's account and the scopes it may use. */
1570
1675
  me(): Promise<ApiResponse<Me>>;
1571
1676
  /** Dashboard numbers, with each section limited to the caller's scopes. */
1572
- stats(): Promise<{
1573
- error: {
1574
- message: string;
1575
- status?: number;
1576
- } | null;
1577
- data: {
1578
- files: {
1579
- largest: any[];
1580
- recent: any[];
1581
- total: number;
1582
- folders: number;
1583
- storage: {
1584
- used: number;
1585
- available: number;
1586
- };
1587
- types: {
1588
- mimeType: string;
1589
- size: number;
1590
- count: number;
1591
- }[];
1592
- } | null;
1593
- apiKeys: {
1594
- total: number;
1595
- requests: {
1596
- date: string;
1597
- count: number;
1598
- }[];
1599
- } | null;
1600
- } | null;
1601
- }>;
1677
+ stats(): Promise<ApiResponse<Stats>>;
1602
1678
  }
1603
1679
 
1604
- 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[];
1172
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;
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. */
@@ -1569,36 +1674,7 @@ declare class Vaze extends Base implements IVaze {
1569
1674
  /** The caller's account and the scopes it may use. */
1570
1675
  me(): Promise<ApiResponse<Me>>;
1571
1676
  /** Dashboard numbers, with each section limited to the caller's scopes. */
1572
- stats(): Promise<{
1573
- error: {
1574
- message: string;
1575
- status?: number;
1576
- } | null;
1577
- data: {
1578
- files: {
1579
- largest: any[];
1580
- recent: any[];
1581
- total: number;
1582
- folders: number;
1583
- storage: {
1584
- used: number;
1585
- available: number;
1586
- };
1587
- types: {
1588
- mimeType: string;
1589
- size: number;
1590
- count: number;
1591
- }[];
1592
- } | null;
1593
- apiKeys: {
1594
- total: number;
1595
- requests: {
1596
- date: string;
1597
- count: number;
1598
- }[];
1599
- } | null;
1600
- } | null;
1601
- }>;
1677
+ stats(): Promise<ApiResponse<Stats>>;
1602
1678
  }
1603
1679
 
1604
- 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
@@ -606,27 +606,37 @@ var Vaze = class extends Base {
606
606
  }
607
607
  /** Dashboard numbers, with each section limited to the caller's scopes. */
608
608
  async stats() {
609
- const { data, error } = await this.request(
609
+ const response = await this.request(
610
610
  "GET",
611
611
  this.apiUrl("/api/stats")
612
612
  );
613
- 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
+ });
614
620
  return {
615
- error,
616
- data: data ? {
617
- ...data,
621
+ error: null,
622
+ data: {
623
+ ...response.data,
618
624
  files: files ? {
619
625
  ...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
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
+ }
630
640
  };
631
641
  }
632
642
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@darseen/vaze",
3
- "version": "2.5.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
  },