@zimic/interceptor 1.2.3-canary.7 → 1.2.4-canary.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/{chunk-ZU6IGW27.js → chunk-IPL73BDI.js} +99 -73
- package/dist/chunk-IPL73BDI.js.map +1 -0
- package/dist/{chunk-XCYZ5L2M.mjs → chunk-OTZ5Z633.mjs} +99 -73
- package/dist/chunk-OTZ5Z633.mjs.map +1 -0
- package/dist/cli.js +18 -18
- package/dist/cli.js.map +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/http.js +101 -99
- package/dist/http.js.map +1 -1
- package/dist/http.mjs +101 -99
- package/dist/http.mjs.map +1 -1
- package/dist/server.js +6 -6
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/src/http/interceptor/HttpInterceptorClient.ts +1 -1
- package/src/http/interceptor/HttpInterceptorStore.ts +6 -3
- package/src/http/interceptor/RemoteHttpInterceptor.ts +1 -1
- package/src/http/interceptorWorker/HttpInterceptorWorker.ts +3 -5
- package/src/http/interceptorWorker/LocalHttpInterceptorWorker.ts +16 -12
- package/src/http/interceptorWorker/RemoteHttpInterceptorWorker.ts +20 -43
- package/src/server/InterceptorServer.ts +39 -21
- package/src/server/types/schema.ts +1 -1
- package/src/webSocket/WebSocketClient.ts +4 -4
- package/src/webSocket/WebSocketHandler.ts +115 -65
- package/src/webSocket/WebSocketServer.ts +2 -3
- package/src/webSocket/types.ts +9 -14
- package/dist/chunk-XCYZ5L2M.mjs.map +0 -1
- package/dist/chunk-ZU6IGW27.js.map +0 -1
|
@@ -897,7 +897,7 @@ var WebSocketHandler = class {
|
|
|
897
897
|
messageTimeout;
|
|
898
898
|
channelListeners = {};
|
|
899
899
|
socketListeners = {
|
|
900
|
-
|
|
900
|
+
abortRequests: /* @__PURE__ */ new Map()
|
|
901
901
|
};
|
|
902
902
|
constructor(options) {
|
|
903
903
|
this.socketTimeout = options.socketTimeout ?? DEFAULT_WEB_SOCKET_LIFECYCLE_TIMEOUT;
|
|
@@ -918,10 +918,12 @@ var WebSocketHandler = class {
|
|
|
918
918
|
}
|
|
919
919
|
socket.addEventListener("error", handleSocketError);
|
|
920
920
|
const handleSocketClose = () => {
|
|
921
|
+
this.sockets.delete(socket);
|
|
922
|
+
this.emitSocket("abortRequests", socket);
|
|
923
|
+
this.socketListeners.abortRequests.delete(socket);
|
|
921
924
|
socket.removeEventListener("message", handleSocketMessage);
|
|
922
925
|
socket.removeEventListener("close", handleSocketClose);
|
|
923
926
|
socket.removeEventListener("error", handleSocketError);
|
|
924
|
-
this.removeSocket(socket);
|
|
925
927
|
};
|
|
926
928
|
socket.addEventListener("close", handleSocketClose);
|
|
927
929
|
this.sockets.add(socket);
|
|
@@ -975,6 +977,9 @@ var WebSocketHandler = class {
|
|
|
975
977
|
isMessage(message) {
|
|
976
978
|
return typeof message === "object" && message !== null && "id" in message && typeof message.id === "string" && "channel" in message && typeof message.channel === "string" && (!("requestId" in message) || typeof message.requestId === "string");
|
|
977
979
|
}
|
|
980
|
+
isChannelEvent(event, channel) {
|
|
981
|
+
return event.channel === channel;
|
|
982
|
+
}
|
|
978
983
|
async notifyListeners(message, socket) {
|
|
979
984
|
if (this.isReplyMessage(message)) {
|
|
980
985
|
await this.notifyReplyListeners(message, socket);
|
|
@@ -1003,10 +1008,6 @@ var WebSocketHandler = class {
|
|
|
1003
1008
|
});
|
|
1004
1009
|
await Promise.all(closingPromises);
|
|
1005
1010
|
}
|
|
1006
|
-
removeSocket(socket) {
|
|
1007
|
-
this.abortSocketMessages([socket]);
|
|
1008
|
-
this.sockets.delete(socket);
|
|
1009
|
-
}
|
|
1010
1011
|
async createEventMessage(channel, eventData) {
|
|
1011
1012
|
const crypto2 = await importCrypto();
|
|
1012
1013
|
const eventMessage = {
|
|
@@ -1023,31 +1024,46 @@ var WebSocketHandler = class {
|
|
|
1023
1024
|
async request(channel, requestData, options = {}) {
|
|
1024
1025
|
const request = await this.createEventMessage(channel, requestData);
|
|
1025
1026
|
this.sendMessage(request, options.sockets);
|
|
1026
|
-
const response = await this.waitForReply(channel, request
|
|
1027
|
+
const response = await this.waitForReply(channel, request, options.sockets);
|
|
1027
1028
|
return response.data;
|
|
1028
1029
|
}
|
|
1029
|
-
async waitForReply(channel,
|
|
1030
|
+
async waitForReply(channel, request, sockets = this.sockets) {
|
|
1030
1031
|
return new Promise((resolve, reject) => {
|
|
1031
1032
|
const replyTimeout = setTimeout(() => {
|
|
1032
|
-
this.
|
|
1033
|
-
|
|
1033
|
+
this.offChannel("reply", channel, replyListener);
|
|
1034
|
+
for (const socket of sockets) {
|
|
1035
|
+
this.offSocket("abortRequests", socket, abortRequestsHandler);
|
|
1036
|
+
}
|
|
1034
1037
|
const timeoutError = new WebSocketMessageTimeoutError(this.messageTimeout);
|
|
1035
1038
|
reject(timeoutError);
|
|
1036
1039
|
}, this.messageTimeout);
|
|
1037
|
-
const
|
|
1040
|
+
const replyListener = this.onChannel("reply", channel, (message) => {
|
|
1041
|
+
if (message.requestId !== request.id) {
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1038
1044
|
clearTimeout(replyTimeout);
|
|
1039
|
-
this.
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
});
|
|
1043
|
-
const replyListener = this.onReply(channel, (message) => {
|
|
1044
|
-
if (message.requestId === requestId) {
|
|
1045
|
-
clearTimeout(replyTimeout);
|
|
1046
|
-
this.offReply(channel, replyListener);
|
|
1047
|
-
this.offAbortSocketMessages(sockets, abortListener);
|
|
1048
|
-
resolve(message);
|
|
1045
|
+
this.offChannel("reply", channel, replyListener);
|
|
1046
|
+
for (const socket of sockets) {
|
|
1047
|
+
this.offSocket("abortRequests", socket, abortRequestsHandler);
|
|
1049
1048
|
}
|
|
1049
|
+
resolve(message);
|
|
1050
1050
|
});
|
|
1051
|
+
const abortRequestsHandler = (options) => {
|
|
1052
|
+
const shouldAbortRequest = options.shouldAbortRequest === void 0 || options.shouldAbortRequest(request);
|
|
1053
|
+
if (!shouldAbortRequest) {
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
clearTimeout(replyTimeout);
|
|
1057
|
+
this.offChannel("reply", channel, replyListener);
|
|
1058
|
+
for (const socket of sockets) {
|
|
1059
|
+
this.offSocket("abortRequests", socket, abortRequestsHandler);
|
|
1060
|
+
}
|
|
1061
|
+
const abortError = new WebSocketMessageAbortError();
|
|
1062
|
+
reject(abortError);
|
|
1063
|
+
};
|
|
1064
|
+
for (const socket of sockets) {
|
|
1065
|
+
this.onSocket("abortRequests", socket, abortRequestsHandler);
|
|
1066
|
+
}
|
|
1051
1067
|
});
|
|
1052
1068
|
}
|
|
1053
1069
|
isReplyMessage(message) {
|
|
@@ -1078,9 +1094,9 @@ var WebSocketHandler = class {
|
|
|
1078
1094
|
socket.send(stringifiedMessage);
|
|
1079
1095
|
}
|
|
1080
1096
|
}
|
|
1081
|
-
|
|
1097
|
+
onChannel(type, channel, listener) {
|
|
1082
1098
|
const listeners = this.getOrCreateChannelListeners(channel);
|
|
1083
|
-
listeners.
|
|
1099
|
+
listeners[type].add(listener);
|
|
1084
1100
|
return listener;
|
|
1085
1101
|
}
|
|
1086
1102
|
getOrCreateChannelListeners(channel) {
|
|
@@ -1093,42 +1109,36 @@ var WebSocketHandler = class {
|
|
|
1093
1109
|
}
|
|
1094
1110
|
return listeners;
|
|
1095
1111
|
}
|
|
1096
|
-
|
|
1097
|
-
const listeners = this.
|
|
1098
|
-
listeners.
|
|
1099
|
-
return listener;
|
|
1100
|
-
}
|
|
1101
|
-
offEvent(channel, listener) {
|
|
1102
|
-
this.channelListeners[channel]?.event.delete(listener);
|
|
1112
|
+
offChannel(type, channel, listener) {
|
|
1113
|
+
const listeners = this.channelListeners[channel];
|
|
1114
|
+
listeners?.[type].delete(listener);
|
|
1103
1115
|
}
|
|
1104
|
-
|
|
1105
|
-
this.
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
this.channelListeners = {};
|
|
1116
|
+
onSocket(type, socket, listener) {
|
|
1117
|
+
const listeners = this.getOrCreateSocketListeners(type, socket);
|
|
1118
|
+
listeners.add(listener);
|
|
1119
|
+
return listener;
|
|
1109
1120
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
listeners = /* @__PURE__ */ new Set();
|
|
1115
|
-
this.socketListeners.messageAbort.set(socket, listeners);
|
|
1116
|
-
}
|
|
1117
|
-
listeners.add(listener);
|
|
1121
|
+
getOrCreateSocketListeners(type, socket) {
|
|
1122
|
+
const listeners = this.socketListeners[type].get(socket) ?? /* @__PURE__ */ new Set();
|
|
1123
|
+
if (!this.socketListeners[type].has(socket)) {
|
|
1124
|
+
this.socketListeners[type].set(socket, listeners);
|
|
1118
1125
|
}
|
|
1119
|
-
return
|
|
1126
|
+
return listeners;
|
|
1120
1127
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1128
|
+
offSocket(type, socket, listener) {
|
|
1129
|
+
const listeners = this.socketListeners[type].get(socket);
|
|
1130
|
+
listeners?.delete(listener);
|
|
1131
|
+
}
|
|
1132
|
+
emitSocket(type, socket, options = {}) {
|
|
1133
|
+
for (const listener of this.socketListeners[type].get(socket) ?? []) {
|
|
1134
|
+
listener(options);
|
|
1124
1135
|
}
|
|
1125
1136
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
for (const
|
|
1129
|
-
const listeners
|
|
1130
|
-
|
|
1131
|
-
listener(abortError);
|
|
1137
|
+
offAny() {
|
|
1138
|
+
this.channelListeners = {};
|
|
1139
|
+
for (const listenersBySocket of Object.values(this.socketListeners)) {
|
|
1140
|
+
for (const listeners of listenersBySocket.values()) {
|
|
1141
|
+
listeners.clear();
|
|
1132
1142
|
}
|
|
1133
1143
|
}
|
|
1134
1144
|
}
|
|
@@ -1181,11 +1191,9 @@ var WebSocketServer = class extends WebSocketHandler_default {
|
|
|
1181
1191
|
if (!this.webSocketServer || !this.isRunning) {
|
|
1182
1192
|
return;
|
|
1183
1193
|
}
|
|
1184
|
-
super.
|
|
1185
|
-
super.abortSocketMessages();
|
|
1194
|
+
super.offAny();
|
|
1186
1195
|
await super.closeClientSockets();
|
|
1187
1196
|
await closeServerSocket(this.webSocketServer, { timeout: this.socketTimeout });
|
|
1188
|
-
this.webSocketServer.removeAllListeners();
|
|
1189
1197
|
this.webSocketServer = void 0;
|
|
1190
1198
|
}
|
|
1191
1199
|
};
|
|
@@ -1535,17 +1543,17 @@ var InterceptorServer = class {
|
|
|
1535
1543
|
return void 0;
|
|
1536
1544
|
}
|
|
1537
1545
|
async startHttpServer() {
|
|
1546
|
+
this.httpServerOrThrow.on("request", this.handleHttpRequest);
|
|
1538
1547
|
await startHttpServer(this.httpServerOrThrow, {
|
|
1539
1548
|
hostname: this.hostname,
|
|
1540
1549
|
port: this.port
|
|
1541
1550
|
});
|
|
1542
1551
|
this.port = getHttpServerPort(this.httpServerOrThrow);
|
|
1543
|
-
this.httpServerOrThrow.on("request", this.handleHttpRequest);
|
|
1544
1552
|
}
|
|
1545
1553
|
startWebSocketServer() {
|
|
1554
|
+
this.webSocketServerOrThrow.onChannel("event", "interceptors/workers/commit", this.commitWorker);
|
|
1555
|
+
this.webSocketServerOrThrow.onChannel("event", "interceptors/workers/reset", this.resetWorker);
|
|
1546
1556
|
this.webSocketServerOrThrow.start();
|
|
1547
|
-
this.webSocketServerOrThrow.onEvent("interceptors/workers/commit", this.commitWorker);
|
|
1548
|
-
this.webSocketServerOrThrow.onEvent("interceptors/workers/reset", this.resetWorker);
|
|
1549
1557
|
}
|
|
1550
1558
|
commitWorker = (message, socket) => {
|
|
1551
1559
|
const commit = message.data;
|
|
@@ -1553,18 +1561,31 @@ var InterceptorServer = class {
|
|
|
1553
1561
|
this.registerWorkerSocketIfUnknown(socket);
|
|
1554
1562
|
return {};
|
|
1555
1563
|
};
|
|
1556
|
-
resetWorker = (
|
|
1557
|
-
this.
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1564
|
+
resetWorker = ({ data: handlersToRecommit }, socket) => {
|
|
1565
|
+
this.registerWorkerSocketIfUnknown(socket);
|
|
1566
|
+
this.webSocketServerOrThrow.emitSocket("abortRequests", socket, {
|
|
1567
|
+
shouldAbortRequest: (request) => {
|
|
1568
|
+
const isResponseCreationRequest = this.webSocketServerOrThrow.isChannelEvent(
|
|
1569
|
+
request,
|
|
1570
|
+
"interceptors/responses/create"
|
|
1571
|
+
);
|
|
1572
|
+
if (!isResponseCreationRequest) {
|
|
1573
|
+
return false;
|
|
1574
|
+
}
|
|
1575
|
+
const isHandlerStillCommitted = handlersToRecommit.some(
|
|
1576
|
+
/* istanbul ignore next -- @preserve
|
|
1577
|
+
* Ensuring this function is called in tests is difficult because it requires clearing or stopping a worker
|
|
1578
|
+
* at the exact moment a request is being handled, in a scenario when there are other handlers still
|
|
1579
|
+
* committed. */
|
|
1580
|
+
(handler) => request.data.handlerId === handler.id
|
|
1581
|
+
);
|
|
1582
|
+
return !isHandlerStillCommitted;
|
|
1565
1583
|
}
|
|
1584
|
+
});
|
|
1585
|
+
this.removeHttpHandlersBySocket(socket);
|
|
1586
|
+
for (const handler of handlersToRecommit) {
|
|
1587
|
+
this.registerHttpHandler(handler, socket);
|
|
1566
1588
|
}
|
|
1567
|
-
this.registerWorkerSocketIfUnknown(socket);
|
|
1568
1589
|
return {};
|
|
1569
1590
|
};
|
|
1570
1591
|
registerHttpHandler({ id, baseURL, method, path: path2 }, socket) {
|
|
@@ -1605,8 +1626,8 @@ var InterceptorServer = class {
|
|
|
1605
1626
|
this.httpServer = void 0;
|
|
1606
1627
|
}
|
|
1607
1628
|
async stopWebSocketServer() {
|
|
1608
|
-
this.webSocketServerOrThrow.
|
|
1609
|
-
this.webSocketServerOrThrow.
|
|
1629
|
+
this.webSocketServerOrThrow.offChannel("event", "interceptors/workers/commit", this.commitWorker);
|
|
1630
|
+
this.webSocketServerOrThrow.offChannel("event", "interceptors/workers/reset", this.resetWorker);
|
|
1610
1631
|
await this.webSocketServerOrThrow.stop();
|
|
1611
1632
|
this.webSocketServer = void 0;
|
|
1612
1633
|
}
|
|
@@ -1736,6 +1757,8 @@ function createInterceptorServer(options = {}) {
|
|
|
1736
1757
|
/* istanbul ignore next -- @preserve
|
|
1737
1758
|
* Reply listeners are always present when notified in normal conditions. If they were not present, the request
|
|
1738
1759
|
* would reach a timeout and not be responded. The empty set serves as a fallback. */
|
|
1760
|
+
/* istanbul ignore if -- @preserve
|
|
1761
|
+
* Aborting requests is highly non-deterministic because it depends on specific timing of socket events. */
|
|
1739
1762
|
/* istanbul ignore if -- @preserve
|
|
1740
1763
|
* This should never happen, but let's check that the token identifier is valid after generated. */
|
|
1741
1764
|
/* istanbul ignore if -- @preserve
|
|
@@ -1746,6 +1769,9 @@ function createInterceptorServer(options = {}) {
|
|
|
1746
1769
|
* The HTTP server is initialized before using this method in normal conditions. */
|
|
1747
1770
|
/* istanbul ignore if -- @preserve
|
|
1748
1771
|
* The web socket server is initialized before using this method in normal conditions. */
|
|
1772
|
+
/* istanbul ignore if -- @preserve
|
|
1773
|
+
* While resetting a worker, there could be other types of requests in progress. These are not guaranteed to
|
|
1774
|
+
* exist and are not related to handler resets, so we let them continue. */
|
|
1749
1775
|
/* istanbul ignore else -- @preserve
|
|
1750
1776
|
* This is always true during tests because we force max-age=0 to disable CORS caching. */
|
|
1751
1777
|
/* istanbul ignore next -- @preserve
|
|
@@ -1769,5 +1795,5 @@ exports.listInterceptorTokens = listInterceptorTokens;
|
|
|
1769
1795
|
exports.logger = logger;
|
|
1770
1796
|
exports.readInterceptorTokenFromFile = readInterceptorTokenFromFile;
|
|
1771
1797
|
exports.removeInterceptorToken = removeInterceptorToken;
|
|
1772
|
-
//# sourceMappingURL=chunk-
|
|
1773
|
-
//# sourceMappingURL=chunk-
|
|
1798
|
+
//# sourceMappingURL=chunk-IPL73BDI.js.map
|
|
1799
|
+
//# sourceMappingURL=chunk-IPL73BDI.js.map
|