@mswjs/interceptors 0.15.3 → 0.16.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.
Files changed (91) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +70 -50
  3. package/lib/BatchInterceptor.d.ts +18 -0
  4. package/lib/BatchInterceptor.js +79 -0
  5. package/lib/BatchInterceptor.js.map +1 -0
  6. package/lib/Interceptor.d.ts +49 -0
  7. package/lib/Interceptor.js +197 -0
  8. package/lib/Interceptor.js.map +1 -0
  9. package/lib/RemoteHttpInterceptor.d.ts +24 -0
  10. package/lib/RemoteHttpInterceptor.js +216 -0
  11. package/lib/RemoteHttpInterceptor.js.map +1 -0
  12. package/lib/glossary.d.ts +32 -0
  13. package/lib/glossary.js +3 -0
  14. package/lib/glossary.js.map +1 -0
  15. package/lib/index.d.ts +3 -2
  16. package/lib/index.js +3 -2
  17. package/lib/index.js.map +1 -1
  18. package/lib/interceptors/ClientRequest/NodeClientRequest.d.ts +5 -5
  19. package/lib/interceptors/ClientRequest/NodeClientRequest.js +56 -15
  20. package/lib/interceptors/ClientRequest/NodeClientRequest.js.map +1 -1
  21. package/lib/interceptors/ClientRequest/http.get.d.ts +2 -3
  22. package/lib/interceptors/ClientRequest/http.get.js +2 -5
  23. package/lib/interceptors/ClientRequest/http.get.js.map +1 -1
  24. package/lib/interceptors/ClientRequest/http.request.d.ts +2 -3
  25. package/lib/interceptors/ClientRequest/http.request.js +3 -6
  26. package/lib/interceptors/ClientRequest/http.request.js.map +1 -1
  27. package/lib/interceptors/ClientRequest/index.d.ts +14 -4
  28. package/lib/interceptors/ClientRequest/index.js +59 -46
  29. package/lib/interceptors/ClientRequest/index.js.map +1 -1
  30. package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js +7 -2
  31. package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js.map +1 -1
  32. package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.d.ts +11 -4
  33. package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js +111 -58
  34. package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js.map +1 -1
  35. package/lib/interceptors/XMLHttpRequest/index.d.ts +11 -5
  36. package/lib/interceptors/XMLHttpRequest/index.js +43 -25
  37. package/lib/interceptors/XMLHttpRequest/index.js.map +1 -1
  38. package/lib/interceptors/fetch/index.d.ts +8 -2
  39. package/lib/interceptors/fetch/index.js +120 -68
  40. package/lib/interceptors/fetch/index.js.map +1 -1
  41. package/lib/presets/browser.d.ts +3 -1
  42. package/lib/presets/browser.js +2 -2
  43. package/lib/presets/browser.js.map +1 -1
  44. package/lib/presets/node.d.ts +3 -1
  45. package/lib/presets/node.js +1 -1
  46. package/lib/presets/node.js.map +1 -1
  47. package/lib/utils/AsyncEventEmitter.d.ts +29 -0
  48. package/lib/utils/AsyncEventEmitter.js +241 -0
  49. package/lib/utils/AsyncEventEmitter.js.map +1 -0
  50. package/lib/utils/createLazyCallback.d.ts +11 -0
  51. package/lib/utils/createLazyCallback.js +75 -0
  52. package/lib/utils/createLazyCallback.js.map +1 -0
  53. package/lib/utils/nextTick.d.ts +2 -0
  54. package/lib/utils/nextTick.js +16 -0
  55. package/lib/utils/nextTick.js.map +1 -0
  56. package/lib/utils/toIsoResponse.d.ts +1 -1
  57. package/package.json +6 -6
  58. package/src/BatchInterceptor.test.ts +113 -0
  59. package/src/BatchInterceptor.ts +60 -0
  60. package/src/Interceptor.test.ts +166 -0
  61. package/src/Interceptor.ts +226 -0
  62. package/src/RemoteHttpInterceptor.ts +176 -0
  63. package/src/glossary.ts +42 -0
  64. package/src/index.ts +3 -2
  65. package/src/interceptors/ClientRequest/NodeClientRequest.test.ts +87 -70
  66. package/src/interceptors/ClientRequest/NodeClientRequest.ts +139 -100
  67. package/src/interceptors/ClientRequest/http.get.ts +7 -11
  68. package/src/interceptors/ClientRequest/http.request.ts +8 -12
  69. package/src/interceptors/ClientRequest/index.test.ts +43 -0
  70. package/src/interceptors/ClientRequest/index.ts +46 -46
  71. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.test.ts +9 -0
  72. package/src/interceptors/ClientRequest/utils/getIncomingMessageBody.ts +9 -2
  73. package/src/interceptors/XMLHttpRequest/XMLHttpRequestOverride.ts +216 -159
  74. package/src/interceptors/XMLHttpRequest/index.ts +41 -23
  75. package/src/interceptors/fetch/index.ts +81 -55
  76. package/src/presets/browser.ts +3 -3
  77. package/src/presets/node.ts +3 -3
  78. package/src/utils/AsyncEventEmitter.test.ts +68 -0
  79. package/src/utils/AsyncEventEmitter.ts +171 -0
  80. package/src/utils/createLazyCallback.ts +49 -0
  81. package/src/utils/nextTick.ts +11 -0
  82. package/src/utils/toIsoResponse.ts +1 -1
  83. package/lib/createInterceptor.d.ts +0 -54
  84. package/lib/createInterceptor.js +0 -27
  85. package/lib/createInterceptor.js.map +0 -1
  86. package/lib/remote.d.ts +0 -21
  87. package/lib/remote.js +0 -178
  88. package/lib/remote.js.map +0 -1
  89. package/src/createInterceptor.ts +0 -100
  90. package/src/remote.ts +0 -174
  91. package/src/utils/.DS_Store +0 -0
package/LICENSE.md ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018–present Artem Zakharchenko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -98,101 +98,112 @@ npm install @mswjs/interceptors
98
98
 
99
99
  ## API
100
100
 
101
- ### `createInterceptor(options: CreateInterceptorOptions)`
101
+ ### Individual interceptors
102
102
 
103
- Enables request interception in the current process.
103
+ There are multiple individual interceptors exported from this library:
104
+
105
+ - `ClientRequestInterceptor`
106
+ - `XMLHttpRequestInterceptor`
107
+ - `FetchInterceptor`
108
+
109
+ All aforementioned interceptors implement the same HTTP request interception contract, meaning that they allow you to handle intercepted requests in the same way, regardless of the request origin (`http`/`XMLHttpRequest`/`fetch`).
110
+
111
+ To use multiple interceptors at once, consider [`BatchInterceptor`](#BatchInterceptor).
112
+
113
+ ```js
114
+ import { ClientRequestInterceptor } from '@mswjs/interceptors/lib/interceptors/ClientRequest'
115
+
116
+ const interceptor = new ClientRequestInterceptor()
117
+ interceptor.on('request', (request) => {
118
+ // Introspect request or mock its response
119
+ // via "request.respondWith()".
120
+ })
121
+ ```
122
+
123
+ ### `BatchInterceptor`
124
+
125
+ Applies multiple request interceptors at the same time.
104
126
 
105
127
  ```js
106
- import { createInterceptor } from '@mswjs/interceptors'
128
+ import { BatchInterceptor } from '@mswjs/interceptors'
107
129
  import nodeInterceptors from '@mswjs/interceptors/lib/presets/node'
108
130
 
109
- const interceptor = createInterceptor({
110
- modules: nodeInterceptors,
111
- resolver(request, ref) {
112
- // Optionally, return a mocked response.
113
- },
131
+ const interceptor = BatchInterceptor({
132
+ name: 'my-interceptor',
133
+ interceptors: nodeInterceptors,
134
+ })
135
+
136
+ interceptor.on('request', (request) => {
137
+ // Inspect the intercepted "request".
138
+ // Optionally, return a mocked response.
114
139
  })
115
140
  ```
116
141
 
117
142
  > Using the `/presets/node` interceptors preset is the recommended way to ensure all requests get intercepted, regardless of their origin.
118
143
 
119
- ### `createRemoteInterceptor(options: CreateRemoteInterceptorOptions)`
144
+ ### `RemoteHttpInterceptor`
120
145
 
121
146
  Enables request interception in the current process while delegating the response resolution logic to the _parent process_. **Requires the current process to be a child process**. Requires the parent process to establish a resolver by calling the `createRemoteResolver` function.
122
147
 
123
148
  ```js
124
- import { createRemoteInterceptor } from '@mswjs/interceptors'
149
+ // child.js
150
+ import { RemoteHttpInterceptor } from '@mswjs/interceptors/lib/RemoteHttpInterceptor'
151
+ import { ClientRequestInterceptor } from '@mswjs/interceptors/lib/interceptors/ClientRequest'
125
152
 
126
- const interceptor = createRemoteInterceptor({
127
- modules: nodeInterceptors,
153
+ const interceptor = new RemoteHttpInterceptor({
154
+ // Alternatively, you can use presets.
155
+ interceptors: [new ClientRequestInterceptor()],
128
156
  })
129
157
 
130
158
  interceptor.apply()
131
159
 
132
160
  process.on('disconnect', () => {
133
- interceptor.restore()
161
+ interceptor.dispose()
134
162
  })
135
163
  ```
136
164
 
137
- ### `createRemoteResolver(options: CreateRemoteResolverOptions)`
165
+ You can still listen to and handle any requests in the child process via the `request` event listener. Keep in mind that a single request can only be responded to once.
166
+
167
+ ### `RemoteHttpResolver`
138
168
 
139
169
  Resolves an intercepted request in the given child `process`. Requires for that child process to enable request interception by calling the `createRemoteInterceptor` function.
140
170
 
141
171
  ```js
172
+ // parent.js
142
173
  import { spawn } from 'child_process'
143
- import { createRemoteResolver } from '@mswjs/interceptors'
174
+ import { RemoteHttpResolver } from '@mswjs/interceptors/lib/RemoteHttpInterceptor'
144
175
 
145
176
  const appProcess = spawn('node', ['app.js'], {
146
177
  stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
147
178
  })
148
179
 
149
- createRemoteResolver({
180
+ const resolver = new RemoteHttpResolver({
150
181
  process: appProcess,
151
- resolver(request) {
152
- // Optionally, return a mocked response
153
- // for a request that occurred in the "appProcess".
154
- },
155
182
  })
156
- ```
157
-
158
- ### Interceptors
159
-
160
- This library utilizes a concept of _interceptors_–functions that extend request modules, handle mocked responses, and restore themselves when done.
161
-
162
- **Available interceptors:**
163
-
164
- - `/interceptors/ClientRequest`
165
- - `/interceptors/XMLHttpRequest`
166
- - `/interceptors/fetch`
167
-
168
- To use a single, or multiple interceptors, import and provide them to the `createInterceptor` function.
169
183
 
170
- ```js
171
- import { createInterceptor } from '@mswjs/interceptors'
172
- import { interceptXMLHttpRequest } from '@mswjs/interceptors/lib/interceptors/XMLHttpRequest'
173
-
174
- // This `interceptor` instance would handle only XMLHttpRequest,
175
- // ignoring requests issued via `http`/`https` modules.
176
- const interceptor = createInterceptor({
177
- modules: [interceptXMLHttpRequest],
184
+ resolver.on('request', (request) => {
185
+ // Optionally, return a mocked response
186
+ // for a request that occurred in the "appProcess".
178
187
  })
179
188
  ```
180
189
 
181
- > Interceptors are crucial in leveraging environment-specific module overrides. Certain environments (i.e. React Native) do not have access to native Node.js modules (like `http`). Importing such modules throws an exception and should be avoided.
182
-
183
190
  ### Methods
184
191
 
185
- #### `.apply(): void`
192
+ #### `apply`
186
193
 
187
- Applies module patches and enables interception of the requests.
194
+ Applies interceptor, enabling the interception of requests in the current process.
188
195
 
189
196
  ```js
190
197
  interceptor.apply()
191
198
  ```
192
199
 
193
- #### `.on(event, listener): boolean`
200
+ The same interceptor can be applied multiple times. If that happens, each subsequent interceptor instance will reusing a single running instance instead of applying itself repeatedly. Each interceptor instance should still be disposed individually.
201
+
202
+ #### `on`
194
203
 
195
- Adds an event listener to one of the following supported events:
204
+ Listens to the interceptor events.
205
+
206
+ Each interceptor decides what event map to implement. Currently, all exported interceptors implement an HTTP request event map that consists of the following events:
196
207
 
197
208
  - `request`, signals when a new request happens;
198
209
  - `response`, signals when a response was sent.
@@ -201,14 +212,23 @@ Adds an event listener to one of the following supported events:
201
212
  interceptor.on('request', (request) => {
202
213
  console.log('[%s] %s', request.method, request.url.toString())
203
214
  })
215
+
216
+ interceptor.on('response', (request, response) => {
217
+ console.log(
218
+ 'Received response to [%s] %s:',
219
+ request.method,
220
+ request.url.href,
221
+ response
222
+ )
223
+ })
204
224
  ```
205
225
 
206
- #### `.restore(): void`
226
+ #### `dispose`
207
227
 
208
- Restores all extensions and stops the interception of future requests.
228
+ Disposes of the applied interceptor. This cleans up all the side-effects introduced by the interceptor (i.e. restores augmented modules).
209
229
 
210
230
  ```js
211
- interceptor.restore()
231
+ interceptor.dispose()
212
232
  ```
213
233
 
214
234
  ## Special mention
@@ -0,0 +1,18 @@
1
+ import { EventMapType } from 'strict-event-emitter';
2
+ import { ExtractEventNames, Interceptor } from './Interceptor';
3
+ export interface BatchInterceptorOptions<InterceptorList extends Interceptor<any>[]> {
4
+ name: string;
5
+ interceptors: InterceptorList;
6
+ }
7
+ export declare type ExtractEventMapType<InterceptorList extends Interceptor<any>[]> = InterceptorList extends Array<infer InterceptorType> ? InterceptorType extends Interceptor<infer EventMap> ? EventMap : never : never;
8
+ /**
9
+ * A batch interceptor that exposes a single interface
10
+ * to apply and operate with multiple interceptors at once.
11
+ */
12
+ export declare class BatchInterceptor<InterceptorList extends Interceptor<any>[], EventMap extends EventMapType = ExtractEventMapType<InterceptorList>> extends Interceptor<EventMap> {
13
+ static symbol: Symbol;
14
+ private interceptors;
15
+ constructor(options: BatchInterceptorOptions<InterceptorList>);
16
+ protected setup(): void;
17
+ on<Event extends ExtractEventNames<EventMap>>(event: Event, listener: EventMap[Event]): void;
18
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __values = (this && this.__values) || function(o) {
18
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
19
+ if (m) return m.call(o);
20
+ if (o && typeof o.length === "number") return {
21
+ next: function () {
22
+ if (o && i >= o.length) o = void 0;
23
+ return { value: o && o[i++], done: !o };
24
+ }
25
+ };
26
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.BatchInterceptor = void 0;
30
+ var Interceptor_1 = require("./Interceptor");
31
+ /**
32
+ * A batch interceptor that exposes a single interface
33
+ * to apply and operate with multiple interceptors at once.
34
+ */
35
+ var BatchInterceptor = /** @class */ (function (_super) {
36
+ __extends(BatchInterceptor, _super);
37
+ function BatchInterceptor(options) {
38
+ var _this = this;
39
+ BatchInterceptor.symbol = Symbol(options.name);
40
+ _this = _super.call(this, BatchInterceptor.symbol) || this;
41
+ _this.interceptors = options.interceptors;
42
+ return _this;
43
+ }
44
+ BatchInterceptor.prototype.setup = function () {
45
+ var e_1, _a;
46
+ var log = this.log.extend('setup');
47
+ log('applying all %d interceptors...', this.interceptors.length);
48
+ var _loop_1 = function (interceptor) {
49
+ log('applying "%s" interceptor...', interceptor.constructor.name);
50
+ interceptor.apply();
51
+ log('adding interceptor dispose subscription');
52
+ this_1.subscriptions.push(function () { return interceptor.dispose(); });
53
+ };
54
+ var this_1 = this;
55
+ try {
56
+ for (var _b = __values(this.interceptors), _c = _b.next(); !_c.done; _c = _b.next()) {
57
+ var interceptor = _c.value;
58
+ _loop_1(interceptor);
59
+ }
60
+ }
61
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
62
+ finally {
63
+ try {
64
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
65
+ }
66
+ finally { if (e_1) throw e_1.error; }
67
+ }
68
+ };
69
+ BatchInterceptor.prototype.on = function (event, listener) {
70
+ // Instead of adding a listener to the batch interceptor,
71
+ // propagate the listener to each of the individual interceptors.
72
+ this.interceptors.forEach(function (interceptor) {
73
+ interceptor.on(event, listener);
74
+ });
75
+ };
76
+ return BatchInterceptor;
77
+ }(Interceptor_1.Interceptor));
78
+ exports.BatchInterceptor = BatchInterceptor;
79
+ //# sourceMappingURL=BatchInterceptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BatchInterceptor.js","sourceRoot":"","sources":["../src/BatchInterceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,6CAA8D;AAgB9D;;;GAGG;AACH;IAGU,oCAAqB;IAK7B,0BAAY,OAAiD;QAA7D,iBAIC;QAHC,gBAAgB,CAAC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC9C,QAAA,kBAAM,gBAAgB,CAAC,MAAM,CAAC,SAAA;QAC9B,KAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAA;;IAC1C,CAAC;IAES,gCAAK,GAAf;;QACE,IAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAEpC,GAAG,CAAC,iCAAiC,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;gCAErD,WAAW;YACpB,GAAG,CAAC,8BAA8B,EAAE,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;YACjE,WAAW,CAAC,KAAK,EAAE,CAAA;YAEnB,GAAG,CAAC,yCAAyC,CAAC,CAAA;YAC9C,OAAK,aAAa,CAAC,IAAI,CAAC,cAAM,OAAA,WAAW,CAAC,OAAO,EAAE,EAArB,CAAqB,CAAC,CAAA;;;;YALtD,KAA0B,IAAA,KAAA,SAAA,IAAI,CAAC,YAAY,CAAA,gBAAA;gBAAtC,IAAM,WAAW,WAAA;wBAAX,WAAW;aAMrB;;;;;;;;;IACH,CAAC;IAEM,6BAAE,GAAT,UACE,KAAY,EACZ,QAAyB;QAEzB,yDAAyD;QACzD,iEAAiE;QACjE,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,UAAC,WAAW;YACpC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QACjC,CAAC,CAAC,CAAA;IACJ,CAAC;IACH,uBAAC;AAAD,CAAC,AAtCD,CAGU,yBAAW,GAmCpB;AAtCY,4CAAgB"}
@@ -0,0 +1,49 @@
1
+ import { Debugger } from 'debug';
2
+ import { AsyncEventEmitter } from './utils/AsyncEventEmitter';
3
+ export declare type InterceptorEventMap = Record<string, (...args: any[]) => void>;
4
+ export declare type InterceptorSubscription = () => void;
5
+ export declare function getGlobalSymbol<V>(symbol: Symbol): V | undefined;
6
+ export declare function deleteGlobalSymbol(symbol: Symbol): void;
7
+ export declare enum InterceptorReadyState {
8
+ IDLE = "IDLE",
9
+ APPLYING = "APPLYING",
10
+ APPLIED = "APPLIED",
11
+ DISPOSING = "DISPOSING",
12
+ DISPOSED = "DISPOSED"
13
+ }
14
+ export declare type ExtractEventNames<EventMap extends Record<string, any>> = EventMap extends Record<infer EventName, any> ? EventName : never;
15
+ export declare class Interceptor<EventMap extends InterceptorEventMap> {
16
+ private readonly symbol;
17
+ protected emitter: AsyncEventEmitter<EventMap>;
18
+ protected subscriptions: InterceptorSubscription[];
19
+ protected log: Debugger;
20
+ readyState: InterceptorReadyState;
21
+ constructor(symbol: Symbol);
22
+ /**
23
+ * Determine if this interceptor can be applied
24
+ * in the current environment.
25
+ */
26
+ protected checkEnvironment(): boolean;
27
+ /**
28
+ * Apply this interceptor to the current process.
29
+ * Returns an already running interceptor instance if it's present.
30
+ */
31
+ apply(): void;
32
+ /**
33
+ * Setup the module augments and stubs necessary for this interceptor.
34
+ * This method is not run if there's a running interceptor instance
35
+ * to prevent instantiating an interceptor multiple times.
36
+ */
37
+ protected setup(): void;
38
+ /**
39
+ * Listen to the interceptor's public events.
40
+ */
41
+ on<Event extends ExtractEventNames<EventMap>>(event: Event, listener: EventMap[Event]): void;
42
+ /**
43
+ * Disposes of any side-effects this interceptor has introduced.
44
+ */
45
+ dispose(): void;
46
+ private getInstance;
47
+ private setInstance;
48
+ private clearInstance;
49
+ }
@@ -0,0 +1,197 @@
1
+ "use strict";
2
+ var __values = (this && this.__values) || function(o) {
3
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
4
+ if (m) return m.call(o);
5
+ if (o && typeof o.length === "number") return {
6
+ next: function () {
7
+ if (o && i >= o.length) o = void 0;
8
+ return { value: o && o[i++], done: !o };
9
+ }
10
+ };
11
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.Interceptor = exports.InterceptorReadyState = exports.deleteGlobalSymbol = exports.getGlobalSymbol = void 0;
15
+ var debug_1 = require("debug");
16
+ var AsyncEventEmitter_1 = require("./utils/AsyncEventEmitter");
17
+ var nextTick_1 = require("./utils/nextTick");
18
+ function getGlobalSymbol(symbol) {
19
+ return (
20
+ // @ts-ignore https://github.com/Microsoft/TypeScript/issues/24587
21
+ globalThis[symbol] || undefined);
22
+ }
23
+ exports.getGlobalSymbol = getGlobalSymbol;
24
+ function setGlobalSymbol(symbol, value) {
25
+ // @ts-ignore
26
+ globalThis[symbol] = value;
27
+ }
28
+ function deleteGlobalSymbol(symbol) {
29
+ // @ts-ignore
30
+ delete globalThis[symbol];
31
+ }
32
+ exports.deleteGlobalSymbol = deleteGlobalSymbol;
33
+ var InterceptorReadyState;
34
+ (function (InterceptorReadyState) {
35
+ InterceptorReadyState["IDLE"] = "IDLE";
36
+ InterceptorReadyState["APPLYING"] = "APPLYING";
37
+ InterceptorReadyState["APPLIED"] = "APPLIED";
38
+ InterceptorReadyState["DISPOSING"] = "DISPOSING";
39
+ InterceptorReadyState["DISPOSED"] = "DISPOSED";
40
+ })(InterceptorReadyState = exports.InterceptorReadyState || (exports.InterceptorReadyState = {}));
41
+ var Interceptor = /** @class */ (function () {
42
+ function Interceptor(symbol) {
43
+ this.symbol = symbol;
44
+ this.readyState = InterceptorReadyState.IDLE;
45
+ this.emitter = new AsyncEventEmitter_1.AsyncEventEmitter();
46
+ this.subscriptions = [];
47
+ this.log = debug_1.debug(symbol.description);
48
+ // Do not limit the maximum number of listeners
49
+ // so not to limit the maximum amount of parallel events emitted.
50
+ this.emitter.setMaxListeners(0);
51
+ this.log('constructing the interceptor...');
52
+ }
53
+ /**
54
+ * Determine if this interceptor can be applied
55
+ * in the current environment.
56
+ */
57
+ Interceptor.prototype.checkEnvironment = function () {
58
+ return true;
59
+ };
60
+ /**
61
+ * Apply this interceptor to the current process.
62
+ * Returns an already running interceptor instance if it's present.
63
+ */
64
+ Interceptor.prototype.apply = function () {
65
+ var _this = this;
66
+ var log = this.log.extend('apply');
67
+ log('applying the interceptor...');
68
+ if (this.readyState === InterceptorReadyState.APPLIED) {
69
+ log('intercepted already applied!');
70
+ return;
71
+ }
72
+ var shouldApply = this.checkEnvironment();
73
+ if (!shouldApply) {
74
+ log('the interceptor cannot be applied in this environment!');
75
+ return;
76
+ }
77
+ this.readyState = InterceptorReadyState.APPLYING;
78
+ // Always activate the emitter when applying the interceptor.
79
+ // This will ensure the interceptor can process events after it's
80
+ // been disposed and re-applied again (it may be a singleton).
81
+ this.emitter.activate();
82
+ log('activated the emiter!', this.emitter.readyState);
83
+ // Whenever applying a new interceptor, check if it hasn't been applied already.
84
+ // This enables to apply the same interceptor multiple times, for example from a different
85
+ // interceptor, only proxying events but keeping the stubs in a single place.
86
+ var runningInstance = this.getInstance();
87
+ if (runningInstance) {
88
+ log('found a running instance, reusing...');
89
+ // Proxy any listeners you set on this instance to the running instance.
90
+ this.on = function (event, listener) {
91
+ log('proxying the "%s" listener', event);
92
+ // Add listeners to the running instance so they appear
93
+ // at the top of the event listeners list and are executed first.
94
+ runningInstance.emitter.addListener(event, listener);
95
+ // Ensure that once this interceptor instance is disposed,
96
+ // it removes all listeners it has appended to the running interceptor instance.
97
+ _this.subscriptions.push(function () {
98
+ runningInstance.emitter.removeListener(event, listener);
99
+ log('removed proxied "%s" listener!', event);
100
+ });
101
+ };
102
+ nextTick_1.nextTick(function () {
103
+ _this.readyState = InterceptorReadyState.APPLIED;
104
+ });
105
+ return;
106
+ }
107
+ log('no running instance found, setting up a new instance...');
108
+ // Setup the interceptor.
109
+ this.setup();
110
+ // Store the newly applied interceptor instance globally.
111
+ this.setInstance();
112
+ nextTick_1.nextTick(function () {
113
+ _this.readyState = InterceptorReadyState.APPLIED;
114
+ });
115
+ };
116
+ /**
117
+ * Setup the module augments and stubs necessary for this interceptor.
118
+ * This method is not run if there's a running interceptor instance
119
+ * to prevent instantiating an interceptor multiple times.
120
+ */
121
+ Interceptor.prototype.setup = function () { };
122
+ /**
123
+ * Listen to the interceptor's public events.
124
+ */
125
+ Interceptor.prototype.on = function (event, listener) {
126
+ var log = this.log.extend('on');
127
+ if (this.readyState === InterceptorReadyState.DISPOSING ||
128
+ this.readyState === InterceptorReadyState.DISPOSED) {
129
+ log('cannot listen to events, already disposed!');
130
+ return;
131
+ }
132
+ log('adding "%s" event listener:', event, listener.name);
133
+ this.emitter.on(event, listener);
134
+ };
135
+ /**
136
+ * Disposes of any side-effects this interceptor has introduced.
137
+ */
138
+ Interceptor.prototype.dispose = function () {
139
+ var e_1, _a;
140
+ var _this = this;
141
+ var log = this.log.extend('dispose');
142
+ if (this.readyState === InterceptorReadyState.DISPOSED) {
143
+ log('cannot dispose, already disposed!');
144
+ return;
145
+ }
146
+ log('disposing the interceptor...');
147
+ this.readyState = InterceptorReadyState.DISPOSING;
148
+ if (!this.getInstance()) {
149
+ log('no interceptors running, skipping dispose...');
150
+ return;
151
+ }
152
+ // Delete the global symbol as soon as possible,
153
+ // indicating that the interceptor is no longer running.
154
+ this.clearInstance();
155
+ log('global symbol deleted:', getGlobalSymbol(this.symbol));
156
+ if (this.subscriptions.length > 0) {
157
+ log('disposing of %d subscriptions...', this.subscriptions.length);
158
+ try {
159
+ for (var _b = __values(this.subscriptions), _c = _b.next(); !_c.done; _c = _b.next()) {
160
+ var dispose = _c.value;
161
+ dispose();
162
+ }
163
+ }
164
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
165
+ finally {
166
+ try {
167
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
168
+ }
169
+ finally { if (e_1) throw e_1.error; }
170
+ }
171
+ this.subscriptions = [];
172
+ log('disposed of all subscriptions!', this.subscriptions.length);
173
+ }
174
+ this.emitter.deactivate();
175
+ log('destroyed the listener!');
176
+ nextTick_1.nextTick(function () {
177
+ _this.readyState = InterceptorReadyState.DISPOSED;
178
+ });
179
+ };
180
+ Interceptor.prototype.getInstance = function () {
181
+ var _a;
182
+ var instance = getGlobalSymbol(this.symbol);
183
+ this.log('retrieved global instance:', (_a = instance === null || instance === void 0 ? void 0 : instance.constructor) === null || _a === void 0 ? void 0 : _a.name);
184
+ return instance;
185
+ };
186
+ Interceptor.prototype.setInstance = function () {
187
+ setGlobalSymbol(this.symbol, this);
188
+ this.log('set global instance!', this.symbol.description);
189
+ };
190
+ Interceptor.prototype.clearInstance = function () {
191
+ deleteGlobalSymbol(this.symbol);
192
+ this.log('cleared global instance!', this.symbol.description);
193
+ };
194
+ return Interceptor;
195
+ }());
196
+ exports.Interceptor = Interceptor;
197
+ //# sourceMappingURL=Interceptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Interceptor.js","sourceRoot":"","sources":["../src/Interceptor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /// <reference types="node" />
2
+ import { ChildProcess } from 'child_process';
3
+ import type { HttpRequestEventMap } from './glossary';
4
+ import { Interceptor } from './Interceptor';
5
+ import { BatchInterceptor } from './BatchInterceptor';
6
+ import { ClientRequestInterceptor } from './interceptors/ClientRequest';
7
+ import { XMLHttpRequestInterceptor } from './interceptors/XMLHttpRequest';
8
+ export declare class RemoteHttpInterceptor extends BatchInterceptor<[
9
+ ClientRequestInterceptor,
10
+ XMLHttpRequestInterceptor
11
+ ]> {
12
+ constructor();
13
+ protected setup(): void;
14
+ }
15
+ export declare function requestReviver(key: string, value: any): any;
16
+ export interface RemoveResolverOptions {
17
+ process: ChildProcess;
18
+ }
19
+ export declare class RemoteHttpResolver extends Interceptor<HttpRequestEventMap> {
20
+ static symbol: symbol;
21
+ private process;
22
+ constructor(options: RemoveResolverOptions);
23
+ protected setup(): void;
24
+ }