@mswjs/interceptors 0.15.1 → 0.15.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/LICENSE.md +9 -0
- package/README.md +68 -49
- package/lib/BatchInterceptor.d.ts +18 -0
- package/lib/BatchInterceptor.js +79 -0
- package/lib/BatchInterceptor.js.map +1 -0
- package/lib/Interceptor.d.ts +49 -0
- package/lib/Interceptor.js +197 -0
- package/lib/Interceptor.js.map +1 -0
- package/lib/RemoteInterceptor.d.ts +24 -0
- package/lib/RemoteInterceptor.js +216 -0
- package/lib/RemoteInterceptor.js.map +1 -0
- package/lib/glossary.d.ts +32 -0
- package/lib/glossary.js +3 -0
- package/lib/glossary.js.map +1 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/interceptors/ClientRequest/NodeClientRequest.d.ts +5 -5
- package/lib/interceptors/ClientRequest/NodeClientRequest.js +56 -15
- package/lib/interceptors/ClientRequest/NodeClientRequest.js.map +1 -1
- package/lib/interceptors/ClientRequest/http.get.d.ts +2 -3
- package/lib/interceptors/ClientRequest/http.get.js +2 -5
- package/lib/interceptors/ClientRequest/http.get.js.map +1 -1
- package/lib/interceptors/ClientRequest/http.request.d.ts +2 -3
- package/lib/interceptors/ClientRequest/http.request.js +3 -6
- package/lib/interceptors/ClientRequest/http.request.js.map +1 -1
- package/lib/interceptors/ClientRequest/index.d.ts +14 -4
- package/lib/interceptors/ClientRequest/index.js +59 -46
- package/lib/interceptors/ClientRequest/index.js.map +1 -1
- package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js +7 -2
- package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js.map +1 -1
- package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.d.ts +11 -4
- package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js +110 -58
- package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js.map +1 -1
- package/lib/interceptors/XMLHttpRequest/index.d.ts +11 -5
- package/lib/interceptors/XMLHttpRequest/index.js +43 -25
- package/lib/interceptors/XMLHttpRequest/index.js.map +1 -1
- package/lib/interceptors/fetch/index.d.ts +8 -2
- package/lib/interceptors/fetch/index.js +120 -68
- package/lib/interceptors/fetch/index.js.map +1 -1
- package/lib/presets/browser.d.ts +3 -1
- package/lib/presets/browser.js +2 -2
- package/lib/presets/browser.js.map +1 -1
- package/lib/presets/node.d.ts +3 -1
- package/lib/presets/node.js +1 -1
- package/lib/presets/node.js.map +1 -1
- package/lib/utils/AsyncEventEmitter.d.ts +29 -0
- package/lib/utils/AsyncEventEmitter.js +241 -0
- package/lib/utils/AsyncEventEmitter.js.map +1 -0
- package/lib/utils/createLazyCallback.d.ts +11 -0
- package/lib/utils/createLazyCallback.js +75 -0
- package/lib/utils/createLazyCallback.js.map +1 -0
- package/lib/utils/nextTick.d.ts +2 -0
- package/lib/utils/nextTick.js +16 -0
- package/lib/utils/nextTick.js.map +1 -0
- package/lib/utils/toIsoResponse.d.ts +1 -1
- package/package.json +6 -6
- package/src/BatchInterceptor.test.ts +113 -0
- package/src/BatchInterceptor.ts +60 -0
- package/src/Interceptor.test.ts +166 -0
- package/src/Interceptor.ts +226 -0
- package/src/RemoteInterceptor.ts +176 -0
- package/src/glossary.ts +42 -0
- package/src/index.ts +2 -2
- package/src/interceptors/ClientRequest/NodeClientRequest.test.ts +87 -70
- package/src/interceptors/ClientRequest/NodeClientRequest.ts +139 -100
- package/src/interceptors/ClientRequest/http.get.ts +7 -11
- package/src/interceptors/ClientRequest/http.request.ts +8 -12
- package/src/interceptors/ClientRequest/index.test.ts +43 -0
- package/src/interceptors/ClientRequest/index.ts +46 -46
- package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +9 -0
- package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +9 -2
- package/src/interceptors/XMLHttpRequest/XMLHttpRequestOverride.ts +215 -159
- package/src/interceptors/XMLHttpRequest/index.ts +41 -23
- package/src/interceptors/fetch/index.ts +81 -55
- package/src/presets/browser.ts +3 -3
- package/src/presets/node.ts +3 -3
- package/src/utils/AsyncEventEmitter.test.ts +68 -0
- package/src/utils/AsyncEventEmitter.ts +171 -0
- package/src/utils/createLazyCallback.ts +49 -0
- package/src/utils/nextTick.ts +11 -0
- package/src/utils/toIsoResponse.ts +1 -1
- package/lib/createInterceptor.d.ts +0 -54
- package/lib/createInterceptor.js +0 -27
- package/lib/createInterceptor.js.map +0 -1
- package/lib/remote.d.ts +0 -21
- package/lib/remote.js +0 -178
- package/lib/remote.js.map +0 -1
- package/src/createInterceptor.ts +0 -100
- package/src/remote.ts +0 -174
package/lib/remote.js
DELETED
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (_) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
50
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
51
|
-
if (!m) return o;
|
|
52
|
-
var i = m.call(o), r, ar = [], e;
|
|
53
|
-
try {
|
|
54
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
55
|
-
}
|
|
56
|
-
catch (error) { e = { error: error }; }
|
|
57
|
-
finally {
|
|
58
|
-
try {
|
|
59
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
60
|
-
}
|
|
61
|
-
finally { if (e) throw e.error; }
|
|
62
|
-
}
|
|
63
|
-
return ar;
|
|
64
|
-
};
|
|
65
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
66
|
-
exports.createRemoteResolver = exports.createRemoteInterceptor = void 0;
|
|
67
|
-
var headers_polyfill_1 = require("headers-polyfill");
|
|
68
|
-
var outvariant_1 = require("outvariant");
|
|
69
|
-
var strict_event_emitter_1 = require("strict-event-emitter");
|
|
70
|
-
var createInterceptor_1 = require("./createInterceptor");
|
|
71
|
-
var toIsoResponse_1 = require("./utils/toIsoResponse");
|
|
72
|
-
function requestReviver(key, value) {
|
|
73
|
-
switch (key) {
|
|
74
|
-
case 'url':
|
|
75
|
-
return new URL(value);
|
|
76
|
-
case 'headers':
|
|
77
|
-
return new headers_polyfill_1.Headers(value);
|
|
78
|
-
default:
|
|
79
|
-
return value;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Creates a remote request interceptor that delegates
|
|
84
|
-
* the mocked response resolution to the parent process.
|
|
85
|
-
* The parent process must establish a remote resolver
|
|
86
|
-
* by calling `createRemoteResolver` function.
|
|
87
|
-
*/
|
|
88
|
-
function createRemoteInterceptor(options) {
|
|
89
|
-
outvariant_1.invariant(process.connected, "Failed to create a remote interceptor: the current process (%s) does not have a parent. Please make sure you're spawning this process as a child process in order to use remote request interception.", process.pid);
|
|
90
|
-
if (typeof process.send === 'undefined') {
|
|
91
|
-
throw new Error("Failed to create a remote interceptor: the current process (" + process.pid + ") does not have the IPC enabled. Please make sure you're spawning this process with the \"ipc\" stdio value set:\n\nspawn('node', ['module.js'], { stdio: ['ipc'] })");
|
|
92
|
-
}
|
|
93
|
-
var handleParentMessage;
|
|
94
|
-
var interceptor = createInterceptor_1.createInterceptor(__assign(__assign({}, options), { resolver: function (request) {
|
|
95
|
-
var _a;
|
|
96
|
-
var serializedRequest = JSON.stringify(request);
|
|
97
|
-
(_a = process.send) === null || _a === void 0 ? void 0 : _a.call(process, "request:" + serializedRequest);
|
|
98
|
-
return new Promise(function (resolve) {
|
|
99
|
-
handleParentMessage = function (message) {
|
|
100
|
-
if (typeof message !== 'string') {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
if (message.startsWith("response:" + request.id)) {
|
|
104
|
-
var _a = __read(message.match(/^response:.+?:(.+)$/) || [], 2), responseString = _a[1];
|
|
105
|
-
if (!responseString) {
|
|
106
|
-
return resolve();
|
|
107
|
-
}
|
|
108
|
-
var mockedResponse = JSON.parse(responseString);
|
|
109
|
-
return resolve(mockedResponse);
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
process.addListener('message', handleParentMessage);
|
|
113
|
-
});
|
|
114
|
-
} }));
|
|
115
|
-
return __assign(__assign({}, interceptor), { restore: function () {
|
|
116
|
-
interceptor.restore();
|
|
117
|
-
process.removeListener('message', handleParentMessage);
|
|
118
|
-
} });
|
|
119
|
-
}
|
|
120
|
-
exports.createRemoteInterceptor = createRemoteInterceptor;
|
|
121
|
-
/**
|
|
122
|
-
* Creates a response resolver function attached to the given `ChildProcess`.
|
|
123
|
-
* The child process must establish a remote interceptor by calling `createRemoteInterceptor` function.
|
|
124
|
-
*/
|
|
125
|
-
function createRemoteResolver(options) {
|
|
126
|
-
var _this = this;
|
|
127
|
-
var observer = new strict_event_emitter_1.StrictEventEmitter();
|
|
128
|
-
var handleChildMessage = function (message) { return __awaiter(_this, void 0, void 0, function () {
|
|
129
|
-
var _a, requestString, isoRequest_1, mockedResponse_1, serializedResponse;
|
|
130
|
-
return __generator(this, function (_b) {
|
|
131
|
-
switch (_b.label) {
|
|
132
|
-
case 0:
|
|
133
|
-
if (typeof message !== 'string') {
|
|
134
|
-
return [2 /*return*/];
|
|
135
|
-
}
|
|
136
|
-
if (!message.startsWith('request:')) return [3 /*break*/, 2];
|
|
137
|
-
_a = __read(message.match(/^request:(.+)$/) || [], 2), requestString = _a[1];
|
|
138
|
-
if (!requestString) {
|
|
139
|
-
return [2 /*return*/];
|
|
140
|
-
}
|
|
141
|
-
isoRequest_1 = JSON.parse(requestString, requestReviver);
|
|
142
|
-
observer.emit('request', isoRequest_1);
|
|
143
|
-
return [4 /*yield*/, options.resolver(isoRequest_1, undefined)
|
|
144
|
-
// Send the mocked response to the child process.
|
|
145
|
-
];
|
|
146
|
-
case 1:
|
|
147
|
-
mockedResponse_1 = _b.sent();
|
|
148
|
-
serializedResponse = JSON.stringify(mockedResponse_1);
|
|
149
|
-
options.process.send("response:" + isoRequest_1.id + ":" + serializedResponse, function (error) {
|
|
150
|
-
if (error) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
if (mockedResponse_1) {
|
|
154
|
-
// Emit an optimisting "response" event at this point,
|
|
155
|
-
// not to rely on the back-and-forth signaling for the sake of the event.
|
|
156
|
-
observer.emit('response', isoRequest_1, toIsoResponse_1.toIsoResponse(mockedResponse_1));
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
_b.label = 2;
|
|
160
|
-
case 2: return [2 /*return*/];
|
|
161
|
-
}
|
|
162
|
-
});
|
|
163
|
-
}); };
|
|
164
|
-
var cleanup = function () {
|
|
165
|
-
options.process.removeListener('message', handleChildMessage);
|
|
166
|
-
};
|
|
167
|
-
options.process.addListener('message', handleChildMessage);
|
|
168
|
-
options.process.addListener('disconnect', cleanup);
|
|
169
|
-
options.process.addListener('error', cleanup);
|
|
170
|
-
options.process.addListener('exit', cleanup);
|
|
171
|
-
return {
|
|
172
|
-
on: function (event, listener) {
|
|
173
|
-
observer.addListener(event, listener);
|
|
174
|
-
},
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
exports.createRemoteResolver = createRemoteResolver;
|
|
178
|
-
//# sourceMappingURL=remote.js.map
|
package/lib/remote.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"remote.js","sourceRoot":"","sources":["../src/remote.ts"],"names":[],"mappings":"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"}
|
package/src/createInterceptor.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { IncomingMessage } from 'http'
|
|
2
|
-
import { HeadersObject, Headers } from 'headers-polyfill'
|
|
3
|
-
import { StrictEventEmitter } from 'strict-event-emitter'
|
|
4
|
-
|
|
5
|
-
export type Interceptor = (
|
|
6
|
-
observer: Observer,
|
|
7
|
-
resolver: Resolver
|
|
8
|
-
) => InterceptorCleanupFn
|
|
9
|
-
|
|
10
|
-
export type Observer = StrictEventEmitter<InterceptorEventsMap>
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* A side-effect function to restore all the patched modules.
|
|
14
|
-
*/
|
|
15
|
-
export type InterceptorCleanupFn = () => void
|
|
16
|
-
|
|
17
|
-
export type RequestCredentials = 'omit' | 'include' | 'same-origin'
|
|
18
|
-
|
|
19
|
-
export interface IsomorphicRequest {
|
|
20
|
-
id: string
|
|
21
|
-
url: URL
|
|
22
|
-
method: string
|
|
23
|
-
headers: Headers
|
|
24
|
-
/**
|
|
25
|
-
* The value of the request client's "credentials" option
|
|
26
|
-
* or a compatible alternative (i.e. `withCredentials` for `XMLHttpRequest`).
|
|
27
|
-
* Always equals to "omit" in Node.js.
|
|
28
|
-
*/
|
|
29
|
-
credentials: RequestCredentials
|
|
30
|
-
body?: string
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface IsomorphicResponse {
|
|
34
|
-
status: number
|
|
35
|
-
statusText: string
|
|
36
|
-
headers: Headers
|
|
37
|
-
body?: string
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface MockedResponse
|
|
41
|
-
extends Omit<Partial<IsomorphicResponse>, 'headers'> {
|
|
42
|
-
headers?: HeadersObject
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export interface InterceptorEventsMap {
|
|
46
|
-
request(request: IsomorphicRequest): void
|
|
47
|
-
response(request: IsomorphicRequest, response: IsomorphicResponse): void
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export type Resolver = (
|
|
51
|
-
request: IsomorphicRequest,
|
|
52
|
-
ref: IncomingMessage | XMLHttpRequest | Request
|
|
53
|
-
) => MockedResponse | Promise<MockedResponse | void> | void
|
|
54
|
-
|
|
55
|
-
export interface InterceptorOptions {
|
|
56
|
-
modules: Interceptor[]
|
|
57
|
-
resolver: Resolver
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export interface InterceptorApi {
|
|
61
|
-
/**
|
|
62
|
-
* Apply necessary module patches to provision the interception of requests.
|
|
63
|
-
*/
|
|
64
|
-
apply(): void
|
|
65
|
-
on<Event extends keyof InterceptorEventsMap>(
|
|
66
|
-
event: Event,
|
|
67
|
-
listener: InterceptorEventsMap[Event]
|
|
68
|
-
): void
|
|
69
|
-
/**
|
|
70
|
-
* Restore all applied module patches and disable the interception.
|
|
71
|
-
*/
|
|
72
|
-
restore(): void
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function createInterceptor(options: InterceptorOptions): InterceptorApi {
|
|
76
|
-
const observer = new StrictEventEmitter<InterceptorEventsMap>()
|
|
77
|
-
let cleanupFns: InterceptorCleanupFn[] = []
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
apply() {
|
|
81
|
-
cleanupFns = options.modules.map((interceptor) => {
|
|
82
|
-
return interceptor(observer, options.resolver)
|
|
83
|
-
})
|
|
84
|
-
},
|
|
85
|
-
on(event, listener) {
|
|
86
|
-
observer.addListener(event, listener)
|
|
87
|
-
},
|
|
88
|
-
restore() {
|
|
89
|
-
observer.removeAllListeners()
|
|
90
|
-
|
|
91
|
-
if (cleanupFns.length === 0) {
|
|
92
|
-
throw new Error(
|
|
93
|
-
`Failed to restore patched modules: no patches found. Did you forget to run ".apply()"?`
|
|
94
|
-
)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
cleanupFns.forEach((restore) => restore())
|
|
98
|
-
},
|
|
99
|
-
}
|
|
100
|
-
}
|
package/src/remote.ts
DELETED
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { ChildProcess } from 'child_process'
|
|
2
|
-
import { Headers } from 'headers-polyfill'
|
|
3
|
-
import { invariant } from 'outvariant'
|
|
4
|
-
import { StrictEventEmitter } from 'strict-event-emitter'
|
|
5
|
-
import {
|
|
6
|
-
createInterceptor,
|
|
7
|
-
InterceptorApi,
|
|
8
|
-
InterceptorEventsMap,
|
|
9
|
-
InterceptorOptions,
|
|
10
|
-
IsomorphicRequest,
|
|
11
|
-
Resolver,
|
|
12
|
-
} from './createInterceptor'
|
|
13
|
-
import { toIsoResponse } from './utils/toIsoResponse'
|
|
14
|
-
|
|
15
|
-
export type CreateRemoteInterceptorOptions = Omit<
|
|
16
|
-
InterceptorOptions,
|
|
17
|
-
'resolver'
|
|
18
|
-
>
|
|
19
|
-
|
|
20
|
-
export type RemoteResolverApi = Pick<InterceptorApi, 'on'>
|
|
21
|
-
|
|
22
|
-
export interface CreateRemoteResolverOptions {
|
|
23
|
-
process: ChildProcess
|
|
24
|
-
resolver: Resolver
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function requestReviver(key: string, value: any) {
|
|
28
|
-
switch (key) {
|
|
29
|
-
case 'url':
|
|
30
|
-
return new URL(value)
|
|
31
|
-
|
|
32
|
-
case 'headers':
|
|
33
|
-
return new Headers(value)
|
|
34
|
-
|
|
35
|
-
default:
|
|
36
|
-
return value
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Creates a remote request interceptor that delegates
|
|
42
|
-
* the mocked response resolution to the parent process.
|
|
43
|
-
* The parent process must establish a remote resolver
|
|
44
|
-
* by calling `createRemoteResolver` function.
|
|
45
|
-
*/
|
|
46
|
-
export function createRemoteInterceptor(
|
|
47
|
-
options: CreateRemoteInterceptorOptions
|
|
48
|
-
): InterceptorApi {
|
|
49
|
-
invariant(
|
|
50
|
-
process.connected,
|
|
51
|
-
`Failed to create a remote interceptor: the current process (%s) does not have a parent. Please make sure you're spawning this process as a child process in order to use remote request interception.`,
|
|
52
|
-
process.pid
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
if (typeof process.send === 'undefined') {
|
|
56
|
-
throw new Error(
|
|
57
|
-
`\
|
|
58
|
-
Failed to create a remote interceptor: the current process (${process.pid}) does not have the IPC enabled. Please make sure you're spawning this process with the "ipc" stdio value set:
|
|
59
|
-
|
|
60
|
-
spawn('node', ['module.js'], { stdio: ['ipc'] })\
|
|
61
|
-
`
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
let handleParentMessage: NodeJS.MessageListener
|
|
66
|
-
|
|
67
|
-
const interceptor = createInterceptor({
|
|
68
|
-
...options,
|
|
69
|
-
resolver(request) {
|
|
70
|
-
const serializedRequest = JSON.stringify(request)
|
|
71
|
-
process.send?.(`request:${serializedRequest}`)
|
|
72
|
-
|
|
73
|
-
return new Promise((resolve) => {
|
|
74
|
-
handleParentMessage = (message) => {
|
|
75
|
-
if (typeof message !== 'string') {
|
|
76
|
-
return
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if (message.startsWith(`response:${request.id}`)) {
|
|
80
|
-
const [, responseString] =
|
|
81
|
-
message.match(/^response:.+?:(.+)$/) || []
|
|
82
|
-
|
|
83
|
-
if (!responseString) {
|
|
84
|
-
return resolve()
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const mockedResponse = JSON.parse(responseString)
|
|
88
|
-
|
|
89
|
-
return resolve(mockedResponse)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
process.addListener('message', handleParentMessage)
|
|
94
|
-
})
|
|
95
|
-
},
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
...interceptor,
|
|
100
|
-
restore() {
|
|
101
|
-
interceptor.restore()
|
|
102
|
-
process.removeListener('message', handleParentMessage)
|
|
103
|
-
},
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Creates a response resolver function attached to the given `ChildProcess`.
|
|
109
|
-
* The child process must establish a remote interceptor by calling `createRemoteInterceptor` function.
|
|
110
|
-
*/
|
|
111
|
-
export function createRemoteResolver(
|
|
112
|
-
options: CreateRemoteResolverOptions
|
|
113
|
-
): RemoteResolverApi {
|
|
114
|
-
const observer = new StrictEventEmitter<InterceptorEventsMap>()
|
|
115
|
-
|
|
116
|
-
const handleChildMessage: NodeJS.MessageListener = async (message) => {
|
|
117
|
-
if (typeof message !== 'string') {
|
|
118
|
-
return
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (message.startsWith('request:')) {
|
|
122
|
-
const [, requestString] = message.match(/^request:(.+)$/) || []
|
|
123
|
-
|
|
124
|
-
if (!requestString) {
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const isoRequest: IsomorphicRequest = JSON.parse(
|
|
129
|
-
requestString,
|
|
130
|
-
requestReviver
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
observer.emit('request', isoRequest)
|
|
134
|
-
|
|
135
|
-
// Retrieve the mocked response.
|
|
136
|
-
const mockedResponse = await options.resolver(
|
|
137
|
-
isoRequest,
|
|
138
|
-
undefined as any
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
// Send the mocked response to the child process.
|
|
142
|
-
const serializedResponse = JSON.stringify(mockedResponse)
|
|
143
|
-
options.process.send(
|
|
144
|
-
`response:${isoRequest.id}:${serializedResponse}`,
|
|
145
|
-
(error) => {
|
|
146
|
-
if (error) {
|
|
147
|
-
return
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (mockedResponse) {
|
|
151
|
-
// Emit an optimisting "response" event at this point,
|
|
152
|
-
// not to rely on the back-and-forth signaling for the sake of the event.
|
|
153
|
-
observer.emit('response', isoRequest, toIsoResponse(mockedResponse))
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const cleanup = () => {
|
|
161
|
-
options.process.removeListener('message', handleChildMessage)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
options.process.addListener('message', handleChildMessage)
|
|
165
|
-
options.process.addListener('disconnect', cleanup)
|
|
166
|
-
options.process.addListener('error', cleanup)
|
|
167
|
-
options.process.addListener('exit', cleanup)
|
|
168
|
-
|
|
169
|
-
return {
|
|
170
|
-
on(event, listener) {
|
|
171
|
-
observer.addListener(event, listener)
|
|
172
|
-
},
|
|
173
|
-
}
|
|
174
|
-
}
|