@aegis-fluxion/core 0.4.0 → 0.7.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/dist/index.js CHANGED
@@ -4,6 +4,8 @@ import WebSocket, { WebSocketServer } from 'ws';
4
4
  // src/index.ts
5
5
  var DEFAULT_CLOSE_CODE = 1e3;
6
6
  var DEFAULT_CLOSE_REASON = "";
7
+ var POLICY_VIOLATION_CLOSE_CODE = 1008;
8
+ var POLICY_VIOLATION_CLOSE_REASON = "Connection rejected by middleware.";
7
9
  var INTERNAL_HANDSHAKE_EVENT = "__handshake";
8
10
  var INTERNAL_RPC_REQUEST_EVENT = "__rpc:req";
9
11
  var INTERNAL_RPC_RESPONSE_EVENT = "__rpc:res";
@@ -15,6 +17,8 @@ var GCM_AUTH_TAG_LENGTH = 16;
15
17
  var ENCRYPTION_KEY_LENGTH = 32;
16
18
  var ENCRYPTED_PACKET_VERSION = 1;
17
19
  var ENCRYPTED_PACKET_PREFIX_LENGTH = 1 + GCM_IV_LENGTH + GCM_AUTH_TAG_LENGTH;
20
+ var BINARY_PAYLOAD_MARKER = "__afxBinaryPayload";
21
+ var BINARY_PAYLOAD_VERSION = 1;
18
22
  var DEFAULT_HEARTBEAT_INTERVAL_MS = 15e3;
19
23
  var DEFAULT_HEARTBEAT_TIMEOUT_MS = 15e3;
20
24
  var DEFAULT_RECONNECT_INITIAL_DELAY_MS = 250;
@@ -55,7 +59,103 @@ function rawDataToBuffer(rawData) {
55
59
  }
56
60
  return Buffer.from(rawData);
57
61
  }
58
- function serializeEnvelope(event, data) {
62
+ function isBlobValue(value) {
63
+ return typeof Blob !== "undefined" && value instanceof Blob;
64
+ }
65
+ function isPlainObject(value) {
66
+ if (typeof value !== "object" || value === null) {
67
+ return false;
68
+ }
69
+ const prototype = Object.getPrototypeOf(value);
70
+ return prototype === Object.prototype || prototype === null;
71
+ }
72
+ function encodeBinaryPayload(kind, payloadBuffer, mimeType) {
73
+ const encodedPayload = {
74
+ [BINARY_PAYLOAD_MARKER]: BINARY_PAYLOAD_VERSION,
75
+ kind,
76
+ base64: payloadBuffer.toString("base64")
77
+ };
78
+ if (mimeType !== void 0 && mimeType.length > 0) {
79
+ encodedPayload.mimeType = mimeType;
80
+ }
81
+ return encodedPayload;
82
+ }
83
+ async function encodeEnvelopeData(value) {
84
+ if (Buffer.isBuffer(value)) {
85
+ return encodeBinaryPayload("buffer", value);
86
+ }
87
+ if (value instanceof Uint8Array) {
88
+ const typedArrayBuffer = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
89
+ return encodeBinaryPayload("uint8array", typedArrayBuffer);
90
+ }
91
+ if (isBlobValue(value)) {
92
+ const blobBuffer = Buffer.from(await value.arrayBuffer());
93
+ return encodeBinaryPayload("blob", blobBuffer, value.type);
94
+ }
95
+ if (Array.isArray(value)) {
96
+ return Promise.all(value.map((item) => encodeEnvelopeData(item)));
97
+ }
98
+ if (isPlainObject(value)) {
99
+ const encodedEntries = await Promise.all(
100
+ Object.entries(value).map(async ([key, entryValue]) => {
101
+ return [key, await encodeEnvelopeData(entryValue)];
102
+ })
103
+ );
104
+ return Object.fromEntries(encodedEntries);
105
+ }
106
+ return value;
107
+ }
108
+ function isEncodedBinaryPayload(value) {
109
+ if (!isPlainObject(value)) {
110
+ return false;
111
+ }
112
+ if (value[BINARY_PAYLOAD_MARKER] !== BINARY_PAYLOAD_VERSION) {
113
+ return false;
114
+ }
115
+ if (value.kind !== "buffer" && value.kind !== "uint8array" && value.kind !== "blob") {
116
+ return false;
117
+ }
118
+ if (typeof value.base64 !== "string") {
119
+ return false;
120
+ }
121
+ if (value.mimeType !== void 0 && typeof value.mimeType !== "string") {
122
+ return false;
123
+ }
124
+ return true;
125
+ }
126
+ function decodeEnvelopeData(value) {
127
+ if (Array.isArray(value)) {
128
+ return value.map((item) => decodeEnvelopeData(item));
129
+ }
130
+ if (isEncodedBinaryPayload(value)) {
131
+ const binaryBuffer = Buffer.from(value.base64, "base64");
132
+ if (value.kind === "buffer") {
133
+ return binaryBuffer;
134
+ }
135
+ if (value.kind === "uint8array") {
136
+ return Uint8Array.from(binaryBuffer);
137
+ }
138
+ if (typeof Blob === "undefined") {
139
+ return binaryBuffer;
140
+ }
141
+ return new Blob([binaryBuffer], {
142
+ type: value.mimeType ?? ""
143
+ });
144
+ }
145
+ if (isPlainObject(value)) {
146
+ const decodedEntries = Object.entries(value).map(([key, entryValue]) => {
147
+ return [key, decodeEnvelopeData(entryValue)];
148
+ });
149
+ return Object.fromEntries(decodedEntries);
150
+ }
151
+ return value;
152
+ }
153
+ async function serializeEnvelope(event, data) {
154
+ const encodedData = await encodeEnvelopeData(data);
155
+ const envelope = { event, data: encodedData };
156
+ return JSON.stringify(envelope);
157
+ }
158
+ function serializePlainEnvelope(event, data) {
59
159
  const envelope = { event, data };
60
160
  return JSON.stringify(envelope);
61
161
  }
@@ -67,7 +167,7 @@ function parseEnvelope(rawData) {
67
167
  }
68
168
  return {
69
169
  event: parsed.event,
70
- data: parsed.data
170
+ data: decodeEnvelopeData(parsed.data)
71
171
  };
72
172
  }
73
173
  function parseEnvelopeFromText(decodedPayload) {
@@ -77,7 +177,7 @@ function parseEnvelopeFromText(decodedPayload) {
77
177
  }
78
178
  return {
79
179
  event: parsed.event,
80
- data: parsed.data
180
+ data: decodeEnvelopeData(parsed.data)
81
181
  };
82
182
  }
83
183
  function decodeCloseReason(reason) {
@@ -259,7 +359,9 @@ var SecureServer = class {
259
359
  disconnectHandlers = /* @__PURE__ */ new Set();
260
360
  readyHandlers = /* @__PURE__ */ new Set();
261
361
  errorHandlers = /* @__PURE__ */ new Set();
362
+ middlewareHandlers = [];
262
363
  handshakeStateBySocket = /* @__PURE__ */ new WeakMap();
364
+ middlewareMetadataBySocket = /* @__PURE__ */ new WeakMap();
263
365
  sharedSecretBySocket = /* @__PURE__ */ new WeakMap();
264
366
  encryptionKeyBySocket = /* @__PURE__ */ new WeakMap();
265
367
  pendingPayloadsBySocket = /* @__PURE__ */ new WeakMap();
@@ -348,6 +450,19 @@ var SecureServer = class {
348
450
  }
349
451
  return this;
350
452
  }
453
+ use(middleware) {
454
+ try {
455
+ if (typeof middleware !== "function") {
456
+ throw new Error("Server middleware must be a function.");
457
+ }
458
+ this.middlewareHandlers.push(middleware);
459
+ } catch (error) {
460
+ this.notifyError(
461
+ normalizeToError(error, "Failed to register server middleware.")
462
+ );
463
+ }
464
+ return this;
465
+ }
351
466
  emit(event, data) {
352
467
  try {
353
468
  if (isReservedEmitEvent(event)) {
@@ -355,7 +470,9 @@ var SecureServer = class {
355
470
  }
356
471
  const envelope = { event, data };
357
472
  for (const client of this.clientsById.values()) {
358
- this.sendOrQueuePayload(client.socket, envelope);
473
+ void this.sendOrQueuePayload(client.socket, envelope).catch(() => {
474
+ return void 0;
475
+ });
359
476
  }
360
477
  } catch (error) {
361
478
  this.notifyError(normalizeToError(error, "Failed to emit server event."));
@@ -373,7 +490,9 @@ var SecureServer = class {
373
490
  throw new Error(`Client with id ${clientId} was not found.`);
374
491
  }
375
492
  if (!ackArgs.expectsAck) {
376
- this.sendOrQueuePayload(client.socket, { event, data });
493
+ void this.sendOrQueuePayload(client.socket, { event, data }).catch(() => {
494
+ return void 0;
495
+ });
377
496
  return true;
378
497
  }
379
498
  const ackPromise = this.sendRpcRequest(
@@ -429,6 +548,7 @@ var SecureServer = class {
429
548
  client.socket,
430
549
  new Error("Server closed before ACK response was received.")
431
550
  );
551
+ this.middlewareMetadataBySocket.delete(client.socket);
432
552
  if (client.socket.readyState === WebSocket.OPEN || client.socket.readyState === WebSocket.CONNECTING) {
433
553
  client.socket.close(code, reason);
434
554
  }
@@ -491,6 +611,7 @@ var SecureServer = class {
491
611
  this.pendingRpcRequestsBySocket.delete(socket);
492
612
  this.handshakeStateBySocket.delete(socket);
493
613
  this.heartbeatStateBySocket.delete(socket);
614
+ this.middlewareMetadataBySocket.delete(socket);
494
615
  socket.terminate();
495
616
  continue;
496
617
  }
@@ -520,17 +641,46 @@ var SecureServer = class {
520
641
  }
521
642
  bindSocketServerEvents() {
522
643
  this.socketServer.on("connection", (socket, request) => {
523
- this.handleConnection(socket, request);
644
+ void this.handleConnection(socket, request);
524
645
  });
525
646
  this.socketServer.on("error", (error) => {
526
647
  this.notifyError(normalizeToError(error, "WebSocket server encountered an error."));
527
648
  });
528
649
  }
529
- handleConnection(socket, request) {
650
+ async handleConnection(socket, request) {
651
+ const connectionMetadata = /* @__PURE__ */ new Map();
652
+ this.middlewareMetadataBySocket.set(socket, connectionMetadata);
653
+ try {
654
+ await this.executeServerMiddleware({
655
+ phase: "connection",
656
+ socket,
657
+ request,
658
+ metadata: connectionMetadata
659
+ });
660
+ } catch (error) {
661
+ const normalizedError = normalizeToError(
662
+ error,
663
+ "Connection middleware rejected the incoming socket."
664
+ );
665
+ this.notifyError(normalizedError);
666
+ this.middlewareMetadataBySocket.delete(socket);
667
+ if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
668
+ socket.close(
669
+ POLICY_VIOLATION_CLOSE_CODE,
670
+ normalizedError.message || POLICY_VIOLATION_CLOSE_REASON
671
+ );
672
+ }
673
+ return;
674
+ }
530
675
  try {
531
676
  const clientId = randomUUID();
532
677
  const handshakeState = this.createServerHandshakeState();
533
- const client = this.createSecureServerClient(clientId, socket, request);
678
+ const client = this.createSecureServerClient(
679
+ clientId,
680
+ socket,
681
+ request,
682
+ connectionMetadata
683
+ );
534
684
  this.clientsById.set(clientId, client);
535
685
  this.clientIdBySocket.set(socket, clientId);
536
686
  this.handshakeStateBySocket.set(socket, handshakeState);
@@ -542,7 +692,7 @@ var SecureServer = class {
542
692
  });
543
693
  this.roomNamesByClientId.set(clientId, /* @__PURE__ */ new Set());
544
694
  socket.on("message", (rawData) => {
545
- this.handleIncomingMessage(client, rawData);
695
+ void this.handleIncomingMessage(client, rawData);
546
696
  });
547
697
  socket.on("close", (code, reason) => {
548
698
  this.handleDisconnection(client, code, reason);
@@ -562,9 +712,10 @@ var SecureServer = class {
562
712
  this.notifyConnection(client);
563
713
  } catch (error) {
564
714
  this.notifyError(normalizeToError(error, "Failed to handle client connection."));
715
+ this.middlewareMetadataBySocket.delete(socket);
565
716
  }
566
717
  }
567
- handleIncomingMessage(client, rawData) {
718
+ async handleIncomingMessage(client, rawData) {
568
719
  try {
569
720
  let envelope = null;
570
721
  try {
@@ -608,10 +759,16 @@ var SecureServer = class {
608
759
  return;
609
760
  }
610
761
  if (decryptedEnvelope.event === INTERNAL_RPC_REQUEST_EVENT) {
611
- void this.handleRpcRequest(client, decryptedEnvelope.data);
762
+ await this.handleRpcRequest(client, decryptedEnvelope.data);
612
763
  return;
613
764
  }
614
- this.dispatchCustomEvent(decryptedEnvelope.event, decryptedEnvelope.data, client);
765
+ const interceptedData = await this.applyMessageMiddleware(
766
+ "incoming",
767
+ client,
768
+ decryptedEnvelope.event,
769
+ decryptedEnvelope.data
770
+ );
771
+ this.dispatchCustomEvent(decryptedEnvelope.event, interceptedData, client);
615
772
  } catch (error) {
616
773
  this.notifyError(normalizeToError(error, "Failed to process incoming server message."));
617
774
  }
@@ -631,6 +788,7 @@ var SecureServer = class {
631
788
  );
632
789
  this.pendingRpcRequestsBySocket.delete(client.socket);
633
790
  this.heartbeatStateBySocket.delete(client.socket);
791
+ this.middlewareMetadataBySocket.delete(client.socket);
634
792
  const decodedReason = decodeCloseReason(reason);
635
793
  for (const handler of this.disconnectHandlers) {
636
794
  try {
@@ -676,6 +834,48 @@ var SecureServer = class {
676
834
  }
677
835
  }
678
836
  }
837
+ async executeServerMiddleware(context) {
838
+ if (this.middlewareHandlers.length === 0) {
839
+ return;
840
+ }
841
+ let currentIndex = -1;
842
+ const dispatch = async (index) => {
843
+ if (index <= currentIndex) {
844
+ throw new Error("Server middleware next() was called multiple times.");
845
+ }
846
+ currentIndex = index;
847
+ const middleware = this.middlewareHandlers[index];
848
+ if (!middleware) {
849
+ return;
850
+ }
851
+ await Promise.resolve(
852
+ middleware(context, async () => {
853
+ await dispatch(index + 1);
854
+ })
855
+ );
856
+ };
857
+ await dispatch(0);
858
+ }
859
+ async applyMessageMiddleware(phase, client, event, data) {
860
+ const metadata = this.middlewareMetadataBySocket.get(client.socket) ?? /* @__PURE__ */ new Map();
861
+ this.middlewareMetadataBySocket.set(client.socket, metadata);
862
+ const middlewareContext = {
863
+ phase,
864
+ client,
865
+ event,
866
+ data,
867
+ metadata
868
+ };
869
+ await this.executeServerMiddleware(middlewareContext);
870
+ return middlewareContext.data;
871
+ }
872
+ resolveClientBySocket(socket) {
873
+ const clientId = this.clientIdBySocket.get(socket);
874
+ if (!clientId) {
875
+ return null;
876
+ }
877
+ return this.clientsById.get(clientId) ?? null;
878
+ }
679
879
  sendRaw(socket, payload) {
680
880
  try {
681
881
  if (socket.readyState !== WebSocket.OPEN) {
@@ -686,22 +886,24 @@ var SecureServer = class {
686
886
  this.notifyError(normalizeToError(error, "Failed to send server payload."));
687
887
  }
688
888
  }
689
- sendEncryptedEnvelope(socket, envelope) {
889
+ async sendEncryptedEnvelope(socket, envelope) {
890
+ if (socket.readyState !== WebSocket.OPEN) {
891
+ return;
892
+ }
893
+ const encryptionKey = this.encryptionKeyBySocket.get(socket);
894
+ if (!encryptionKey) {
895
+ const missingKeyError = new Error("Missing encryption key for connected socket.");
896
+ this.notifyError(missingKeyError);
897
+ throw missingKeyError;
898
+ }
690
899
  try {
691
- if (socket.readyState !== WebSocket.OPEN) {
692
- return;
693
- }
694
- const encryptionKey = this.encryptionKeyBySocket.get(socket);
695
- if (!encryptionKey) {
696
- throw new Error("Missing encryption key for connected socket.");
697
- }
698
- const encryptedPayload = encryptSerializedEnvelope(
699
- serializeEnvelope(envelope.event, envelope.data),
700
- encryptionKey
701
- );
900
+ const serializedEnvelope = await serializeEnvelope(envelope.event, envelope.data);
901
+ const encryptedPayload = encryptSerializedEnvelope(serializedEnvelope, encryptionKey);
702
902
  socket.send(encryptedPayload);
703
903
  } catch (error) {
704
- this.notifyError(normalizeToError(error, "Failed to send encrypted server payload."));
904
+ const normalizedError = normalizeToError(error, "Failed to send encrypted server payload.");
905
+ this.notifyError(normalizedError);
906
+ throw normalizedError;
705
907
  }
706
908
  }
707
909
  sendRpcRequest(socket, event, data, timeoutMs) {
@@ -722,13 +924,19 @@ var SecureServer = class {
722
924
  reject,
723
925
  timeoutHandle
724
926
  });
725
- this.sendOrQueuePayload(socket, {
927
+ void this.sendOrQueuePayload(socket, {
726
928
  event: INTERNAL_RPC_REQUEST_EVENT,
727
929
  data: {
728
930
  id: requestId,
729
931
  event,
730
932
  data
731
933
  }
934
+ }).catch((error) => {
935
+ clearTimeout(timeoutHandle);
936
+ pendingRequests.delete(requestId);
937
+ reject(
938
+ normalizeToError(error, `Failed to dispatch ACK request for event "${event}".`)
939
+ );
732
940
  });
733
941
  });
734
942
  }
@@ -765,12 +973,18 @@ var SecureServer = class {
765
973
  return;
766
974
  }
767
975
  try {
976
+ const interceptedData = await this.applyMessageMiddleware(
977
+ "incoming",
978
+ client,
979
+ rpcRequestPayload.event,
980
+ rpcRequestPayload.data
981
+ );
768
982
  const ackResponse = await this.executeRpcRequestHandler(
769
983
  rpcRequestPayload.event,
770
- rpcRequestPayload.data,
984
+ interceptedData,
771
985
  client
772
986
  );
773
- this.sendEncryptedEnvelope(client.socket, {
987
+ await this.sendEncryptedEnvelope(client.socket, {
774
988
  event: INTERNAL_RPC_RESPONSE_EVENT,
775
989
  data: {
776
990
  id: rpcRequestPayload.id,
@@ -780,7 +994,7 @@ var SecureServer = class {
780
994
  });
781
995
  } catch (error) {
782
996
  const normalizedError = normalizeToError(error, "Server ACK request handler failed.");
783
- this.sendEncryptedEnvelope(client.socket, {
997
+ await this.sendEncryptedEnvelope(client.socket, {
784
998
  event: INTERNAL_RPC_RESPONSE_EVENT,
785
999
  data: {
786
1000
  id: rpcRequestPayload.id,
@@ -854,7 +1068,7 @@ var SecureServer = class {
854
1068
  sendInternalHandshake(socket, localPublicKey) {
855
1069
  this.sendRaw(
856
1070
  socket,
857
- serializeEnvelope(INTERNAL_HANDSHAKE_EVENT, {
1071
+ serializePlainEnvelope(INTERNAL_HANDSHAKE_EVENT, {
858
1072
  publicKey: localPublicKey
859
1073
  })
860
1074
  );
@@ -884,33 +1098,50 @@ var SecureServer = class {
884
1098
  isClientHandshakeReady(socket) {
885
1099
  return this.handshakeStateBySocket.get(socket)?.isReady ?? false;
886
1100
  }
887
- sendOrQueuePayload(socket, envelope) {
1101
+ async sendOrQueuePayload(socket, envelope) {
1102
+ let interceptedEnvelope = envelope;
1103
+ if (!isReservedEmitEvent(envelope.event)) {
1104
+ const targetClient = this.resolveClientBySocket(socket);
1105
+ if (targetClient) {
1106
+ const interceptedData = await this.applyMessageMiddleware(
1107
+ "outgoing",
1108
+ targetClient,
1109
+ envelope.event,
1110
+ envelope.data
1111
+ );
1112
+ interceptedEnvelope = {
1113
+ event: envelope.event,
1114
+ data: interceptedData
1115
+ };
1116
+ }
1117
+ }
888
1118
  if (!this.isClientHandshakeReady(socket)) {
889
- this.queuePayload(socket, envelope);
1119
+ this.queuePayload(socket, interceptedEnvelope);
890
1120
  return;
891
1121
  }
892
- this.sendEncryptedEnvelope(socket, envelope);
1122
+ await this.sendEncryptedEnvelope(socket, interceptedEnvelope);
893
1123
  }
894
1124
  queuePayload(socket, envelope) {
895
1125
  const pendingPayloads = this.pendingPayloadsBySocket.get(socket) ?? [];
896
1126
  pendingPayloads.push(envelope);
897
1127
  this.pendingPayloadsBySocket.set(socket, pendingPayloads);
898
1128
  }
899
- flushQueuedPayloads(socket) {
1129
+ async flushQueuedPayloads(socket) {
900
1130
  const pendingPayloads = this.pendingPayloadsBySocket.get(socket);
901
1131
  if (!pendingPayloads || pendingPayloads.length === 0) {
902
1132
  return;
903
1133
  }
904
1134
  this.pendingPayloadsBySocket.delete(socket);
905
1135
  for (const envelope of pendingPayloads) {
906
- this.sendEncryptedEnvelope(socket, envelope);
1136
+ await this.sendEncryptedEnvelope(socket, envelope);
907
1137
  }
908
1138
  }
909
- createSecureServerClient(clientId, socket, request) {
1139
+ createSecureServerClient(clientId, socket, request, metadata) {
910
1140
  return {
911
1141
  id: clientId,
912
1142
  socket,
913
1143
  request,
1144
+ metadata,
914
1145
  emit: (event, data, callbackOrOptions, maybeCallback) => {
915
1146
  if (callbackOrOptions === void 0 && maybeCallback === void 0) {
916
1147
  return this.emitTo(clientId, event, data);
@@ -1013,7 +1244,9 @@ var SecureServer = class {
1013
1244
  if (!client) {
1014
1245
  continue;
1015
1246
  }
1016
- this.sendOrQueuePayload(client.socket, envelope);
1247
+ void this.sendOrQueuePayload(client.socket, envelope).catch(() => {
1248
+ return void 0;
1249
+ });
1017
1250
  }
1018
1251
  }
1019
1252
  };
@@ -1177,7 +1410,9 @@ var SecureClient = class {
1177
1410
  this.pendingPayloadQueue.push(envelope);
1178
1411
  return true;
1179
1412
  }
1180
- this.sendEncryptedEnvelope(envelope);
1413
+ void this.sendEncryptedEnvelope(envelope).catch(() => {
1414
+ return void 0;
1415
+ });
1181
1416
  return true;
1182
1417
  } catch (error) {
1183
1418
  const normalizedError = normalizeToError(error, "Failed to emit client event.");
@@ -1423,22 +1658,26 @@ var SecureClient = class {
1423
1658
  }
1424
1659
  }
1425
1660
  }
1426
- sendEncryptedEnvelope(envelope) {
1661
+ async sendEncryptedEnvelope(envelope) {
1662
+ if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
1663
+ const socketStateError = new Error("Client socket is not connected.");
1664
+ this.notifyError(socketStateError);
1665
+ throw socketStateError;
1666
+ }
1667
+ const encryptionKey = this.handshakeState?.encryptionKey;
1668
+ if (!encryptionKey) {
1669
+ const missingKeyError = new Error("Missing encryption key for client payload encryption.");
1670
+ this.notifyError(missingKeyError);
1671
+ throw missingKeyError;
1672
+ }
1427
1673
  try {
1428
- if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
1429
- throw new Error("Client socket is not connected.");
1430
- }
1431
- const encryptionKey = this.handshakeState?.encryptionKey;
1432
- if (!encryptionKey) {
1433
- throw new Error("Missing encryption key for client payload encryption.");
1434
- }
1435
- const encryptedPayload = encryptSerializedEnvelope(
1436
- serializeEnvelope(envelope.event, envelope.data),
1437
- encryptionKey
1438
- );
1674
+ const serializedEnvelope = await serializeEnvelope(envelope.event, envelope.data);
1675
+ const encryptedPayload = encryptSerializedEnvelope(serializedEnvelope, encryptionKey);
1439
1676
  this.socket.send(encryptedPayload);
1440
1677
  } catch (error) {
1441
- this.notifyError(normalizeToError(error, "Failed to send encrypted client payload."));
1678
+ const normalizedError = normalizeToError(error, "Failed to send encrypted client payload.");
1679
+ this.notifyError(normalizedError);
1680
+ throw normalizedError;
1442
1681
  }
1443
1682
  }
1444
1683
  sendRpcRequest(event, data, timeoutMs) {
@@ -1469,7 +1708,13 @@ var SecureClient = class {
1469
1708
  this.pendingPayloadQueue.push(rpcRequestEnvelope);
1470
1709
  return;
1471
1710
  }
1472
- this.sendEncryptedEnvelope(rpcRequestEnvelope);
1711
+ void this.sendEncryptedEnvelope(rpcRequestEnvelope).catch((error) => {
1712
+ clearTimeout(timeoutHandle);
1713
+ this.pendingRpcRequests.delete(requestId);
1714
+ reject(
1715
+ normalizeToError(error, `Failed to dispatch ACK request for event "${event}".`)
1716
+ );
1717
+ });
1473
1718
  });
1474
1719
  }
1475
1720
  handleRpcResponse(data) {
@@ -1505,7 +1750,7 @@ var SecureClient = class {
1505
1750
  rpcRequestPayload.event,
1506
1751
  rpcRequestPayload.data
1507
1752
  );
1508
- this.sendEncryptedEnvelope({
1753
+ await this.sendEncryptedEnvelope({
1509
1754
  event: INTERNAL_RPC_RESPONSE_EVENT,
1510
1755
  data: {
1511
1756
  id: rpcRequestPayload.id,
@@ -1515,7 +1760,7 @@ var SecureClient = class {
1515
1760
  });
1516
1761
  } catch (error) {
1517
1762
  const normalizedError = normalizeToError(error, "Client ACK request handler failed.");
1518
- this.sendEncryptedEnvelope({
1763
+ await this.sendEncryptedEnvelope({
1519
1764
  event: INTERNAL_RPC_RESPONSE_EVENT,
1520
1765
  data: {
1521
1766
  id: rpcRequestPayload.id,
@@ -1560,7 +1805,7 @@ var SecureClient = class {
1560
1805
  throw new Error("Missing client handshake state.");
1561
1806
  }
1562
1807
  this.socket.send(
1563
- serializeEnvelope(INTERNAL_HANDSHAKE_EVENT, {
1808
+ serializePlainEnvelope(INTERNAL_HANDSHAKE_EVENT, {
1564
1809
  publicKey: this.handshakeState.localPublicKey
1565
1810
  })
1566
1811
  );
@@ -1582,7 +1827,7 @@ var SecureClient = class {
1582
1827
  this.handshakeState.sharedSecret = sharedSecret;
1583
1828
  this.handshakeState.encryptionKey = deriveEncryptionKey(sharedSecret);
1584
1829
  this.handshakeState.isReady = true;
1585
- this.flushPendingPayloadQueue();
1830
+ void this.flushPendingPayloadQueue();
1586
1831
  this.notifyReady();
1587
1832
  } catch (error) {
1588
1833
  this.notifyError(normalizeToError(error, "Failed to complete client handshake."));
@@ -1591,14 +1836,14 @@ var SecureClient = class {
1591
1836
  isHandshakeReady() {
1592
1837
  return this.handshakeState?.isReady ?? false;
1593
1838
  }
1594
- flushPendingPayloadQueue() {
1839
+ async flushPendingPayloadQueue() {
1595
1840
  if (!this.socket || this.socket.readyState !== WebSocket.OPEN || !this.isHandshakeReady()) {
1596
1841
  return;
1597
1842
  }
1598
1843
  const pendingPayloads = this.pendingPayloadQueue;
1599
1844
  this.pendingPayloadQueue = [];
1600
1845
  for (const envelope of pendingPayloads) {
1601
- this.sendEncryptedEnvelope(envelope);
1846
+ await this.sendEncryptedEnvelope(envelope);
1602
1847
  }
1603
1848
  }
1604
1849
  };