@mswjs/interceptors 0.12.5 → 0.13.1
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/README.md +64 -15
- package/lib/createInterceptor.d.ts +7 -0
- package/lib/createInterceptor.js.map +1 -1
- package/lib/interceptors/ClientRequest/NodeClientRequest.d.ts +38 -0
- package/lib/interceptors/ClientRequest/NodeClientRequest.js +420 -0
- package/lib/interceptors/ClientRequest/NodeClientRequest.js.map +1 -0
- package/lib/interceptors/ClientRequest/http.get.d.ts +5 -0
- package/lib/interceptors/ClientRequest/http.get.js +47 -0
- package/lib/interceptors/ClientRequest/http.get.js.map +1 -0
- package/lib/interceptors/ClientRequest/http.request.d.ts +5 -0
- package/lib/interceptors/ClientRequest/http.request.js +44 -0
- package/lib/interceptors/ClientRequest/http.request.js.map +1 -0
- package/lib/interceptors/ClientRequest/index.d.ts +5 -1
- package/lib/interceptors/ClientRequest/index.js +50 -84
- package/lib/interceptors/ClientRequest/index.js.map +1 -1
- package/lib/interceptors/ClientRequest/utils/cloneIncomingMessage.d.ts +7 -0
- package/lib/interceptors/ClientRequest/utils/cloneIncomingMessage.js +77 -0
- package/lib/interceptors/ClientRequest/utils/cloneIncomingMessage.js.map +1 -0
- package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.d.ts +1 -1
- package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js +21 -12
- package/lib/interceptors/ClientRequest/utils/getIncomingMessageBody.js.map +1 -1
- package/lib/interceptors/ClientRequest/utils/normalizeClientRequestArgs.d.ts +17 -0
- package/lib/interceptors/ClientRequest/utils/{normalizeHttpRequestParams.js → normalizeClientRequestArgs.js} +65 -39
- package/lib/interceptors/ClientRequest/utils/normalizeClientRequestArgs.js.map +1 -0
- package/lib/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.d.ts +15 -0
- package/lib/interceptors/ClientRequest/utils/{normalizeHttpRequestEndParams.js → normalizeClientRequestEndArgs.js} +5 -6
- package/lib/interceptors/ClientRequest/utils/normalizeClientRequestEndArgs.js.map +1 -0
- package/lib/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.d.ts +13 -0
- package/lib/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.js +20 -0
- package/lib/interceptors/ClientRequest/utils/normalizeClientRequestWriteArgs.js.map +1 -0
- package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js +4 -3
- package/lib/interceptors/XMLHttpRequest/XMLHttpRequestOverride.js.map +1 -1
- package/lib/interceptors/fetch/index.js +6 -4
- package/lib/interceptors/fetch/index.js.map +1 -1
- package/lib/utils/getUrlByRequestOptions.d.ts +5 -4
- package/lib/utils/getUrlByRequestOptions.js.map +1 -1
- package/package.json +34 -20
- package/lib/interceptors/ClientRequest/ClientRequest.glossary.d.ts +0 -6
- package/lib/interceptors/ClientRequest/ClientRequest.glossary.js +0 -3
- package/lib/interceptors/ClientRequest/ClientRequest.glossary.js.map +0 -1
- package/lib/interceptors/ClientRequest/createClientRequestOverride.d.ts +0 -12
- package/lib/interceptors/ClientRequest/createClientRequestOverride.js +0 -340
- package/lib/interceptors/ClientRequest/createClientRequestOverride.js.map +0 -1
- package/lib/interceptors/ClientRequest/polyfills/SocketPolyfill.d.ts +0 -49
- package/lib/interceptors/ClientRequest/polyfills/SocketPolyfill.js +0 -118
- package/lib/interceptors/ClientRequest/polyfills/SocketPolyfill.js.map +0 -1
- package/lib/interceptors/ClientRequest/utils/inheritRequestHeaders.d.ts +0 -3
- package/lib/interceptors/ClientRequest/utils/inheritRequestHeaders.js +0 -34
- package/lib/interceptors/ClientRequest/utils/inheritRequestHeaders.js.map +0 -1
- package/lib/interceptors/ClientRequest/utils/normalizeHttpRequestEndParams.d.ts +0 -17
- package/lib/interceptors/ClientRequest/utils/normalizeHttpRequestEndParams.js.map +0 -1
- package/lib/interceptors/ClientRequest/utils/normalizeHttpRequestParams.d.ts +0 -11
- package/lib/interceptors/ClientRequest/utils/normalizeHttpRequestParams.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
[](https://www.npmjs.com/package/@mswjs/interceptors)
|
|
2
|
-
[](https://app.circleci.com/pipelines/github/mswjs/interceptors)
|
|
3
2
|
|
|
4
3
|
# `@mswjs/interceptors`
|
|
5
4
|
|
|
@@ -11,7 +10,7 @@ Low-level HTTP/HTTPS/XHR/fetch request interception library.
|
|
|
11
10
|
- `https.get`/`https.request`
|
|
12
11
|
- `XMLHttpRequest`
|
|
13
12
|
- `fetch`
|
|
14
|
-
- Any third-party libraries that use the modules above (i.e. `request`, `node-fetch`, etc.)
|
|
13
|
+
- Any third-party libraries that use the modules above (i.e. `request`, `node-fetch`, `supertest`, etc.)
|
|
15
14
|
|
|
16
15
|
## Motivation
|
|
17
16
|
|
|
@@ -21,24 +20,74 @@ This library is a strip-to-bone implementation that provides as little abstracti
|
|
|
21
20
|
|
|
22
21
|
### How is this library different?
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
A traditional API mocking implementation in Node.js looks roughly like this:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
import http from 'http'
|
|
27
|
+
|
|
28
|
+
function applyMock() {
|
|
29
|
+
// Store the original request module.
|
|
30
|
+
const originalHttpRequest = http.request
|
|
31
|
+
|
|
32
|
+
// Rewrite the request module entirely.
|
|
33
|
+
http.request = function (...args) {
|
|
34
|
+
// Decide whether to handle this request before
|
|
35
|
+
// the actual request happens.
|
|
36
|
+
if (shouldMock(args)) {
|
|
37
|
+
// If so, never create a request, respond to it
|
|
38
|
+
// using the mocked response from this blackbox.
|
|
39
|
+
return coerceToResponse.bind(this, mock)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Otherwise, construct the original request
|
|
43
|
+
// and perform it as-is (receives the original response).
|
|
44
|
+
return originalHttpRequest(...args)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
This library deviates from such implementation and uses _class extensions_ instead of module rewrites. Such deviation is necessary because, unlike other solutions that include request matching and can determine whether to mock requests _before_ they actually happen, this library is not opinionated about the mocked/bypassed nature of the requests. Instead, it _intercepts all requests_ and delegates the decision of mocking to the end consumer.
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
class NodeClientRequest extends ClientRequest {
|
|
53
|
+
async end(...args) {
|
|
54
|
+
// Check if there's a mocked response for this request.
|
|
55
|
+
// You control this in the "resolver" function.
|
|
56
|
+
const mockedResponse = await resolver(isomorphicRequest)
|
|
57
|
+
|
|
58
|
+
// If there is a mocked response, use it to respond to this
|
|
59
|
+
// request, finalizing it afterward as if it received that
|
|
60
|
+
// response from the actual server it connected to.
|
|
61
|
+
if (mockedResponse) {
|
|
62
|
+
this.respondWith(mockedResponse)
|
|
63
|
+
this.finish()
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Otherwise, perform the original "ClientRequest.prototype.end" call.
|
|
68
|
+
return super.end(...args)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
By extending the native modules, this library actually constructs requests as soon as they are constructed by the consumer. This enables all the request input validation and transformations done natively by Node.js—something that traditional solutions simply cannot do (they replace `http.ClientRequest` entirely). The class extension allows to fully utilize Node.js internals instead of polyfilling them, which results in more resilient mocks.
|
|
25
74
|
|
|
26
75
|
## What this library does
|
|
27
76
|
|
|
28
|
-
This library
|
|
77
|
+
This library extends (or patches, where applicable) the following native modules:
|
|
29
78
|
|
|
30
79
|
- `http.get`/`http.request`
|
|
31
80
|
- `https.get`/`https.request`
|
|
32
81
|
- `XMLHttpRequest`
|
|
33
82
|
- `fetch`
|
|
34
83
|
|
|
35
|
-
Once
|
|
84
|
+
Once extended, it intercepts and normalizes all requests to the _isomorphic request instances_. The isomorphic request is an abstract representation of the request coming from different sources (`ClientRequest`, `XMLHttpRequest`, `window.Request`, etc.) that allows us to handle such requests in the same, unified manner.
|
|
36
85
|
|
|
37
|
-
|
|
86
|
+
You can respond to an isomorphic request using an _isomorphic response_. In a similar way, the isomorphic response is a representation of the response to use for different requests. Responding to requests differs substantially when using modules like `http` or `XMLHttpRequest`. This library takes the responsibility for coercing isomorphic responses into appropriate responses depending on the request module automatically.
|
|
38
87
|
|
|
39
88
|
## What this library doesn't do
|
|
40
89
|
|
|
41
|
-
- Does **not** provide any request matching logic
|
|
90
|
+
- Does **not** provide any request matching logic;
|
|
42
91
|
- Does **not** decide how to handle requests.
|
|
43
92
|
|
|
44
93
|
## Getting started
|
|
@@ -108,15 +157,15 @@ createRemoteResolver({
|
|
|
108
157
|
|
|
109
158
|
### Interceptors
|
|
110
159
|
|
|
111
|
-
This library utilizes a concept of _interceptors_–functions that
|
|
160
|
+
This library utilizes a concept of _interceptors_–functions that extend request modules, handle mocked responses, and restore themselves when done.
|
|
112
161
|
|
|
113
|
-
**
|
|
162
|
+
**Available interceptors:**
|
|
114
163
|
|
|
115
164
|
- `/interceptors/ClientRequest`
|
|
116
165
|
- `/interceptors/XMLHttpRequest`
|
|
117
166
|
- `/interceptors/fetch`
|
|
118
167
|
|
|
119
|
-
To use a single, or multiple interceptors, import and provide them to the `
|
|
168
|
+
To use a single, or multiple interceptors, import and provide them to the `createInterceptor` function.
|
|
120
169
|
|
|
121
170
|
```js
|
|
122
171
|
import { createInterceptor } from '@mswjs/interceptors'
|
|
@@ -124,12 +173,12 @@ import { interceptXMLHttpRequest } from '@mswjs/interceptors/lib/interceptors/XM
|
|
|
124
173
|
|
|
125
174
|
// This `interceptor` instance would handle only XMLHttpRequest,
|
|
126
175
|
// ignoring requests issued via `http`/`https` modules.
|
|
127
|
-
const interceptor =
|
|
176
|
+
const interceptor = createInterceptor({
|
|
128
177
|
modules: [interceptXMLHttpRequest],
|
|
129
178
|
})
|
|
130
179
|
```
|
|
131
180
|
|
|
132
|
-
> 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
|
|
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.
|
|
133
182
|
|
|
134
183
|
### Methods
|
|
135
184
|
|
|
@@ -145,8 +194,8 @@ interceptor.apply()
|
|
|
145
194
|
|
|
146
195
|
Adds an event listener to one of the following supported events:
|
|
147
196
|
|
|
148
|
-
- `request`,
|
|
149
|
-
- `response`,
|
|
197
|
+
- `request`, signals when a new request happens;
|
|
198
|
+
- `response`, signals when a response was sent.
|
|
150
199
|
|
|
151
200
|
```js
|
|
152
201
|
interceptor.on('request', (request) => {
|
|
@@ -156,7 +205,7 @@ interceptor.on('request', (request) => {
|
|
|
156
205
|
|
|
157
206
|
#### `.restore(): void`
|
|
158
207
|
|
|
159
|
-
Restores all
|
|
208
|
+
Restores all extensions and stops the interception of future requests.
|
|
160
209
|
|
|
161
210
|
```js
|
|
162
211
|
interceptor.restore()
|
|
@@ -8,11 +8,18 @@ export declare type Observer = StrictEventEmitter<InterceptorEventsMap>;
|
|
|
8
8
|
* A side-effect function to restore all the patched modules.
|
|
9
9
|
*/
|
|
10
10
|
export declare type InterceptorCleanupFn = () => void;
|
|
11
|
+
export declare type RequestCredentials = 'omit' | 'include' | 'same-origin';
|
|
11
12
|
export interface IsomorphicRequest {
|
|
12
13
|
id: string;
|
|
13
14
|
url: URL;
|
|
14
15
|
method: string;
|
|
15
16
|
headers: Headers;
|
|
17
|
+
/**
|
|
18
|
+
* The value of the request client's "credentials" option
|
|
19
|
+
* or a compatible alternative (i.e. `withCredentials` for `XMLHttpRequest`).
|
|
20
|
+
* Always equals to "omit" in Node.js.
|
|
21
|
+
*/
|
|
22
|
+
credentials: RequestCredentials;
|
|
16
23
|
body?: string;
|
|
17
24
|
}
|
|
18
25
|
export interface IsomorphicResponse {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createInterceptor.js","sourceRoot":"","sources":["../src/createInterceptor.ts"],"names":[],"mappings":";;;AAEA,6DAAyD;
|
|
1
|
+
{"version":3,"file":"createInterceptor.js","sourceRoot":"","sources":["../src/createInterceptor.ts"],"names":[],"mappings":";;;AAEA,6DAAyD;AAwEzD,SAAgB,iBAAiB,CAAC,OAA2B;IAC3D,IAAM,QAAQ,GAAG,IAAI,yCAAkB,EAAwB,CAAA;IAC/D,IAAI,UAAU,GAA2B,EAAE,CAAA;IAE3C,OAAO;QACL,KAAK;YACH,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,UAAC,WAAW;gBAC3C,OAAO,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAA;YAChD,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,EAAE,YAAC,KAAK,EAAE,QAAQ;YAChB,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QACvC,CAAC;QACD,OAAO;YACL,QAAQ,CAAC,kBAAkB,EAAE,CAAA;YAE7B,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC3B,MAAM,IAAI,KAAK,CACb,0FAAwF,CACzF,CAAA;aACF;YAED,UAAU,CAAC,OAAO,CAAC,UAAC,OAAO,IAAK,OAAA,OAAO,EAAE,EAAT,CAAS,CAAC,CAAA;QAC5C,CAAC;KACF,CAAA;AACH,CAAC;AAzBD,8CAyBC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { ClientRequest } from 'http';
|
|
3
|
+
import type { Observer, Resolver } from '../../createInterceptor';
|
|
4
|
+
import { NormalizedClientRequestArgs } from './utils/normalizeClientRequestArgs';
|
|
5
|
+
import { ClientRequestWriteArgs } from './utils/normalizeClientRequestWriteArgs';
|
|
6
|
+
export declare type Protocol = 'http' | 'https';
|
|
7
|
+
export interface NodeClientOptions {
|
|
8
|
+
observer: Observer;
|
|
9
|
+
resolver: Resolver;
|
|
10
|
+
}
|
|
11
|
+
export declare class NodeClientRequest extends ClientRequest {
|
|
12
|
+
/**
|
|
13
|
+
* The list of internal Node.js errors to suppress while
|
|
14
|
+
* using the "mock" response source.
|
|
15
|
+
*/
|
|
16
|
+
static suppressErrorCodes: string[];
|
|
17
|
+
private url;
|
|
18
|
+
private options;
|
|
19
|
+
private response;
|
|
20
|
+
private resolver;
|
|
21
|
+
private observer;
|
|
22
|
+
private log;
|
|
23
|
+
private chunks;
|
|
24
|
+
private responseSource;
|
|
25
|
+
private capturedError?;
|
|
26
|
+
requestBody: Buffer[];
|
|
27
|
+
constructor([url, requestOptions, callback]: NormalizedClientRequestArgs, options: NodeClientOptions);
|
|
28
|
+
write(...args: ClientRequestWriteArgs): boolean;
|
|
29
|
+
end(...args: any): Promise<void>;
|
|
30
|
+
emit(event: string, ...data: any[]): boolean;
|
|
31
|
+
private respondWith;
|
|
32
|
+
/**
|
|
33
|
+
* Terminates a pending request.
|
|
34
|
+
*/
|
|
35
|
+
private terminate;
|
|
36
|
+
private getRequestBody;
|
|
37
|
+
private toIsomorphicRequest;
|
|
38
|
+
}
|
|
@@ -0,0 +1,420 @@
|
|
|
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 __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
18
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
19
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
20
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
21
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
22
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
23
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
27
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
28
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
29
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
30
|
+
function step(op) {
|
|
31
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
32
|
+
while (_) try {
|
|
33
|
+
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;
|
|
34
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
35
|
+
switch (op[0]) {
|
|
36
|
+
case 0: case 1: t = op; break;
|
|
37
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
38
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
39
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
40
|
+
default:
|
|
41
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
42
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
43
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
44
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
45
|
+
if (t[2]) _.ops.pop();
|
|
46
|
+
_.trys.pop(); continue;
|
|
47
|
+
}
|
|
48
|
+
op = body.call(thisArg, _);
|
|
49
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
50
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
54
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
55
|
+
if (!m) return o;
|
|
56
|
+
var i = m.call(o), r, ar = [], e;
|
|
57
|
+
try {
|
|
58
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
59
|
+
}
|
|
60
|
+
catch (error) { e = { error: error }; }
|
|
61
|
+
finally {
|
|
62
|
+
try {
|
|
63
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
64
|
+
}
|
|
65
|
+
finally { if (e) throw e.error; }
|
|
66
|
+
}
|
|
67
|
+
return ar;
|
|
68
|
+
};
|
|
69
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
|
|
70
|
+
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
|
|
71
|
+
to[j] = from[i];
|
|
72
|
+
return to;
|
|
73
|
+
};
|
|
74
|
+
var __values = (this && this.__values) || function(o) {
|
|
75
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
76
|
+
if (m) return m.call(o);
|
|
77
|
+
if (o && typeof o.length === "number") return {
|
|
78
|
+
next: function () {
|
|
79
|
+
if (o && i >= o.length) o = void 0;
|
|
80
|
+
return { value: o && o[i++], done: !o };
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
84
|
+
};
|
|
85
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
86
|
+
exports.NodeClientRequest = void 0;
|
|
87
|
+
var debug_1 = require("debug");
|
|
88
|
+
var http_1 = require("http");
|
|
89
|
+
var until_1 = require("@open-draft/until");
|
|
90
|
+
var lib_1 = require("headers-utils/lib");
|
|
91
|
+
var uuid_1 = require("../../utils/uuid");
|
|
92
|
+
var concatChunkToBuffer_1 = require("./utils/concatChunkToBuffer");
|
|
93
|
+
var normalizeClientRequestEndArgs_1 = require("./utils/normalizeClientRequestEndArgs");
|
|
94
|
+
var toIsoResponse_1 = require("../../utils/toIsoResponse");
|
|
95
|
+
var getIncomingMessageBody_1 = require("./utils/getIncomingMessageBody");
|
|
96
|
+
var bodyBufferToString_1 = require("./utils/bodyBufferToString");
|
|
97
|
+
var normalizeClientRequestWriteArgs_1 = require("./utils/normalizeClientRequestWriteArgs");
|
|
98
|
+
var cloneIncomingMessage_1 = require("./utils/cloneIncomingMessage");
|
|
99
|
+
var NodeClientRequest = /** @class */ (function (_super) {
|
|
100
|
+
__extends(NodeClientRequest, _super);
|
|
101
|
+
function NodeClientRequest(_a, options) {
|
|
102
|
+
var _b = __read(_a, 3), url = _b[0], requestOptions = _b[1], callback = _b[2];
|
|
103
|
+
var _this = _super.call(this, requestOptions, callback) || this;
|
|
104
|
+
_this.chunks = [];
|
|
105
|
+
_this.responseSource = 'mock';
|
|
106
|
+
_this.requestBody = [];
|
|
107
|
+
_this.log = debug_1.debug("http " + requestOptions.method + " " + url.href);
|
|
108
|
+
_this.log('constructing ClientRequest...', {
|
|
109
|
+
url: url,
|
|
110
|
+
requestOptions: requestOptions,
|
|
111
|
+
callback: callback,
|
|
112
|
+
});
|
|
113
|
+
_this.url = url;
|
|
114
|
+
_this.options = requestOptions;
|
|
115
|
+
_this.resolver = options.resolver;
|
|
116
|
+
_this.observer = options.observer;
|
|
117
|
+
// Construct a mocked response message.
|
|
118
|
+
_this.response = new http_1.IncomingMessage(_this.socket);
|
|
119
|
+
return _this;
|
|
120
|
+
}
|
|
121
|
+
NodeClientRequest.prototype.write = function () {
|
|
122
|
+
var _this = this;
|
|
123
|
+
var args = [];
|
|
124
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
125
|
+
args[_i] = arguments[_i];
|
|
126
|
+
}
|
|
127
|
+
var _a = __read(normalizeClientRequestWriteArgs_1.normalizeClientRequestWriteArgs(args), 3), chunk = _a[0], encoding = _a[1], callback = _a[2];
|
|
128
|
+
this.log('write:', { chunk: chunk, encoding: encoding, callback: callback });
|
|
129
|
+
this.chunks.push({
|
|
130
|
+
chunk: chunk,
|
|
131
|
+
encoding: encoding,
|
|
132
|
+
callback: function (error) {
|
|
133
|
+
if (error) {
|
|
134
|
+
_this.log('error while writing chunk!', error);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
_this.log('request chunk successfully written!');
|
|
138
|
+
}
|
|
139
|
+
callback === null || callback === void 0 ? void 0 : callback(error);
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
this.log('chunk successfully stored!');
|
|
143
|
+
this.requestBody = concatChunkToBuffer_1.concatChunkToBuffer(chunk, this.requestBody);
|
|
144
|
+
// Do not write the request body chunks to prevent
|
|
145
|
+
// the Socket from sending data to a potentially existing
|
|
146
|
+
// server when there is a mocked response defined.
|
|
147
|
+
return true;
|
|
148
|
+
};
|
|
149
|
+
NodeClientRequest.prototype.end = function () {
|
|
150
|
+
var args = [];
|
|
151
|
+
for (var _i = 0; _i < arguments.length; _i++) {
|
|
152
|
+
args[_i] = arguments[_i];
|
|
153
|
+
}
|
|
154
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
155
|
+
var _a, chunk, encoding, callback, requestBody, isomorphicRequest, _b, resolverError, mockedResponse, isomorphicResponse, _c, _d, _e, chunk_1, encoding_1, callback_1;
|
|
156
|
+
var e_1, _f;
|
|
157
|
+
var _this = this;
|
|
158
|
+
return __generator(this, function (_g) {
|
|
159
|
+
switch (_g.label) {
|
|
160
|
+
case 0:
|
|
161
|
+
this.log('end', args);
|
|
162
|
+
_a = __read(normalizeClientRequestEndArgs_1.normalizeClientRequestEndArgs.apply(void 0, __spreadArray([], __read(args))), 3), chunk = _a[0], encoding = _a[1], callback = _a[2];
|
|
163
|
+
this.log('normalized arguments:', { chunk: chunk, encoding: encoding, callback: callback });
|
|
164
|
+
requestBody = this.getRequestBody(chunk);
|
|
165
|
+
isomorphicRequest = this.toIsomorphicRequest(requestBody);
|
|
166
|
+
this.observer.emit('request', isomorphicRequest);
|
|
167
|
+
this.log('executing response resolver...');
|
|
168
|
+
return [4 /*yield*/, until_1.until(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
169
|
+
return [2 /*return*/, this.resolver(isomorphicRequest, this.response)];
|
|
170
|
+
}); }); })
|
|
171
|
+
// Halt the request whenever the resolver throws an exception.
|
|
172
|
+
];
|
|
173
|
+
case 1:
|
|
174
|
+
_b = __read.apply(void 0, [_g.sent()
|
|
175
|
+
// Halt the request whenever the resolver throws an exception.
|
|
176
|
+
, 2]), resolverError = _b[0], mockedResponse = _b[1];
|
|
177
|
+
// Halt the request whenever the resolver throws an exception.
|
|
178
|
+
if (resolverError) {
|
|
179
|
+
this.log('encountered resolver exception, aborting request...', resolverError);
|
|
180
|
+
this.emit('error', resolverError);
|
|
181
|
+
this.terminate();
|
|
182
|
+
return [2 /*return*/];
|
|
183
|
+
}
|
|
184
|
+
if (mockedResponse) {
|
|
185
|
+
this.log('received mocked response:', mockedResponse);
|
|
186
|
+
this.responseSource = 'mock';
|
|
187
|
+
isomorphicResponse = toIsoResponse_1.toIsoResponse(mockedResponse);
|
|
188
|
+
this.respondWith(mockedResponse);
|
|
189
|
+
this.log(isomorphicResponse.status, isomorphicResponse.statusText, isomorphicResponse.body, '(MOCKED)');
|
|
190
|
+
callback === null || callback === void 0 ? void 0 : callback();
|
|
191
|
+
this.observer.emit('response', isomorphicRequest, isomorphicResponse);
|
|
192
|
+
return [2 /*return*/];
|
|
193
|
+
}
|
|
194
|
+
this.log('no mocked response found!');
|
|
195
|
+
// Set the response source to "bypass".
|
|
196
|
+
// Any errors emitted past this point are not suppressed.
|
|
197
|
+
this.responseSource = 'bypass';
|
|
198
|
+
// Propagate previously captured errors.
|
|
199
|
+
// For example, a ECONNREFUSED error when connecting to a non-existing host.
|
|
200
|
+
if (this.capturedError) {
|
|
201
|
+
this.emit('error', this.capturedError);
|
|
202
|
+
return [2 /*return*/];
|
|
203
|
+
}
|
|
204
|
+
// Write the request body chunks in the order of ".write()" calls.
|
|
205
|
+
// Note that no request body has been written prior to this point
|
|
206
|
+
// in order to prevent the Socket to communicate with a potentially
|
|
207
|
+
// existing server.
|
|
208
|
+
this.log('writing request chunks...', this.chunks);
|
|
209
|
+
try {
|
|
210
|
+
for (_c = __values(this.chunks), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
211
|
+
_e = _d.value, chunk_1 = _e.chunk, encoding_1 = _e.encoding, callback_1 = _e.callback;
|
|
212
|
+
encoding_1
|
|
213
|
+
? _super.prototype.write.call(this, chunk_1, encoding_1, callback_1)
|
|
214
|
+
: _super.prototype.write.call(this, chunk_1, callback_1);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
218
|
+
finally {
|
|
219
|
+
try {
|
|
220
|
+
if (_d && !_d.done && (_f = _c.return)) _f.call(_c);
|
|
221
|
+
}
|
|
222
|
+
finally { if (e_1) throw e_1.error; }
|
|
223
|
+
}
|
|
224
|
+
this.once('error', function (error) {
|
|
225
|
+
_this.log('original request error:', error);
|
|
226
|
+
});
|
|
227
|
+
this.once('abort', function () {
|
|
228
|
+
_this.log('original request aborted!');
|
|
229
|
+
});
|
|
230
|
+
this.once('response-internal', function (response) { return __awaiter(_this, void 0, void 0, function () {
|
|
231
|
+
var responseBody;
|
|
232
|
+
return __generator(this, function (_a) {
|
|
233
|
+
switch (_a.label) {
|
|
234
|
+
case 0: return [4 /*yield*/, getIncomingMessageBody_1.getIncomingMessageBody(response)];
|
|
235
|
+
case 1:
|
|
236
|
+
responseBody = _a.sent();
|
|
237
|
+
this.log(response.statusCode, response.statusMessage, responseBody);
|
|
238
|
+
this.log('original response headers:', response.headers);
|
|
239
|
+
this.observer.emit('response', isomorphicRequest, {
|
|
240
|
+
status: response.statusCode || 200,
|
|
241
|
+
statusText: response.statusMessage || 'OK',
|
|
242
|
+
headers: lib_1.objectToHeaders(response.headers),
|
|
243
|
+
body: responseBody,
|
|
244
|
+
});
|
|
245
|
+
return [2 /*return*/];
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}); });
|
|
249
|
+
this.log('performing original request...');
|
|
250
|
+
return [2 /*return*/, _super.prototype.end.apply(this, __spreadArray([], __read([
|
|
251
|
+
chunk,
|
|
252
|
+
encoding,
|
|
253
|
+
function () {
|
|
254
|
+
_this.log('original request end!');
|
|
255
|
+
callback === null || callback === void 0 ? void 0 : callback();
|
|
256
|
+
},
|
|
257
|
+
].filter(Boolean))))];
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
};
|
|
262
|
+
NodeClientRequest.prototype.emit = function (event) {
|
|
263
|
+
var data = [];
|
|
264
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
265
|
+
data[_i - 1] = arguments[_i];
|
|
266
|
+
}
|
|
267
|
+
this.log('event:%s', event);
|
|
268
|
+
if (event === 'response') {
|
|
269
|
+
this.log('found "response" event, cloning the response...');
|
|
270
|
+
try {
|
|
271
|
+
/**
|
|
272
|
+
* Clone the response object when emitting the "response" event.
|
|
273
|
+
* This prevents the response body stream from locking
|
|
274
|
+
* and allows reading it twice:
|
|
275
|
+
* 1. Internal "response" event from the observer.
|
|
276
|
+
* 2. Any external response body listeners.
|
|
277
|
+
* @see https://github.com/mswjs/interceptors/issues/161
|
|
278
|
+
*/
|
|
279
|
+
var response = data[0];
|
|
280
|
+
var firstClone = cloneIncomingMessage_1.cloneIncomingMessage(response);
|
|
281
|
+
var secondClone = cloneIncomingMessage_1.cloneIncomingMessage(response);
|
|
282
|
+
this.emit('response-internal', secondClone);
|
|
283
|
+
this.log('response successfuly cloned, emitting "response" event...');
|
|
284
|
+
return _super.prototype.emit.apply(this, __spreadArray([event, firstClone], __read(data.slice(1))));
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
this.log('error when cloning response:', error);
|
|
288
|
+
return _super.prototype.emit.apply(this, __spreadArray([event], __read(data)));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (event === 'error') {
|
|
292
|
+
var error = data[0];
|
|
293
|
+
var errorCode = error.code || '';
|
|
294
|
+
this.log('error:\n', error);
|
|
295
|
+
// Supress certain errors while using the "mock" source.
|
|
296
|
+
// For example, no need to destroy this request if it connects
|
|
297
|
+
// to a non-existing hostname but has a mocked response.
|
|
298
|
+
if (this.responseSource === 'mock' &&
|
|
299
|
+
NodeClientRequest.suppressErrorCodes.includes(errorCode)) {
|
|
300
|
+
// Capture the first emitted error in order to replay
|
|
301
|
+
// it later if this request won't have any mocked response.
|
|
302
|
+
if (!this.capturedError) {
|
|
303
|
+
this.capturedError = error;
|
|
304
|
+
}
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return _super.prototype.emit.apply(this, __spreadArray([event], __read(data)));
|
|
309
|
+
};
|
|
310
|
+
NodeClientRequest.prototype.respondWith = function (mockedResponse) {
|
|
311
|
+
var e_2, _a, _b;
|
|
312
|
+
this.log('responding with a mocked response...', mockedResponse);
|
|
313
|
+
var status = mockedResponse.status, statusText = mockedResponse.statusText, headers = mockedResponse.headers, body = mockedResponse.body;
|
|
314
|
+
this.response.statusCode = status;
|
|
315
|
+
this.response.statusMessage = statusText;
|
|
316
|
+
if (headers) {
|
|
317
|
+
this.response.headers = {};
|
|
318
|
+
try {
|
|
319
|
+
for (var _c = __values(Object.entries(headers)), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
320
|
+
var _e = __read(_d.value, 2), headerName = _e[0], headerValue = _e[1];
|
|
321
|
+
(_b = this.response.rawHeaders).push.apply(_b, __spreadArray([headerName], __read((Array.isArray(headerValue) ? headerValue : [headerValue]))));
|
|
322
|
+
var insensitiveHeaderName = headerName.toLowerCase();
|
|
323
|
+
var prevHeaders = this.response.headers[insensitiveHeaderName];
|
|
324
|
+
this.response.headers[insensitiveHeaderName] = prevHeaders
|
|
325
|
+
? Array.prototype.concat([], prevHeaders, headerValue)
|
|
326
|
+
: headerValue;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
330
|
+
finally {
|
|
331
|
+
try {
|
|
332
|
+
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
333
|
+
}
|
|
334
|
+
finally { if (e_2) throw e_2.error; }
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
this.log('mocked response headers ready:', headers);
|
|
338
|
+
if (body) {
|
|
339
|
+
this.response.push(Buffer.from(body));
|
|
340
|
+
}
|
|
341
|
+
// Push "null" to indicate that the response body is complete
|
|
342
|
+
// and shouldn't be written to anymore.
|
|
343
|
+
this.response.push(null);
|
|
344
|
+
this.response.complete = true;
|
|
345
|
+
/**
|
|
346
|
+
* Set the internal "res" property to the mocked "OutgoingMessage"
|
|
347
|
+
* to make the "ClientRequest" instance think there's data received
|
|
348
|
+
* from the socket.
|
|
349
|
+
* @see https://github.com/nodejs/node/blob/9c405f2591f5833d0247ed0fafdcd68c5b14ce7a/lib/_http_client.js#L501
|
|
350
|
+
*/
|
|
351
|
+
// @ts-ignore
|
|
352
|
+
this.res = this.response;
|
|
353
|
+
this.finished = true;
|
|
354
|
+
Object.defineProperty(this, 'writableEnded', {
|
|
355
|
+
value: true,
|
|
356
|
+
});
|
|
357
|
+
this.emit('finish');
|
|
358
|
+
this.emit('response', this.response);
|
|
359
|
+
this.terminate();
|
|
360
|
+
};
|
|
361
|
+
/**
|
|
362
|
+
* Terminates a pending request.
|
|
363
|
+
*/
|
|
364
|
+
NodeClientRequest.prototype.terminate = function () {
|
|
365
|
+
// @ts-ignore
|
|
366
|
+
this.agent.destroy();
|
|
367
|
+
};
|
|
368
|
+
NodeClientRequest.prototype.getRequestBody = function (chunk) {
|
|
369
|
+
var writtenRequestBody = bodyBufferToString_1.bodyBufferToString(Buffer.concat(this.requestBody));
|
|
370
|
+
this.log('written request body:', writtenRequestBody);
|
|
371
|
+
// Write the last request body chunk to the internal request body buffer.
|
|
372
|
+
if (chunk) {
|
|
373
|
+
this.requestBody = concatChunkToBuffer_1.concatChunkToBuffer(chunk, this.requestBody);
|
|
374
|
+
}
|
|
375
|
+
var resolvedRequestBody = bodyBufferToString_1.bodyBufferToString(Buffer.concat(this.requestBody));
|
|
376
|
+
this.log('resolved request body:', resolvedRequestBody);
|
|
377
|
+
return resolvedRequestBody;
|
|
378
|
+
};
|
|
379
|
+
NodeClientRequest.prototype.toIsomorphicRequest = function (body) {
|
|
380
|
+
var e_3, _a;
|
|
381
|
+
this.log('creating isomorphic request object...');
|
|
382
|
+
var outgoingHeaders = this.getHeaders();
|
|
383
|
+
this.log('request outgoing headers:', outgoingHeaders);
|
|
384
|
+
var headers = new lib_1.Headers();
|
|
385
|
+
try {
|
|
386
|
+
for (var _b = __values(Object.entries(outgoingHeaders)), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
387
|
+
var _d = __read(_c.value, 2), headerName = _d[0], headerValue = _d[1];
|
|
388
|
+
if (!headerValue) {
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
headers.set(headerName.toLowerCase(), headerValue.toString());
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
395
|
+
finally {
|
|
396
|
+
try {
|
|
397
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
398
|
+
}
|
|
399
|
+
finally { if (e_3) throw e_3.error; }
|
|
400
|
+
}
|
|
401
|
+
var isomorphicRequest = {
|
|
402
|
+
id: uuid_1.uuidv4(),
|
|
403
|
+
url: this.url,
|
|
404
|
+
method: this.options.method || 'GET',
|
|
405
|
+
credentials: 'omit',
|
|
406
|
+
headers: headers,
|
|
407
|
+
body: body,
|
|
408
|
+
};
|
|
409
|
+
this.log('successfully created isomorphic request!', isomorphicRequest);
|
|
410
|
+
return isomorphicRequest;
|
|
411
|
+
};
|
|
412
|
+
/**
|
|
413
|
+
* The list of internal Node.js errors to suppress while
|
|
414
|
+
* using the "mock" response source.
|
|
415
|
+
*/
|
|
416
|
+
NodeClientRequest.suppressErrorCodes = ['ENOTFOUND', 'ECONNREFUSED', 'ECONNRESET'];
|
|
417
|
+
return NodeClientRequest;
|
|
418
|
+
}(http_1.ClientRequest));
|
|
419
|
+
exports.NodeClientRequest = NodeClientRequest;
|
|
420
|
+
//# sourceMappingURL=NodeClientRequest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NodeClientRequest.js","sourceRoot":"","sources":["../../../src/interceptors/ClientRequest/NodeClientRequest.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+BAAuC;AAEvC,6BAAqD;AACrD,2CAAyC;AACzC,yCAA4D;AAO5D,yCAAyC;AACzC,mEAAiE;AACjE,uFAG8C;AAE9C,2DAAyD;AACzD,yEAAuE;AACvE,iEAA+D;AAC/D,2FAIgD;AAChD,qEAAmE;AASnE;IAAuC,qCAAa;IAuBlD,2BACE,EAA4D,EAC5D,OAA0B;YAD1B,KAAA,aAA4D,EAA3D,GAAG,QAAA,EAAE,cAAc,QAAA,EAAE,QAAQ,QAAA;QADhC,YAIE,kBAAM,cAAc,EAAE,QAAQ,CAAC,SAgBhC;QA9BO,YAAM,GAIT,EAAE,CAAA;QACC,oBAAc,GAAsB,MAAM,CAAA;QAG3C,iBAAW,GAAa,EAAE,CAAA;QAQ/B,KAAI,CAAC,GAAG,GAAG,aAAK,CAAC,UAAQ,cAAc,CAAC,MAAM,SAAI,GAAG,CAAC,IAAM,CAAC,CAAA;QAC7D,KAAI,CAAC,GAAG,CAAC,+BAA+B,EAAE;YACxC,GAAG,KAAA;YACH,cAAc,gBAAA;YACd,QAAQ,UAAA;SACT,CAAC,CAAA;QAEF,KAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,KAAI,CAAC,OAAO,GAAG,cAAc,CAAA;QAC7B,KAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;QAChC,KAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAA;QAEhC,uCAAuC;QACvC,KAAI,CAAC,QAAQ,GAAG,IAAI,sBAAe,CAAC,KAAI,CAAC,MAAO,CAAC,CAAA;;IACnD,CAAC;IAED,iCAAK,GAAL;QAAA,iBAyBC;QAzBK,cAA+B;aAA/B,UAA+B,EAA/B,qBAA+B,EAA/B,IAA+B;YAA/B,yBAA+B;;QAC7B,IAAA,KAAA,OAA8B,iEAA+B,CAAC,IAAI,CAAC,IAAA,EAAlE,KAAK,QAAA,EAAE,QAAQ,QAAA,EAAE,QAAQ,QAAyC,CAAA;QACzE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,KAAK,OAAA,EAAE,QAAQ,UAAA,EAAE,QAAQ,UAAA,EAAE,CAAC,CAAA;QAEjD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACf,KAAK,OAAA;YACL,QAAQ,UAAA;YACR,QAAQ,EAAE,UAAC,KAAoB;gBAC7B,IAAI,KAAK,EAAE;oBACT,KAAI,CAAC,GAAG,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAA;iBAC9C;qBAAM;oBACL,KAAI,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAA;iBAChD;gBAED,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAG,KAAK,CAAC,CAAA;YACnB,CAAC;SACF,CAAC,CAAA;QAEF,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;QACtC,IAAI,CAAC,WAAW,GAAG,yCAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;QAE/D,kDAAkD;QAClD,yDAAyD;QACzD,kDAAkD;QAClD,OAAO,IAAI,CAAA;IACb,CAAC;IAEK,+BAAG,GAAT;QAAU,cAAY;aAAZ,UAAY,EAAZ,qBAAY,EAAZ,IAAY;YAAZ,yBAAY;;;;;;;;;wBACpB,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;wBAEf,KAAA,OAA8B,6DAA6B,wCAAI,IAAI,OAAC,EAAnE,KAAK,QAAA,EAAE,QAAQ,QAAA,EAAE,QAAQ,QAAA,CAA0C;wBAC1E,IAAI,CAAC,GAAG,CAAC,uBAAuB,EAAE,EAAE,KAAK,OAAA,EAAE,QAAQ,UAAA,EAAE,QAAQ,UAAA,EAAE,CAAC,CAAA;wBAE1D,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;wBACxC,iBAAiB,GAAG,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAA;wBAC/D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAA;wBAEhD,IAAI,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAA;wBACF,qBAAM,aAAK,CAAC;gCAClD,sBAAA,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAA;qCAAA,CAChD;4BAED,8DAA8D;0BAF7D;;wBAFK,KAAA,sBAAkC,SAEvC;4BAED,8DAA8D;iCAF7D,EAFM,aAAa,QAAA,EAAE,cAAc,QAAA;wBAIpC,8DAA8D;wBAC9D,IAAI,aAAa,EAAE;4BACjB,IAAI,CAAC,GAAG,CACN,qDAAqD,EACrD,aAAa,CACd,CAAA;4BACD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAA;4BACjC,IAAI,CAAC,SAAS,EAAE,CAAA;4BAEhB,sBAAM;yBACP;wBAED,IAAI,cAAc,EAAE;4BAClB,IAAI,CAAC,GAAG,CAAC,2BAA2B,EAAE,cAAc,CAAC,CAAA;4BACrD,IAAI,CAAC,cAAc,GAAG,MAAM,CAAA;4BAEtB,kBAAkB,GAAG,6BAAa,CAAC,cAAc,CAAC,CAAA;4BACxD,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,CAAA;4BAChC,IAAI,CAAC,GAAG,CACN,kBAAkB,CAAC,MAAM,EACzB,kBAAkB,CAAC,UAAU,EAC7B,kBAAkB,CAAC,IAAI,EACvB,UAAU,CACX,CAAA;4BAED,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,EAAI,CAAA;4BAEZ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,CAAA;4BAErE,sBAAM;yBACP;wBAED,IAAI,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAA;wBAErC,uCAAuC;wBACvC,yDAAyD;wBACzD,IAAI,CAAC,cAAc,GAAG,QAAQ,CAAA;wBAE9B,wCAAwC;wBACxC,4EAA4E;wBAC5E,IAAI,IAAI,CAAC,aAAa,EAAE;4BACtB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,CAAA;4BACtC,sBAAM;yBACP;wBAED,kEAAkE;wBAClE,iEAAiE;wBACjE,mEAAmE;wBACnE,mBAAmB;wBACnB,IAAI,CAAC,GAAG,CAAC,2BAA2B,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;;4BAClD,KAA4C,KAAA,SAAA,IAAI,CAAC,MAAM,CAAA,4CAAE;gCAA9C,aAA6B,EAA3B,kBAAK,EAAE,wBAAQ,EAAE,wBAAQ;gCACpC,UAAQ;oCACN,CAAC,CAAC,iBAAM,KAAK,YAAC,OAAK,EAAE,UAAQ,EAAE,UAAQ,CAAC;oCACxC,CAAC,CAAC,iBAAM,KAAK,YAAC,OAAK,EAAE,UAAQ,CAAC,CAAA;6BACjC;;;;;;;;;wBAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAC,KAAK;4BACvB,KAAI,CAAC,GAAG,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAA;wBAC5C,CAAC,CAAC,CAAA;wBAEF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;4BACjB,KAAI,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAA;wBACvC,CAAC,CAAC,CAAA;wBAEF,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,UAAO,QAAyB;;;;4CACxC,qBAAM,+CAAsB,CAAC,QAAQ,CAAC,EAAA;;wCAArD,YAAY,GAAG,SAAsC;wCAC3D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,aAAa,EAAE,YAAY,CAAC,CAAA;wCACnE,IAAI,CAAC,GAAG,CAAC,4BAA4B,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;wCAExD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,EAAE;4CAChD,MAAM,EAAE,QAAQ,CAAC,UAAU,IAAI,GAAG;4CAClC,UAAU,EAAE,QAAQ,CAAC,aAAa,IAAI,IAAI;4CAC1C,OAAO,EAAE,qBAAe,CAAC,QAAQ,CAAC,OAAO,CAAC;4CAC1C,IAAI,EAAE,YAAY;yCACnB,CAAC,CAAA;;;;6BACH,CAAC,CAAA;wBAEF,IAAI,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAA;wBAE1C,sBAAO,iBAAM,GAAG,sCACX;gCACD,KAAK;gCACL,QAAe;gCACf;oCACE,KAAI,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAA;oCACjC,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,EAAI,CAAA;gCACd,CAAC;6BACF,CAAC,MAAM,CAAC,OAAO,CAAC,KAClB;;;;KACF;IAED,gCAAI,GAAJ,UAAK,KAAa;QAAE,cAAc;aAAd,UAAc,EAAd,qBAAc,EAAd,IAAc;YAAd,6BAAc;;QAChC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;QAE3B,IAAI,KAAK,KAAK,UAAU,EAAE;YACxB,IAAI,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAA;YAE3D,IAAI;gBACF;;;;;;;mBAOG;gBACH,IAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAoB,CAAA;gBAC3C,IAAM,UAAU,GAAG,2CAAoB,CAAC,QAAQ,CAAC,CAAA;gBACjD,IAAM,WAAW,GAAG,2CAAoB,CAAC,QAAQ,CAAC,CAAA;gBAElD,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,WAAW,CAAC,CAAA;gBAE3C,IAAI,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAA;gBACrE,OAAO,iBAAM,IAAI,4BAAC,KAAK,EAAE,UAAU,UAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAC;aACvD;YAAC,OAAO,KAAK,EAAE;gBACd,IAAI,CAAC,GAAG,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAA;gBAC/C,OAAO,iBAAM,IAAI,4BAAC,KAAK,UAAK,IAAI,IAAC;aAClC;SACF;QAED,IAAI,KAAK,KAAK,OAAO,EAAE;YACrB,IAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAA0B,CAAA;YAC9C,IAAM,SAAS,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAA;YAElC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;YAE3B,wDAAwD;YACxD,8DAA8D;YAC9D,wDAAwD;YACxD,IACE,IAAI,CAAC,cAAc,KAAK,MAAM;gBAC9B,iBAAiB,CAAC,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,EACxD;gBACA,qDAAqD;gBACrD,2DAA2D;gBAC3D,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;oBACvB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAA;iBAC3B;gBACD,OAAO,KAAK,CAAA;aACb;SACF;QAED,OAAO,iBAAM,IAAI,4BAAC,KAAK,UAAK,IAAI,IAAC;IACnC,CAAC;IAEO,uCAAW,GAAnB,UAAoB,cAA8B;;QAChD,IAAI,CAAC,GAAG,CAAC,sCAAsC,EAAE,cAAc,CAAC,CAAA;QAExD,IAAA,MAAM,GAAgC,cAAc,OAA9C,EAAE,UAAU,GAAoB,cAAc,WAAlC,EAAE,OAAO,GAAW,cAAc,QAAzB,EAAE,IAAI,GAAK,cAAc,KAAnB,CAAmB;QAC5D,IAAI,CAAC,QAAQ,CAAC,UAAU,GAAG,MAAM,CAAA;QACjC,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,UAAU,CAAA;QAExC,IAAI,OAAO,EAAE;YACX,IAAI,CAAC,QAAQ,CAAC,OAAO,GAAG,EAAE,CAAA;;gBAE1B,KAAwC,IAAA,KAAA,SAAA,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA,gBAAA,4BAAE;oBAAtD,IAAA,KAAA,mBAAyB,EAAxB,UAAU,QAAA,EAAE,WAAW,QAAA;oBACjC,CAAA,KAAA,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAA,CAAC,IAAI,0BAC3B,UAAU,UACP,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAC9D;oBAED,IAAM,qBAAqB,GAAG,UAAU,CAAC,WAAW,EAAE,CAAA;oBACtD,IAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAA;oBAChE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,GAAG,WAAW;wBACxD,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,WAAW,CAAC;wBACtD,CAAC,CAAC,WAAW,CAAA;iBAChB;;;;;;;;;SACF;QACD,IAAI,CAAC,GAAG,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAA;QAEnD,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;SACtC;QAED,6DAA6D;QAC7D,uCAAuC;QACvC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACxB,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAA;QAE7B;;;;;WAKG;QACH,aAAa;QACb,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAA;QAExB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA;QACpB,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,eAAe,EAAE;YAC3C,KAAK,EAAE,IAAI;SACZ,CAAC,CAAA;QAEF,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACnB,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAEpC,IAAI,CAAC,SAAS,EAAE,CAAA;IAClB,CAAC;IAED;;OAEG;IACK,qCAAS,GAAjB;QACE,aAAa;QACb,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAA;IACtB,CAAC;IAEO,0CAAc,GAAtB,UAAuB,KAAmC;QACxD,IAAM,kBAAkB,GAAG,uCAAkB,CAC3C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAChC,CAAA;QACD,IAAI,CAAC,GAAG,CAAC,uBAAuB,EAAE,kBAAkB,CAAC,CAAA;QAErD,yEAAyE;QACzE,IAAI,KAAK,EAAE;YACT,IAAI,CAAC,WAAW,GAAG,yCAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;SAChE;QAED,IAAM,mBAAmB,GAAG,uCAAkB,CAC5C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAChC,CAAA;QAED,IAAI,CAAC,GAAG,CAAC,wBAAwB,EAAE,mBAAmB,CAAC,CAAA;QAEvD,OAAO,mBAAmB,CAAA;IAC5B,CAAC;IAEO,+CAAmB,GAA3B,UAA4B,IAAY;;QACtC,IAAI,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAA;QAEjD,IAAM,eAAe,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA;QACzC,IAAI,CAAC,GAAG,CAAC,2BAA2B,EAAE,eAAe,CAAC,CAAA;QAEtD,IAAM,OAAO,GAAG,IAAI,aAAO,EAAE,CAAA;;YAC7B,KAAwC,IAAA,KAAA,SAAA,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA,gBAAA,4BAAE;gBAA9D,IAAA,KAAA,mBAAyB,EAAxB,UAAU,QAAA,EAAE,WAAW,QAAA;gBACjC,IAAI,CAAC,WAAW,EAAE;oBAChB,SAAQ;iBACT;gBAED,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAA;aAC9D;;;;;;;;;QAED,IAAM,iBAAiB,GAAsB;YAC3C,EAAE,EAAE,aAAM,EAAE;YACZ,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK;YACpC,WAAW,EAAE,MAAM;YACnB,OAAO,SAAA;YACP,IAAI,MAAA;SACL,CAAA;QAED,IAAI,CAAC,GAAG,CAAC,0CAA0C,EAAE,iBAAiB,CAAC,CAAA;QACvE,OAAO,iBAAiB,CAAA;IAC1B,CAAC;IAnVD;;;OAGG;IACI,oCAAkB,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,YAAY,CAAC,CAAA;IAgVzE,wBAAC;CAAA,AArVD,CAAuC,oBAAa,GAqVnD;AArVY,8CAAiB"}
|