@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.cjs CHANGED
@@ -10,6 +10,8 @@ var WebSocket__default = /*#__PURE__*/_interopDefault(WebSocket);
10
10
  // src/index.ts
11
11
  var DEFAULT_CLOSE_CODE = 1e3;
12
12
  var DEFAULT_CLOSE_REASON = "";
13
+ var POLICY_VIOLATION_CLOSE_CODE = 1008;
14
+ var POLICY_VIOLATION_CLOSE_REASON = "Connection rejected by middleware.";
13
15
  var INTERNAL_HANDSHAKE_EVENT = "__handshake";
14
16
  var INTERNAL_RPC_REQUEST_EVENT = "__rpc:req";
15
17
  var INTERNAL_RPC_RESPONSE_EVENT = "__rpc:res";
@@ -21,6 +23,8 @@ var GCM_AUTH_TAG_LENGTH = 16;
21
23
  var ENCRYPTION_KEY_LENGTH = 32;
22
24
  var ENCRYPTED_PACKET_VERSION = 1;
23
25
  var ENCRYPTED_PACKET_PREFIX_LENGTH = 1 + GCM_IV_LENGTH + GCM_AUTH_TAG_LENGTH;
26
+ var BINARY_PAYLOAD_MARKER = "__afxBinaryPayload";
27
+ var BINARY_PAYLOAD_VERSION = 1;
24
28
  var DEFAULT_HEARTBEAT_INTERVAL_MS = 15e3;
25
29
  var DEFAULT_HEARTBEAT_TIMEOUT_MS = 15e3;
26
30
  var DEFAULT_RECONNECT_INITIAL_DELAY_MS = 250;
@@ -61,7 +65,103 @@ function rawDataToBuffer(rawData) {
61
65
  }
62
66
  return Buffer.from(rawData);
63
67
  }
64
- function serializeEnvelope(event, data) {
68
+ function isBlobValue(value) {
69
+ return typeof Blob !== "undefined" && value instanceof Blob;
70
+ }
71
+ function isPlainObject(value) {
72
+ if (typeof value !== "object" || value === null) {
73
+ return false;
74
+ }
75
+ const prototype = Object.getPrototypeOf(value);
76
+ return prototype === Object.prototype || prototype === null;
77
+ }
78
+ function encodeBinaryPayload(kind, payloadBuffer, mimeType) {
79
+ const encodedPayload = {
80
+ [BINARY_PAYLOAD_MARKER]: BINARY_PAYLOAD_VERSION,
81
+ kind,
82
+ base64: payloadBuffer.toString("base64")
83
+ };
84
+ if (mimeType !== void 0 && mimeType.length > 0) {
85
+ encodedPayload.mimeType = mimeType;
86
+ }
87
+ return encodedPayload;
88
+ }
89
+ async function encodeEnvelopeData(value) {
90
+ if (Buffer.isBuffer(value)) {
91
+ return encodeBinaryPayload("buffer", value);
92
+ }
93
+ if (value instanceof Uint8Array) {
94
+ const typedArrayBuffer = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
95
+ return encodeBinaryPayload("uint8array", typedArrayBuffer);
96
+ }
97
+ if (isBlobValue(value)) {
98
+ const blobBuffer = Buffer.from(await value.arrayBuffer());
99
+ return encodeBinaryPayload("blob", blobBuffer, value.type);
100
+ }
101
+ if (Array.isArray(value)) {
102
+ return Promise.all(value.map((item) => encodeEnvelopeData(item)));
103
+ }
104
+ if (isPlainObject(value)) {
105
+ const encodedEntries = await Promise.all(
106
+ Object.entries(value).map(async ([key, entryValue]) => {
107
+ return [key, await encodeEnvelopeData(entryValue)];
108
+ })
109
+ );
110
+ return Object.fromEntries(encodedEntries);
111
+ }
112
+ return value;
113
+ }
114
+ function isEncodedBinaryPayload(value) {
115
+ if (!isPlainObject(value)) {
116
+ return false;
117
+ }
118
+ if (value[BINARY_PAYLOAD_MARKER] !== BINARY_PAYLOAD_VERSION) {
119
+ return false;
120
+ }
121
+ if (value.kind !== "buffer" && value.kind !== "uint8array" && value.kind !== "blob") {
122
+ return false;
123
+ }
124
+ if (typeof value.base64 !== "string") {
125
+ return false;
126
+ }
127
+ if (value.mimeType !== void 0 && typeof value.mimeType !== "string") {
128
+ return false;
129
+ }
130
+ return true;
131
+ }
132
+ function decodeEnvelopeData(value) {
133
+ if (Array.isArray(value)) {
134
+ return value.map((item) => decodeEnvelopeData(item));
135
+ }
136
+ if (isEncodedBinaryPayload(value)) {
137
+ const binaryBuffer = Buffer.from(value.base64, "base64");
138
+ if (value.kind === "buffer") {
139
+ return binaryBuffer;
140
+ }
141
+ if (value.kind === "uint8array") {
142
+ return Uint8Array.from(binaryBuffer);
143
+ }
144
+ if (typeof Blob === "undefined") {
145
+ return binaryBuffer;
146
+ }
147
+ return new Blob([binaryBuffer], {
148
+ type: value.mimeType ?? ""
149
+ });
150
+ }
151
+ if (isPlainObject(value)) {
152
+ const decodedEntries = Object.entries(value).map(([key, entryValue]) => {
153
+ return [key, decodeEnvelopeData(entryValue)];
154
+ });
155
+ return Object.fromEntries(decodedEntries);
156
+ }
157
+ return value;
158
+ }
159
+ async function serializeEnvelope(event, data) {
160
+ const encodedData = await encodeEnvelopeData(data);
161
+ const envelope = { event, data: encodedData };
162
+ return JSON.stringify(envelope);
163
+ }
164
+ function serializePlainEnvelope(event, data) {
65
165
  const envelope = { event, data };
66
166
  return JSON.stringify(envelope);
67
167
  }
@@ -73,7 +173,7 @@ function parseEnvelope(rawData) {
73
173
  }
74
174
  return {
75
175
  event: parsed.event,
76
- data: parsed.data
176
+ data: decodeEnvelopeData(parsed.data)
77
177
  };
78
178
  }
79
179
  function parseEnvelopeFromText(decodedPayload) {
@@ -83,7 +183,7 @@ function parseEnvelopeFromText(decodedPayload) {
83
183
  }
84
184
  return {
85
185
  event: parsed.event,
86
- data: parsed.data
186
+ data: decodeEnvelopeData(parsed.data)
87
187
  };
88
188
  }
89
189
  function decodeCloseReason(reason) {
@@ -265,7 +365,9 @@ var SecureServer = class {
265
365
  disconnectHandlers = /* @__PURE__ */ new Set();
266
366
  readyHandlers = /* @__PURE__ */ new Set();
267
367
  errorHandlers = /* @__PURE__ */ new Set();
368
+ middlewareHandlers = [];
268
369
  handshakeStateBySocket = /* @__PURE__ */ new WeakMap();
370
+ middlewareMetadataBySocket = /* @__PURE__ */ new WeakMap();
269
371
  sharedSecretBySocket = /* @__PURE__ */ new WeakMap();
270
372
  encryptionKeyBySocket = /* @__PURE__ */ new WeakMap();
271
373
  pendingPayloadsBySocket = /* @__PURE__ */ new WeakMap();
@@ -354,6 +456,19 @@ var SecureServer = class {
354
456
  }
355
457
  return this;
356
458
  }
459
+ use(middleware) {
460
+ try {
461
+ if (typeof middleware !== "function") {
462
+ throw new Error("Server middleware must be a function.");
463
+ }
464
+ this.middlewareHandlers.push(middleware);
465
+ } catch (error) {
466
+ this.notifyError(
467
+ normalizeToError(error, "Failed to register server middleware.")
468
+ );
469
+ }
470
+ return this;
471
+ }
357
472
  emit(event, data) {
358
473
  try {
359
474
  if (isReservedEmitEvent(event)) {
@@ -361,7 +476,9 @@ var SecureServer = class {
361
476
  }
362
477
  const envelope = { event, data };
363
478
  for (const client of this.clientsById.values()) {
364
- this.sendOrQueuePayload(client.socket, envelope);
479
+ void this.sendOrQueuePayload(client.socket, envelope).catch(() => {
480
+ return void 0;
481
+ });
365
482
  }
366
483
  } catch (error) {
367
484
  this.notifyError(normalizeToError(error, "Failed to emit server event."));
@@ -379,7 +496,9 @@ var SecureServer = class {
379
496
  throw new Error(`Client with id ${clientId} was not found.`);
380
497
  }
381
498
  if (!ackArgs.expectsAck) {
382
- this.sendOrQueuePayload(client.socket, { event, data });
499
+ void this.sendOrQueuePayload(client.socket, { event, data }).catch(() => {
500
+ return void 0;
501
+ });
383
502
  return true;
384
503
  }
385
504
  const ackPromise = this.sendRpcRequest(
@@ -435,6 +554,7 @@ var SecureServer = class {
435
554
  client.socket,
436
555
  new Error("Server closed before ACK response was received.")
437
556
  );
557
+ this.middlewareMetadataBySocket.delete(client.socket);
438
558
  if (client.socket.readyState === WebSocket__default.default.OPEN || client.socket.readyState === WebSocket__default.default.CONNECTING) {
439
559
  client.socket.close(code, reason);
440
560
  }
@@ -497,6 +617,7 @@ var SecureServer = class {
497
617
  this.pendingRpcRequestsBySocket.delete(socket);
498
618
  this.handshakeStateBySocket.delete(socket);
499
619
  this.heartbeatStateBySocket.delete(socket);
620
+ this.middlewareMetadataBySocket.delete(socket);
500
621
  socket.terminate();
501
622
  continue;
502
623
  }
@@ -526,17 +647,46 @@ var SecureServer = class {
526
647
  }
527
648
  bindSocketServerEvents() {
528
649
  this.socketServer.on("connection", (socket, request) => {
529
- this.handleConnection(socket, request);
650
+ void this.handleConnection(socket, request);
530
651
  });
531
652
  this.socketServer.on("error", (error) => {
532
653
  this.notifyError(normalizeToError(error, "WebSocket server encountered an error."));
533
654
  });
534
655
  }
535
- handleConnection(socket, request) {
656
+ async handleConnection(socket, request) {
657
+ const connectionMetadata = /* @__PURE__ */ new Map();
658
+ this.middlewareMetadataBySocket.set(socket, connectionMetadata);
659
+ try {
660
+ await this.executeServerMiddleware({
661
+ phase: "connection",
662
+ socket,
663
+ request,
664
+ metadata: connectionMetadata
665
+ });
666
+ } catch (error) {
667
+ const normalizedError = normalizeToError(
668
+ error,
669
+ "Connection middleware rejected the incoming socket."
670
+ );
671
+ this.notifyError(normalizedError);
672
+ this.middlewareMetadataBySocket.delete(socket);
673
+ if (socket.readyState === WebSocket__default.default.OPEN || socket.readyState === WebSocket__default.default.CONNECTING) {
674
+ socket.close(
675
+ POLICY_VIOLATION_CLOSE_CODE,
676
+ normalizedError.message || POLICY_VIOLATION_CLOSE_REASON
677
+ );
678
+ }
679
+ return;
680
+ }
536
681
  try {
537
682
  const clientId = crypto.randomUUID();
538
683
  const handshakeState = this.createServerHandshakeState();
539
- const client = this.createSecureServerClient(clientId, socket, request);
684
+ const client = this.createSecureServerClient(
685
+ clientId,
686
+ socket,
687
+ request,
688
+ connectionMetadata
689
+ );
540
690
  this.clientsById.set(clientId, client);
541
691
  this.clientIdBySocket.set(socket, clientId);
542
692
  this.handshakeStateBySocket.set(socket, handshakeState);
@@ -548,7 +698,7 @@ var SecureServer = class {
548
698
  });
549
699
  this.roomNamesByClientId.set(clientId, /* @__PURE__ */ new Set());
550
700
  socket.on("message", (rawData) => {
551
- this.handleIncomingMessage(client, rawData);
701
+ void this.handleIncomingMessage(client, rawData);
552
702
  });
553
703
  socket.on("close", (code, reason) => {
554
704
  this.handleDisconnection(client, code, reason);
@@ -568,9 +718,10 @@ var SecureServer = class {
568
718
  this.notifyConnection(client);
569
719
  } catch (error) {
570
720
  this.notifyError(normalizeToError(error, "Failed to handle client connection."));
721
+ this.middlewareMetadataBySocket.delete(socket);
571
722
  }
572
723
  }
573
- handleIncomingMessage(client, rawData) {
724
+ async handleIncomingMessage(client, rawData) {
574
725
  try {
575
726
  let envelope = null;
576
727
  try {
@@ -614,10 +765,16 @@ var SecureServer = class {
614
765
  return;
615
766
  }
616
767
  if (decryptedEnvelope.event === INTERNAL_RPC_REQUEST_EVENT) {
617
- void this.handleRpcRequest(client, decryptedEnvelope.data);
768
+ await this.handleRpcRequest(client, decryptedEnvelope.data);
618
769
  return;
619
770
  }
620
- this.dispatchCustomEvent(decryptedEnvelope.event, decryptedEnvelope.data, client);
771
+ const interceptedData = await this.applyMessageMiddleware(
772
+ "incoming",
773
+ client,
774
+ decryptedEnvelope.event,
775
+ decryptedEnvelope.data
776
+ );
777
+ this.dispatchCustomEvent(decryptedEnvelope.event, interceptedData, client);
621
778
  } catch (error) {
622
779
  this.notifyError(normalizeToError(error, "Failed to process incoming server message."));
623
780
  }
@@ -637,6 +794,7 @@ var SecureServer = class {
637
794
  );
638
795
  this.pendingRpcRequestsBySocket.delete(client.socket);
639
796
  this.heartbeatStateBySocket.delete(client.socket);
797
+ this.middlewareMetadataBySocket.delete(client.socket);
640
798
  const decodedReason = decodeCloseReason(reason);
641
799
  for (const handler of this.disconnectHandlers) {
642
800
  try {
@@ -682,6 +840,48 @@ var SecureServer = class {
682
840
  }
683
841
  }
684
842
  }
843
+ async executeServerMiddleware(context) {
844
+ if (this.middlewareHandlers.length === 0) {
845
+ return;
846
+ }
847
+ let currentIndex = -1;
848
+ const dispatch = async (index) => {
849
+ if (index <= currentIndex) {
850
+ throw new Error("Server middleware next() was called multiple times.");
851
+ }
852
+ currentIndex = index;
853
+ const middleware = this.middlewareHandlers[index];
854
+ if (!middleware) {
855
+ return;
856
+ }
857
+ await Promise.resolve(
858
+ middleware(context, async () => {
859
+ await dispatch(index + 1);
860
+ })
861
+ );
862
+ };
863
+ await dispatch(0);
864
+ }
865
+ async applyMessageMiddleware(phase, client, event, data) {
866
+ const metadata = this.middlewareMetadataBySocket.get(client.socket) ?? /* @__PURE__ */ new Map();
867
+ this.middlewareMetadataBySocket.set(client.socket, metadata);
868
+ const middlewareContext = {
869
+ phase,
870
+ client,
871
+ event,
872
+ data,
873
+ metadata
874
+ };
875
+ await this.executeServerMiddleware(middlewareContext);
876
+ return middlewareContext.data;
877
+ }
878
+ resolveClientBySocket(socket) {
879
+ const clientId = this.clientIdBySocket.get(socket);
880
+ if (!clientId) {
881
+ return null;
882
+ }
883
+ return this.clientsById.get(clientId) ?? null;
884
+ }
685
885
  sendRaw(socket, payload) {
686
886
  try {
687
887
  if (socket.readyState !== WebSocket__default.default.OPEN) {
@@ -692,22 +892,24 @@ var SecureServer = class {
692
892
  this.notifyError(normalizeToError(error, "Failed to send server payload."));
693
893
  }
694
894
  }
695
- sendEncryptedEnvelope(socket, envelope) {
895
+ async sendEncryptedEnvelope(socket, envelope) {
896
+ if (socket.readyState !== WebSocket__default.default.OPEN) {
897
+ return;
898
+ }
899
+ const encryptionKey = this.encryptionKeyBySocket.get(socket);
900
+ if (!encryptionKey) {
901
+ const missingKeyError = new Error("Missing encryption key for connected socket.");
902
+ this.notifyError(missingKeyError);
903
+ throw missingKeyError;
904
+ }
696
905
  try {
697
- if (socket.readyState !== WebSocket__default.default.OPEN) {
698
- return;
699
- }
700
- const encryptionKey = this.encryptionKeyBySocket.get(socket);
701
- if (!encryptionKey) {
702
- throw new Error("Missing encryption key for connected socket.");
703
- }
704
- const encryptedPayload = encryptSerializedEnvelope(
705
- serializeEnvelope(envelope.event, envelope.data),
706
- encryptionKey
707
- );
906
+ const serializedEnvelope = await serializeEnvelope(envelope.event, envelope.data);
907
+ const encryptedPayload = encryptSerializedEnvelope(serializedEnvelope, encryptionKey);
708
908
  socket.send(encryptedPayload);
709
909
  } catch (error) {
710
- this.notifyError(normalizeToError(error, "Failed to send encrypted server payload."));
910
+ const normalizedError = normalizeToError(error, "Failed to send encrypted server payload.");
911
+ this.notifyError(normalizedError);
912
+ throw normalizedError;
711
913
  }
712
914
  }
713
915
  sendRpcRequest(socket, event, data, timeoutMs) {
@@ -728,13 +930,19 @@ var SecureServer = class {
728
930
  reject,
729
931
  timeoutHandle
730
932
  });
731
- this.sendOrQueuePayload(socket, {
933
+ void this.sendOrQueuePayload(socket, {
732
934
  event: INTERNAL_RPC_REQUEST_EVENT,
733
935
  data: {
734
936
  id: requestId,
735
937
  event,
736
938
  data
737
939
  }
940
+ }).catch((error) => {
941
+ clearTimeout(timeoutHandle);
942
+ pendingRequests.delete(requestId);
943
+ reject(
944
+ normalizeToError(error, `Failed to dispatch ACK request for event "${event}".`)
945
+ );
738
946
  });
739
947
  });
740
948
  }
@@ -771,12 +979,18 @@ var SecureServer = class {
771
979
  return;
772
980
  }
773
981
  try {
982
+ const interceptedData = await this.applyMessageMiddleware(
983
+ "incoming",
984
+ client,
985
+ rpcRequestPayload.event,
986
+ rpcRequestPayload.data
987
+ );
774
988
  const ackResponse = await this.executeRpcRequestHandler(
775
989
  rpcRequestPayload.event,
776
- rpcRequestPayload.data,
990
+ interceptedData,
777
991
  client
778
992
  );
779
- this.sendEncryptedEnvelope(client.socket, {
993
+ await this.sendEncryptedEnvelope(client.socket, {
780
994
  event: INTERNAL_RPC_RESPONSE_EVENT,
781
995
  data: {
782
996
  id: rpcRequestPayload.id,
@@ -786,7 +1000,7 @@ var SecureServer = class {
786
1000
  });
787
1001
  } catch (error) {
788
1002
  const normalizedError = normalizeToError(error, "Server ACK request handler failed.");
789
- this.sendEncryptedEnvelope(client.socket, {
1003
+ await this.sendEncryptedEnvelope(client.socket, {
790
1004
  event: INTERNAL_RPC_RESPONSE_EVENT,
791
1005
  data: {
792
1006
  id: rpcRequestPayload.id,
@@ -860,7 +1074,7 @@ var SecureServer = class {
860
1074
  sendInternalHandshake(socket, localPublicKey) {
861
1075
  this.sendRaw(
862
1076
  socket,
863
- serializeEnvelope(INTERNAL_HANDSHAKE_EVENT, {
1077
+ serializePlainEnvelope(INTERNAL_HANDSHAKE_EVENT, {
864
1078
  publicKey: localPublicKey
865
1079
  })
866
1080
  );
@@ -890,33 +1104,50 @@ var SecureServer = class {
890
1104
  isClientHandshakeReady(socket) {
891
1105
  return this.handshakeStateBySocket.get(socket)?.isReady ?? false;
892
1106
  }
893
- sendOrQueuePayload(socket, envelope) {
1107
+ async sendOrQueuePayload(socket, envelope) {
1108
+ let interceptedEnvelope = envelope;
1109
+ if (!isReservedEmitEvent(envelope.event)) {
1110
+ const targetClient = this.resolveClientBySocket(socket);
1111
+ if (targetClient) {
1112
+ const interceptedData = await this.applyMessageMiddleware(
1113
+ "outgoing",
1114
+ targetClient,
1115
+ envelope.event,
1116
+ envelope.data
1117
+ );
1118
+ interceptedEnvelope = {
1119
+ event: envelope.event,
1120
+ data: interceptedData
1121
+ };
1122
+ }
1123
+ }
894
1124
  if (!this.isClientHandshakeReady(socket)) {
895
- this.queuePayload(socket, envelope);
1125
+ this.queuePayload(socket, interceptedEnvelope);
896
1126
  return;
897
1127
  }
898
- this.sendEncryptedEnvelope(socket, envelope);
1128
+ await this.sendEncryptedEnvelope(socket, interceptedEnvelope);
899
1129
  }
900
1130
  queuePayload(socket, envelope) {
901
1131
  const pendingPayloads = this.pendingPayloadsBySocket.get(socket) ?? [];
902
1132
  pendingPayloads.push(envelope);
903
1133
  this.pendingPayloadsBySocket.set(socket, pendingPayloads);
904
1134
  }
905
- flushQueuedPayloads(socket) {
1135
+ async flushQueuedPayloads(socket) {
906
1136
  const pendingPayloads = this.pendingPayloadsBySocket.get(socket);
907
1137
  if (!pendingPayloads || pendingPayloads.length === 0) {
908
1138
  return;
909
1139
  }
910
1140
  this.pendingPayloadsBySocket.delete(socket);
911
1141
  for (const envelope of pendingPayloads) {
912
- this.sendEncryptedEnvelope(socket, envelope);
1142
+ await this.sendEncryptedEnvelope(socket, envelope);
913
1143
  }
914
1144
  }
915
- createSecureServerClient(clientId, socket, request) {
1145
+ createSecureServerClient(clientId, socket, request, metadata) {
916
1146
  return {
917
1147
  id: clientId,
918
1148
  socket,
919
1149
  request,
1150
+ metadata,
920
1151
  emit: (event, data, callbackOrOptions, maybeCallback) => {
921
1152
  if (callbackOrOptions === void 0 && maybeCallback === void 0) {
922
1153
  return this.emitTo(clientId, event, data);
@@ -1019,7 +1250,9 @@ var SecureServer = class {
1019
1250
  if (!client) {
1020
1251
  continue;
1021
1252
  }
1022
- this.sendOrQueuePayload(client.socket, envelope);
1253
+ void this.sendOrQueuePayload(client.socket, envelope).catch(() => {
1254
+ return void 0;
1255
+ });
1023
1256
  }
1024
1257
  }
1025
1258
  };
@@ -1183,7 +1416,9 @@ var SecureClient = class {
1183
1416
  this.pendingPayloadQueue.push(envelope);
1184
1417
  return true;
1185
1418
  }
1186
- this.sendEncryptedEnvelope(envelope);
1419
+ void this.sendEncryptedEnvelope(envelope).catch(() => {
1420
+ return void 0;
1421
+ });
1187
1422
  return true;
1188
1423
  } catch (error) {
1189
1424
  const normalizedError = normalizeToError(error, "Failed to emit client event.");
@@ -1429,22 +1664,26 @@ var SecureClient = class {
1429
1664
  }
1430
1665
  }
1431
1666
  }
1432
- sendEncryptedEnvelope(envelope) {
1667
+ async sendEncryptedEnvelope(envelope) {
1668
+ if (!this.socket || this.socket.readyState !== WebSocket__default.default.OPEN) {
1669
+ const socketStateError = new Error("Client socket is not connected.");
1670
+ this.notifyError(socketStateError);
1671
+ throw socketStateError;
1672
+ }
1673
+ const encryptionKey = this.handshakeState?.encryptionKey;
1674
+ if (!encryptionKey) {
1675
+ const missingKeyError = new Error("Missing encryption key for client payload encryption.");
1676
+ this.notifyError(missingKeyError);
1677
+ throw missingKeyError;
1678
+ }
1433
1679
  try {
1434
- if (!this.socket || this.socket.readyState !== WebSocket__default.default.OPEN) {
1435
- throw new Error("Client socket is not connected.");
1436
- }
1437
- const encryptionKey = this.handshakeState?.encryptionKey;
1438
- if (!encryptionKey) {
1439
- throw new Error("Missing encryption key for client payload encryption.");
1440
- }
1441
- const encryptedPayload = encryptSerializedEnvelope(
1442
- serializeEnvelope(envelope.event, envelope.data),
1443
- encryptionKey
1444
- );
1680
+ const serializedEnvelope = await serializeEnvelope(envelope.event, envelope.data);
1681
+ const encryptedPayload = encryptSerializedEnvelope(serializedEnvelope, encryptionKey);
1445
1682
  this.socket.send(encryptedPayload);
1446
1683
  } catch (error) {
1447
- this.notifyError(normalizeToError(error, "Failed to send encrypted client payload."));
1684
+ const normalizedError = normalizeToError(error, "Failed to send encrypted client payload.");
1685
+ this.notifyError(normalizedError);
1686
+ throw normalizedError;
1448
1687
  }
1449
1688
  }
1450
1689
  sendRpcRequest(event, data, timeoutMs) {
@@ -1475,7 +1714,13 @@ var SecureClient = class {
1475
1714
  this.pendingPayloadQueue.push(rpcRequestEnvelope);
1476
1715
  return;
1477
1716
  }
1478
- this.sendEncryptedEnvelope(rpcRequestEnvelope);
1717
+ void this.sendEncryptedEnvelope(rpcRequestEnvelope).catch((error) => {
1718
+ clearTimeout(timeoutHandle);
1719
+ this.pendingRpcRequests.delete(requestId);
1720
+ reject(
1721
+ normalizeToError(error, `Failed to dispatch ACK request for event "${event}".`)
1722
+ );
1723
+ });
1479
1724
  });
1480
1725
  }
1481
1726
  handleRpcResponse(data) {
@@ -1511,7 +1756,7 @@ var SecureClient = class {
1511
1756
  rpcRequestPayload.event,
1512
1757
  rpcRequestPayload.data
1513
1758
  );
1514
- this.sendEncryptedEnvelope({
1759
+ await this.sendEncryptedEnvelope({
1515
1760
  event: INTERNAL_RPC_RESPONSE_EVENT,
1516
1761
  data: {
1517
1762
  id: rpcRequestPayload.id,
@@ -1521,7 +1766,7 @@ var SecureClient = class {
1521
1766
  });
1522
1767
  } catch (error) {
1523
1768
  const normalizedError = normalizeToError(error, "Client ACK request handler failed.");
1524
- this.sendEncryptedEnvelope({
1769
+ await this.sendEncryptedEnvelope({
1525
1770
  event: INTERNAL_RPC_RESPONSE_EVENT,
1526
1771
  data: {
1527
1772
  id: rpcRequestPayload.id,
@@ -1566,7 +1811,7 @@ var SecureClient = class {
1566
1811
  throw new Error("Missing client handshake state.");
1567
1812
  }
1568
1813
  this.socket.send(
1569
- serializeEnvelope(INTERNAL_HANDSHAKE_EVENT, {
1814
+ serializePlainEnvelope(INTERNAL_HANDSHAKE_EVENT, {
1570
1815
  publicKey: this.handshakeState.localPublicKey
1571
1816
  })
1572
1817
  );
@@ -1588,7 +1833,7 @@ var SecureClient = class {
1588
1833
  this.handshakeState.sharedSecret = sharedSecret;
1589
1834
  this.handshakeState.encryptionKey = deriveEncryptionKey(sharedSecret);
1590
1835
  this.handshakeState.isReady = true;
1591
- this.flushPendingPayloadQueue();
1836
+ void this.flushPendingPayloadQueue();
1592
1837
  this.notifyReady();
1593
1838
  } catch (error) {
1594
1839
  this.notifyError(normalizeToError(error, "Failed to complete client handshake."));
@@ -1597,14 +1842,14 @@ var SecureClient = class {
1597
1842
  isHandshakeReady() {
1598
1843
  return this.handshakeState?.isReady ?? false;
1599
1844
  }
1600
- flushPendingPayloadQueue() {
1845
+ async flushPendingPayloadQueue() {
1601
1846
  if (!this.socket || this.socket.readyState !== WebSocket__default.default.OPEN || !this.isHandshakeReady()) {
1602
1847
  return;
1603
1848
  }
1604
1849
  const pendingPayloads = this.pendingPayloadQueue;
1605
1850
  this.pendingPayloadQueue = [];
1606
1851
  for (const envelope of pendingPayloads) {
1607
- this.sendEncryptedEnvelope(envelope);
1852
+ await this.sendEncryptedEnvelope(envelope);
1608
1853
  }
1609
1854
  }
1610
1855
  };