@vex-chat/libvex 6.6.1 → 6.6.2

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/dist/Client.js CHANGED
@@ -5,10 +5,10 @@
5
5
  */
6
6
  import { enterCryptoProfileScope, getCryptoProfile, leaveCryptoProfileScope, setCryptoProfile, xBoxKeyPairAsync, xBoxKeyPairFromSecretAsync, xConcat, xConstants, xDHAsync, xEcdhKeyPairFromEcdsaKeyPairAsync, xEncode, xHMAC, xKDF, XKeyConvert, xMakeNonce, xMnemonic, xRandomBytes, xSecretboxAsync, xSecretboxOpenAsync, xSignAsync, xSignKeyPair, xSignKeyPairAsync, xSignKeyPairFromSecret, xSignKeyPairFromSecretAsync, XUtils, } from "@vex-chat/crypto";
7
7
  import { MailType, MailWSSchema, PermissionSchema, WSMessageSchema, } from "@vex-chat/types";
8
- import axios, { isAxiosError } from "axios";
9
8
  import { EventEmitter } from "eventemitter3";
10
9
  import * as uuid from "uuid";
11
10
  import { z } from "zod/v4";
11
+ import { createFetchHttpClient, isHttpError, } from "./http.js";
12
12
  import { clampLocalMessageRetentionDays, formatVexRetentionEnvelope, stripVexRetentionEnvelope, } from "./retention.js";
13
13
  import { WebSocketAdapter, WebSocketNotOpenError, } from "./transport/websocket.js";
14
14
  import { decodeFipsInitialExtraV1, encodeFipsInitialExtraV1, fipsP256AdFromIdentityPubs, fipsP256PreKeySignPayload, isFipsInitialExtraV1, } from "./utils/fipsMailExtra.js";
@@ -195,10 +195,22 @@ function spireErrorBodyMessage(data, max = 8_000) {
195
195
  return t.length > max ? t.slice(0, max) + "…" : t;
196
196
  }
197
197
  import { msgpack } from "./codec.js";
198
- import { ActionTokenCodec, AuthResponseCodec, ChannelArrayCodec, ChannelCodec, ConnectResponseCodec, decodeAxios, DeviceArrayCodec, DeviceChallengeCodec, DeviceCodec, DeviceRegistrationResultCodec, EmojiArrayCodec, EmojiCodec, FileSQLCodec, InviteArrayCodec, InviteCodec, KeyBundleCodec, OtkCountCodec, PasskeyArrayCodec, PasskeyAuthFinishResponseCodec, PasskeyCodec, PasskeyOptionsCodec, PendingDeviceRequestArrayCodec, PendingDeviceRequestCodec, PermissionArrayCodec, PermissionCodec, RegisterPendingApprovalCodec, RegisterResponseCodec, ServerArrayCodec, ServerChannelBootstrapCodec, ServerCodec, UserArrayCodec, UserCodec, WhoamiCodec, } from "./codecs.js";
198
+ import { ActionTokenCodec, AuthResponseCodec, ChannelArrayCodec, ChannelCodec, ConnectResponseCodec, decodeHttpResponse, DeviceArrayCodec, DeviceChallengeCodec, DeviceCodec, DeviceRegistrationResultCodec, EmojiArrayCodec, EmojiCodec, FileSQLCodec, InviteArrayCodec, InviteCodec, KeyBundleCodec, OtkCountCodec, PasskeyArrayCodec, PasskeyAuthFinishResponseCodec, PasskeyCodec, PasskeyOptionsCodec, PendingDeviceRequestArrayCodec, PendingDeviceRequestCodec, PermissionArrayCodec, PermissionCodec, RegisterPendingApprovalCodec, RegisterResponseCodec, ServerArrayCodec, ServerChannelBootstrapCodec, ServerCodec, UserArrayCodec, UserCodec, WhoamiCodec, } from "./codecs.js";
199
199
  import { sqlSessionToCrypto } from "./utils/sqlSessionToCrypto.js";
200
200
  import { uuidToUint8 } from "./utils/uint8uuid.js";
201
201
  const _protocolMsgRegex = /��\w+:\w+��/g;
202
+ const NotificationSubscriptionSchema = z.object({
203
+ channel: z.literal("expo"),
204
+ createdAt: z.string(),
205
+ deviceID: z.string(),
206
+ enabled: z.boolean(),
207
+ events: z.array(z.string()),
208
+ platform: z.string().nullable(),
209
+ subscriptionID: z.string(),
210
+ token: z.string(),
211
+ updatedAt: z.string(),
212
+ userID: z.string(),
213
+ });
202
214
  function compareInboxEntries(a, b) {
203
215
  const timeCmp = a[2].localeCompare(b[2]);
204
216
  if (timeCmp !== 0) {
@@ -585,7 +597,7 @@ export class Client {
585
597
  forwarded = new Set();
586
598
  host;
587
599
  http;
588
- /** Cancels in-flight axios work on `close()` so `postAuth`/`getMail` cannot hang forever. */
600
+ /** Cancels in-flight HTTP work on `close()` so `postAuth`/`getMail` cannot hang forever. */
589
601
  httpAbortController = new AbortController();
590
602
  idKeys;
591
603
  isAlive = true;
@@ -593,11 +605,6 @@ export class Client {
593
605
  localRetentionPurgeTimer = null;
594
606
  mailInterval;
595
607
  manuallyClosing = false;
596
- /**
597
- * Node-only: per-client HTTP(S) agents (see `init()` + `storage/node/http-agents`).
598
- * Dropped on `close()` so idle keep-alive sockets do not keep the process alive.
599
- */
600
- nodeHttpAgents;
601
608
  /* Retrieves the userID with the user identifier.
602
609
  user identifier is checked for userID, then signkey,
603
610
  and finally falls back to username. */
@@ -658,7 +665,7 @@ export class Client {
658
665
  this.database.on("error", (_error) => {
659
666
  void this.close(true);
660
667
  });
661
- this.http = axios.create({
668
+ this.http = createFetchHttpClient({
662
669
  responseType: "arraybuffer",
663
670
  signal: this.httpAbortController.signal,
664
671
  });
@@ -830,27 +837,6 @@ export class Client {
830
837
  return undefined;
831
838
  }
832
839
  }
833
- /**
834
- * True when running under Node (has `process.versions`).
835
- * Uses indirect lookup so the bare `process` global never appears in
836
- * source that the platform-guard plugin scans.
837
- */
838
- static isNodeRuntime() {
839
- try {
840
- const g = Object.getOwnPropertyDescriptor(globalThis, "\u0070rocess");
841
- if (!g)
842
- return false;
843
- const proc = typeof g.get === "function" ? g.get() : g.value;
844
- if (typeof proc !== "object" || proc === null) {
845
- return false;
846
- }
847
- return ("versions" in proc &&
848
- typeof proc.versions === "object");
849
- }
850
- catch {
851
- return false;
852
- }
853
- }
854
840
  /**
855
841
  * Closes the client — disconnects the WebSocket, shuts down storage,
856
842
  * and emits `closed` unless `muteEvent` is `true`.
@@ -867,11 +853,6 @@ export class Client {
867
853
  this.httpAbortController.abort();
868
854
  this.socket.close();
869
855
  await this.database.close();
870
- if (this.nodeHttpAgents) {
871
- this.nodeHttpAgents.http.destroy();
872
- this.nodeHttpAgents.https.destroy();
873
- delete this.nodeHttpAgents;
874
- }
875
856
  if (this.pingInterval) {
876
857
  clearInterval(this.pingInterval);
877
858
  }
@@ -909,7 +890,7 @@ export class Client {
909
890
  }
910
891
  const signedAsync = await xSignAsync(Uint8Array.from(uuid.parse(connectToken.key)), this.signKeys.secretKey);
911
892
  const res = await this.http.post(this.getHost() + "/device/" + this.device.deviceID + "/connect", msgpack.encode({ signed: signedAsync }), { headers: { "Content-Type": "application/msgpack" } });
912
- const { deviceToken } = decodeAxios(ConnectResponseCodec, res.data);
893
+ const { deviceToken } = decodeHttpResponse(ConnectResponseCodec, res.data);
913
894
  this.http.defaults.headers.common["X-Device-Token"] = deviceToken;
914
895
  this.autoReconnectEnabled = true;
915
896
  this.initSocket();
@@ -978,14 +959,14 @@ export class Client {
978
959
  }), {
979
960
  headers: { "Content-Type": "application/msgpack" },
980
961
  });
981
- const { token, user } = decodeAxios(AuthResponseCodec, res.data);
962
+ const { token, user } = decodeHttpResponse(AuthResponseCodec, res.data);
982
963
  this.setUser(user);
983
964
  this.token = token;
984
965
  this.http.defaults.headers.common.Authorization = `Bearer ${token}`;
985
966
  return { ok: true };
986
967
  }
987
968
  catch (err) {
988
- if (isAxiosError(err) && err.response) {
969
+ if (isHttpError(err) && err.response) {
989
970
  return {
990
971
  error: spireErrorBodyMessage(err.response.data),
991
972
  ok: false,
@@ -1014,10 +995,10 @@ export class Client {
1014
995
  deviceID: id,
1015
996
  signKey: signKeyHex,
1016
997
  }), { headers: { "Content-Type": "application/msgpack" } });
1017
- const { challenge, challengeID } = decodeAxios(DeviceChallengeCodec, challengeRes.data);
998
+ const { challenge, challengeID } = decodeHttpResponse(DeviceChallengeCodec, challengeRes.data);
1018
999
  const signed = XUtils.encodeHex(await xSignAsync(XUtils.decodeHex(challenge), this.signKeys.secretKey));
1019
1000
  const verifyRes = await this.http.post(this.getHost() + "/auth/device/verify", msgpack.encode({ challengeID, signed }), { headers: { "Content-Type": "application/msgpack" } });
1020
- const { token, user } = decodeAxios(AuthResponseCodec, verifyRes.data);
1001
+ const { token, user } = decodeHttpResponse(AuthResponseCodec, verifyRes.data);
1021
1002
  this.setUser(user);
1022
1003
  this.token = token;
1023
1004
  this.http.defaults.headers.common.Authorization = `Bearer ${token}`;
@@ -1128,7 +1109,7 @@ export class Client {
1128
1109
  let didDecodeRegisterResponse = false;
1129
1110
  let pendingApproval = null;
1130
1111
  try {
1131
- const { device, token, user } = decodeAxios(RegisterResponseCodec, res.data);
1112
+ const { device, token, user } = decodeHttpResponse(RegisterResponseCodec, res.data);
1132
1113
  this.device = device;
1133
1114
  this.setUser(user);
1134
1115
  this.token = token;
@@ -1140,7 +1121,7 @@ export class Client {
1140
1121
  }
1141
1122
  if (!didDecodeRegisterResponse) {
1142
1123
  try {
1143
- pendingApproval = decodeAxios(RegisterPendingApprovalCodec, res.data);
1124
+ pendingApproval = decodeHttpResponse(RegisterPendingApprovalCodec, res.data);
1144
1125
  }
1145
1126
  catch {
1146
1127
  // fall through to legacy decode path
@@ -1158,7 +1139,7 @@ export class Client {
1158
1139
  }),
1159
1140
  ];
1160
1141
  }
1161
- const legacyUser = decodeAxios(UserCodec, res.data);
1142
+ const legacyUser = decodeHttpResponse(UserCodec, res.data);
1162
1143
  this.setUser(legacyUser);
1163
1144
  // Legacy servers require /auth after /register to get a JWT.
1164
1145
  const loginResult = await this.login(resolvedUsername, resolvedPassword);
@@ -1173,7 +1154,7 @@ export class Client {
1173
1154
  return [this.getUser(), null];
1174
1155
  }
1175
1156
  catch (err) {
1176
- if (isAxiosError(err) && err.response) {
1157
+ if (isHttpError(err) && err.response) {
1177
1158
  return [
1178
1159
  null,
1179
1160
  new Error(spireErrorBodyMessage(err.response.data)),
@@ -1213,7 +1194,7 @@ export class Client {
1213
1194
  "/device/" +
1214
1195
  this.getDevice().deviceID +
1215
1196
  "/notifications/subscriptions", input, { responseType: "json" });
1216
- return response.data;
1197
+ return NotificationSubscriptionSchema.parse(response.data);
1217
1198
  }
1218
1199
  /**
1219
1200
  * Triggers an immediate inbox sync by fetching `/mail` once.
@@ -1254,7 +1235,7 @@ export class Client {
1254
1235
  */
1255
1236
  async whoami() {
1256
1237
  const res = await this.http.post(this.getHost() + "/whoami");
1257
- const whoami = decodeAxios(WhoamiCodec, res.data);
1238
+ const whoami = decodeHttpResponse(WhoamiCodec, res.data);
1258
1239
  return whoami;
1259
1240
  }
1260
1241
  async abortPendingDeviceRegistration(args) {
@@ -1299,16 +1280,16 @@ export class Client {
1299
1280
  "/devices/requests/" +
1300
1281
  requestID +
1301
1282
  "/approve", msgpack.encode({ signed }), { headers: { "Content-Type": "application/msgpack" } });
1302
- return decodeAxios(DeviceCodec, response.data);
1283
+ return decodeHttpResponse(DeviceCodec, response.data);
1303
1284
  }
1304
1285
  async beginPasskeyAuthentication(username) {
1305
1286
  const response = await this.http.post(this.getHost() + "/auth/passkey/begin", msgpack.encode({ username }), { headers: { "Content-Type": "application/msgpack" } });
1306
- return decodeAxios(PasskeyOptionsCodec, response.data);
1287
+ return decodeHttpResponse(PasskeyOptionsCodec, response.data);
1307
1288
  }
1308
1289
  async beginPasskeyRegistration(name) {
1309
1290
  const userID = this.getUser().userID;
1310
1291
  const response = await this.http.post(this.getHost() + "/user/" + userID + "/passkeys/register/begin", msgpack.encode({ name }), { headers: { "Content-Type": "application/msgpack" } });
1311
- return decodeAxios(PasskeyOptionsCodec, response.data);
1292
+ return decodeHttpResponse(PasskeyOptionsCodec, response.data);
1312
1293
  }
1313
1294
  censorPreKey(preKey) {
1314
1295
  if (!preKey.index) {
@@ -1324,7 +1305,7 @@ export class Client {
1324
1305
  async createChannel(name, serverID) {
1325
1306
  const body = { name };
1326
1307
  const res = await this.http.post(this.getHost() + "/server/" + serverID + "/channels", msgpack.encode(body), { headers: { "Content-Type": "application/msgpack" } });
1327
- return decodeAxios(ChannelCodec, res.data);
1308
+ return decodeHttpResponse(ChannelCodec, res.data);
1328
1309
  }
1329
1310
  // returns the file details and the encryption key
1330
1311
  async createFile(file) {
@@ -1355,7 +1336,7 @@ export class Client {
1355
1336
  this.emitter.emit("fileProgress", progress);
1356
1337
  },
1357
1338
  });
1358
- const fcreatedFile = decodeAxios(FileSQLCodec, fres.data);
1339
+ const fcreatedFile = decodeHttpResponse(FileSQLCodec, fres.data);
1359
1340
  return [fcreatedFile, XUtils.encodeHex(fileKey)];
1360
1341
  }
1361
1342
  const payload = {
@@ -1364,7 +1345,7 @@ export class Client {
1364
1345
  owner: this.getDevice().deviceID,
1365
1346
  };
1366
1347
  const res = await this.http.post(this.getHost() + "/file/json", msgpack.encode(payload), { headers: { "Content-Type": "application/msgpack" } });
1367
- const createdFile = decodeAxios(FileSQLCodec, res.data);
1348
+ const createdFile = decodeHttpResponse(FileSQLCodec, res.data);
1368
1349
  return [createdFile, XUtils.encodeHex(fileKey)];
1369
1350
  });
1370
1351
  }
@@ -1374,7 +1355,7 @@ export class Client {
1374
1355
  serverID,
1375
1356
  };
1376
1357
  const res = await this.http.post(this.getHost() + "/server/" + serverID + "/invites", msgpack.encode(payload), { headers: { "Content-Type": "application/msgpack" } });
1377
- return decodeAxios(InviteCodec, res.data);
1358
+ return decodeHttpResponse(InviteCodec, res.data);
1378
1359
  }
1379
1360
  async createPreKey() {
1380
1361
  const preKeyPair = await xBoxKeyPairAsync();
@@ -1388,7 +1369,7 @@ export class Client {
1388
1369
  }
1389
1370
  async createServer(name) {
1390
1371
  const res = await this.http.post(this.getHost() + "/server/" + globalThis.btoa(name));
1391
- return decodeAxios(ServerCodec, res.data);
1372
+ return decodeHttpResponse(ServerCodec, res.data);
1392
1373
  }
1393
1374
  async createSession(device, user, message, group,
1394
1375
  /* this is passed through if the first message is
@@ -1584,7 +1565,7 @@ export class Client {
1584
1565
  await this.http.delete(this.getHost() + "/server/" + serverID);
1585
1566
  }
1586
1567
  deviceListFailureDetail(err) {
1587
- if (!isAxiosError(err)) {
1568
+ if (!isHttpError(err)) {
1588
1569
  return "";
1589
1570
  }
1590
1571
  const st = err.response?.status;
@@ -1607,7 +1588,7 @@ export class Client {
1607
1588
  "/server/" +
1608
1589
  serverID +
1609
1590
  "/permissions");
1610
- return decodeAxios(PermissionArrayCodec, res.data);
1591
+ return decodeHttpResponse(PermissionArrayCodec, res.data);
1611
1592
  }
1612
1593
  async fetchUser(userIdentifier) {
1613
1594
  // Usernames are case-insensitive at the protocol level, so
@@ -1631,19 +1612,19 @@ export class Client {
1631
1612
  }
1632
1613
  try {
1633
1614
  const res = await this.http.get(this.getHost() + "/user/" + cacheKey);
1634
- const userRecord = decodeAxios(UserCodec, res.data);
1615
+ const userRecord = decodeHttpResponse(UserCodec, res.data);
1635
1616
  this.userRecords[cacheKey] = userRecord;
1636
1617
  this.notFoundUsers.delete(cacheKey);
1637
1618
  return [userRecord, null];
1638
1619
  }
1639
1620
  catch (err) {
1640
- if (isAxiosError(err) && err.response?.status === 404) {
1621
+ if (isHttpError(err) && err.response?.status === 404) {
1641
1622
  // Definitive: user doesn't exist — cache and don't retry
1642
1623
  this.notFoundUsers.set(cacheKey, Date.now());
1643
1624
  return [null, err];
1644
1625
  }
1645
1626
  // Transient (5xx, network error) — don't cache, caller can retry
1646
- return [null, isAxiosError(err) ? err : null];
1627
+ return [null, isHttpError(err) ? err : null];
1647
1628
  }
1648
1629
  }
1649
1630
  async fetchUserDeviceListOnce(userID) {
@@ -1651,7 +1632,7 @@ export class Client {
1651
1632
  return [];
1652
1633
  }
1653
1634
  const res = await this.http.get(this.getHost() + "/user/" + userID + "/devices");
1654
- const devices = decodeAxios(DeviceArrayCodec, res.data);
1635
+ const devices = decodeHttpResponse(DeviceArrayCodec, res.data);
1655
1636
  for (const device of devices) {
1656
1637
  this.deviceRecords[device.deviceID] = device;
1657
1638
  }
@@ -1698,7 +1679,7 @@ export class Client {
1698
1679
  */
1699
1680
  async finishPasskeyAuthentication(args) {
1700
1681
  const response = await this.http.post(this.getHost() + "/auth/passkey/finish", msgpack.encode(args), { headers: { "Content-Type": "application/msgpack" } });
1701
- const decoded = decodeAxios(PasskeyAuthFinishResponseCodec, response.data);
1682
+ const decoded = decodeHttpResponse(PasskeyAuthFinishResponseCodec, response.data);
1702
1683
  this.setUser(decoded.user);
1703
1684
  this.token = decoded.token;
1704
1685
  this.http.defaults.headers.common.Authorization = `Bearer ${decoded.token}`;
@@ -1707,7 +1688,7 @@ export class Client {
1707
1688
  async finishPasskeyRegistration(args) {
1708
1689
  const userID = this.getUser().userID;
1709
1690
  const response = await this.http.post(this.getHost() + "/user/" + userID + "/passkeys/register/finish", msgpack.encode(args), { headers: { "Content-Type": "application/msgpack" } });
1710
- return decodeAxios(PasskeyCodec, response.data);
1691
+ return decodeHttpResponse(PasskeyCodec, response.data);
1711
1692
  }
1712
1693
  async forward(message) {
1713
1694
  if (this.isManualCloseInFlight()) {
@@ -1741,7 +1722,7 @@ export class Client {
1741
1722
  async getChannelByID(channelID) {
1742
1723
  try {
1743
1724
  const res = await this.http.get(this.getHost() + "/channel/" + channelID);
1744
- return decodeAxios(ChannelCodec, res.data);
1725
+ return decodeHttpResponse(ChannelCodec, res.data);
1745
1726
  }
1746
1727
  catch (_err) {
1747
1728
  return null;
@@ -1749,7 +1730,7 @@ export class Client {
1749
1730
  }
1750
1731
  async getChannelList(serverID) {
1751
1732
  const res = await this.http.get(this.getHost() + "/server/" + serverID + "/channels");
1752
- return decodeAxios(ChannelArrayCodec, res.data);
1733
+ return decodeHttpResponse(ChannelArrayCodec, res.data);
1753
1734
  }
1754
1735
  getDevice() {
1755
1736
  if (!this.device) {
@@ -1768,7 +1749,7 @@ export class Client {
1768
1749
  }
1769
1750
  try {
1770
1751
  const res = await this.http.get(this.getHost() + "/device/" + deviceID);
1771
- const fetchedDevice = decodeAxios(DeviceCodec, res.data);
1752
+ const fetchedDevice = decodeHttpResponse(DeviceCodec, res.data);
1772
1753
  this.deviceRecords[deviceID] = fetchedDevice;
1773
1754
  await this.database.saveDevice(fetchedDevice);
1774
1755
  return fetchedDevice;
@@ -1785,10 +1766,10 @@ export class Client {
1785
1766
  this.getUser().userID +
1786
1767
  "/devices/requests/" +
1787
1768
  requestID);
1788
- return decodeAxios(PendingDeviceRequestCodec, response.data);
1769
+ return decodeHttpResponse(PendingDeviceRequestCodec, response.data);
1789
1770
  }
1790
1771
  catch (err) {
1791
- if (isAxiosError(err) && err.response?.status === 404) {
1772
+ if (isHttpError(err) && err.response?.status === 404) {
1792
1773
  return null;
1793
1774
  }
1794
1775
  throw err;
@@ -1885,7 +1866,7 @@ export class Client {
1885
1866
  async getMultiUserDeviceList(userIDs) {
1886
1867
  try {
1887
1868
  const res = await this.http.post(this.getHost() + "/deviceList", msgpack.encode(userIDs), { headers: { "Content-Type": "application/msgpack" } });
1888
- const devices = decodeAxios(DeviceArrayCodec, res.data);
1869
+ const devices = decodeHttpResponse(DeviceArrayCodec, res.data);
1889
1870
  for (const device of devices) {
1890
1871
  this.deviceRecords[device.deviceID] = device;
1891
1872
  }
@@ -1900,7 +1881,7 @@ export class Client {
1900
1881
  "/device/" +
1901
1882
  this.getDevice().deviceID +
1902
1883
  "/otk/count");
1903
- return decodeAxios(OtkCountCodec, res.data).count;
1884
+ return decodeHttpResponse(OtkCountCodec, res.data).count;
1904
1885
  }
1905
1886
  /**
1906
1887
  * Gets all permissions for the logged in user.
@@ -1909,12 +1890,12 @@ export class Client {
1909
1890
  */
1910
1891
  async getPermissions() {
1911
1892
  const res = await this.http.get(this.getHost() + "/user/" + this.getUser().userID + "/permissions");
1912
- return decodeAxios(PermissionArrayCodec, res.data);
1893
+ return decodeHttpResponse(PermissionArrayCodec, res.data);
1913
1894
  }
1914
1895
  async getServerByID(serverID) {
1915
1896
  try {
1916
1897
  const res = await this.http.get(this.getHost() + "/server/" + serverID);
1917
- return decodeAxios(ServerCodec, res.data);
1898
+ return decodeHttpResponse(ServerCodec, res.data);
1918
1899
  }
1919
1900
  catch (_err) {
1920
1901
  return null;
@@ -1925,11 +1906,11 @@ export class Client {
1925
1906
  "/user/" +
1926
1907
  this.getUser().userID +
1927
1908
  "/servers/bootstrap");
1928
- return decodeAxios(ServerChannelBootstrapCodec, res.data);
1909
+ return decodeHttpResponse(ServerChannelBootstrapCodec, res.data);
1929
1910
  }
1930
1911
  async getServerList() {
1931
1912
  const res = await this.http.get(this.getHost() + "/user/" + this.getUser().userID + "/servers");
1932
- return decodeAxios(ServerArrayCodec, res.data);
1913
+ return decodeHttpResponse(ServerArrayCodec, res.data);
1933
1914
  }
1934
1915
  async getSessionByPubkey(publicKey) {
1935
1916
  const strPubKey = XUtils.encodeHex(publicKey);
@@ -1950,7 +1931,7 @@ export class Client {
1950
1931
  const res = await this.http.get(this.getHost() + "/token/" + type, {
1951
1932
  responseType: "arraybuffer",
1952
1933
  });
1953
- return decodeAxios(ActionTokenCodec, res.data);
1934
+ return decodeHttpResponse(ActionTokenCodec, res.data);
1954
1935
  }
1955
1936
  catch {
1956
1937
  return null;
@@ -1980,7 +1961,7 @@ export class Client {
1980
1961
  }
1981
1962
  async getUserList(channelID) {
1982
1963
  const res = await this.http.post(this.getHost() + "/userList/" + channelID);
1983
- return decodeAxios(UserArrayCodec, res.data);
1964
+ return decodeHttpResponse(UserArrayCodec, res.data);
1984
1965
  }
1985
1966
  async handleNotify(msg) {
1986
1967
  switch (msg.event) {
@@ -2044,12 +2025,6 @@ export class Client {
2044
2025
  throw new Error("You should only call init() once.");
2045
2026
  }
2046
2027
  this.hasInit = true;
2047
- if (Client.isNodeRuntime()) {
2048
- const { attachNodeAgentsToAxios, createNodeHttpAgents } = await import("./storage/node/http-agents.js");
2049
- const agents = createNodeHttpAgents();
2050
- this.nodeHttpAgents = agents;
2051
- attachNodeAgentsToAxios(this.http, agents);
2052
- }
2053
2028
  await this.populateKeyRing();
2054
2029
  this.emitter.on("message", this.onInternalMessage);
2055
2030
  void this.runLocalRetentionPurge();
@@ -2182,7 +2157,7 @@ export class Client {
2182
2157
  "/user/" +
2183
2158
  this.getUser().userID +
2184
2159
  "/devices/requests");
2185
- return decodeAxios(PendingDeviceRequestArrayCodec, response.data);
2160
+ return decodeHttpResponse(PendingDeviceRequestArrayCodec, response.data);
2186
2161
  }
2187
2162
  /**
2188
2163
  * Lists every device the current account owns.
@@ -2193,12 +2168,12 @@ export class Client {
2193
2168
  async listDevices() {
2194
2169
  const userID = this.getUser().userID;
2195
2170
  const res = await this.http.get(this.getHost() + "/user/" + userID + "/devices");
2196
- return decodeAxios(DeviceArrayCodec, res.data);
2171
+ return decodeHttpResponse(DeviceArrayCodec, res.data);
2197
2172
  }
2198
2173
  async listPasskeys() {
2199
2174
  const userID = this.getUser().userID;
2200
2175
  const response = await this.http.get(this.getHost() + "/user/" + userID + "/passkeys");
2201
- return decodeAxios(PasskeyArrayCodec, response.data);
2176
+ return decodeHttpResponse(PasskeyArrayCodec, response.data);
2202
2177
  }
2203
2178
  async markSessionVerified(sessionID) {
2204
2179
  return this.database.markSessionVerified(sessionID);
@@ -2249,7 +2224,7 @@ export class Client {
2249
2224
  "/passkey/devices/requests/" +
2250
2225
  requestID +
2251
2226
  "/approve");
2252
- return decodeAxios(DeviceCodec, response.data);
2227
+ return decodeHttpResponse(DeviceCodec, response.data);
2253
2228
  }
2254
2229
  async passkeyDeleteDevice(deviceID) {
2255
2230
  const userID = this.getUser().userID;
@@ -2258,7 +2233,7 @@ export class Client {
2258
2233
  async passkeyListDevices() {
2259
2234
  const userID = this.getUser().userID;
2260
2235
  const response = await this.http.get(this.getHost() + "/user/" + userID + "/passkey/devices");
2261
- return decodeAxios(DeviceArrayCodec, response.data);
2236
+ return decodeHttpResponse(DeviceArrayCodec, response.data);
2262
2237
  }
2263
2238
  async passkeyRejectDeviceRequest(requestID) {
2264
2239
  const userID = this.getUser().userID;
@@ -2310,10 +2285,10 @@ export class Client {
2310
2285
  "/user/devices/requests/" +
2311
2286
  args.requestID +
2312
2287
  "/poll", msgpack.encode({ signed }), { headers: { "Content-Type": "application/msgpack" } });
2313
- return decodeAxios(PendingDeviceRequestCodec, response.data);
2288
+ return decodeHttpResponse(PendingDeviceRequestCodec, response.data);
2314
2289
  }
2315
2290
  catch (err) {
2316
- if (isAxiosError(err) && err.response?.status === 404) {
2291
+ if (isHttpError(err) && err.response?.status === 404) {
2317
2292
  return null;
2318
2293
  }
2319
2294
  throw err;
@@ -2930,7 +2905,7 @@ export class Client {
2930
2905
  }
2931
2906
  async redeemInvite(inviteID) {
2932
2907
  const res = await this.http.patch(this.getHost() + "/invite/" + inviteID);
2933
- return decodeAxios(PermissionCodec, res.data);
2908
+ return decodeHttpResponse(PermissionCodec, res.data);
2934
2909
  }
2935
2910
  registerDecryptFailure(mail) {
2936
2911
  const count = (this.decryptFailureCounts.get(mail.mailID) ?? 0) + 1;
@@ -2969,7 +2944,7 @@ export class Client {
2969
2944
  "/user/" +
2970
2945
  userDetails.userID +
2971
2946
  "/devices", msgpack.encode(devMsg), { headers: { "Content-Type": "application/msgpack" } });
2972
- return decodeAxios(DeviceRegistrationResultCodec, res.data);
2947
+ return decodeHttpResponse(DeviceRegistrationResultCodec, res.data);
2973
2948
  }
2974
2949
  async rejectDeviceRequest(requestID) {
2975
2950
  await this.http.post(this.prefixes.HTTP +
@@ -2996,22 +2971,18 @@ export class Client {
2996
2971
  }
2997
2972
  async retrieveEmojiByID(emojiID) {
2998
2973
  const res = await this.http.get(this.getHost() + "/emoji/" + emojiID + "/details");
2999
- if (!res.data) {
3000
- return null;
3001
- }
3002
- return decodeAxios(EmojiCodec, res.data);
2974
+ return decodeHttpResponse(EmojiCodec, res.data);
3003
2975
  }
3004
2976
  async retrieveEmojiList(serverID) {
3005
2977
  const res = await this.http.get(this.getHost() + "/server/" + serverID + "/emoji");
3006
- return decodeAxios(EmojiArrayCodec, res.data);
2978
+ return decodeHttpResponse(EmojiArrayCodec, res.data);
3007
2979
  }
3008
2980
  async retrieveFile(fileID, key) {
3009
2981
  const detailsRes = await this.http.get(this.getHost() + "/file/" + fileID + "/details");
3010
- const details = decodeAxios(FileSQLCodec, detailsRes.data);
2982
+ const details = decodeHttpResponse(FileSQLCodec, detailsRes.data);
3011
2983
  const res = await this.http.get(this.getHost() + "/file/" + fileID, {
3012
2984
  onDownloadProgress: (progressEvent) => {
3013
- const percentCompleted = Math.round((progressEvent.loaded * 100) /
3014
- (progressEvent.total ?? 1));
2985
+ const percentCompleted = Math.round((progressEvent.loaded * 100) / (progressEvent.total ?? 1));
3015
2986
  const { loaded, total = 0 } = progressEvent;
3016
2987
  const progress = {
3017
2988
  direction: "download",
@@ -3035,11 +3006,11 @@ export class Client {
3035
3006
  }
3036
3007
  async retrieveInvites(serverID) {
3037
3008
  const res = await this.http.get(this.getHost() + "/server/" + serverID + "/invites");
3038
- return decodeAxios(InviteArrayCodec, res.data);
3009
+ return decodeHttpResponse(InviteArrayCodec, res.data);
3039
3010
  }
3040
3011
  async retrieveKeyBundle(deviceID) {
3041
3012
  const res = await this.http.post(this.getHost() + "/device/" + deviceID + "/keyBundle");
3042
- return decodeAxios(KeyBundleCodec, res.data);
3013
+ return decodeHttpResponse(KeyBundleCodec, res.data);
3043
3014
  }
3044
3015
  async retrieveOrCreateDevice() {
3045
3016
  let device;
@@ -3048,10 +3019,10 @@ export class Client {
3048
3019
  this.host +
3049
3020
  "/device/" +
3050
3021
  XUtils.encodeHex(this.signKeys.publicKey));
3051
- device = decodeAxios(DeviceCodec, res.data);
3022
+ device = decodeHttpResponse(DeviceCodec, res.data);
3052
3023
  }
3053
3024
  catch (err) {
3054
- if (isAxiosError(err) && err.response?.status === 404) {
3025
+ if (isHttpError(err) && err.response?.status === 404) {
3055
3026
  await this.database.purgeKeyData();
3056
3027
  await this.populateKeyRing();
3057
3028
  const newDevice = await this.registerDevice();
@@ -3634,7 +3605,7 @@ export class Client {
3634
3605
  this.emitter.emit("fileProgress", progress);
3635
3606
  },
3636
3607
  });
3637
- return decodeAxios(EmojiCodec, res.data);
3608
+ return decodeHttpResponse(EmojiCodec, res.data);
3638
3609
  }
3639
3610
  catch (_err) {
3640
3611
  return null;
@@ -3646,7 +3617,7 @@ export class Client {
3646
3617
  };
3647
3618
  try {
3648
3619
  const res = await this.http.post(this.getHost() + "/emoji/" + serverID + "/json", msgpack.encode(payload), { headers: { "Content-Type": "application/msgpack" } });
3649
- return decodeAxios(EmojiCodec, res.data);
3620
+ return decodeHttpResponse(EmojiCodec, res.data);
3650
3621
  }
3651
3622
  catch (_err) {
3652
3623
  return null;