@appium/base-driver 8.7.2 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/build/lib/basedriver/capabilities.d.ts +11 -163
  2. package/build/lib/basedriver/capabilities.d.ts.map +1 -1
  3. package/build/lib/basedriver/capabilities.js +354 -236
  4. package/build/lib/basedriver/capabilities.js.map +1 -1
  5. package/build/lib/basedriver/commands/event.d.ts +7 -6
  6. package/build/lib/basedriver/commands/event.d.ts.map +1 -1
  7. package/build/lib/basedriver/commands/event.js +55 -35
  8. package/build/lib/basedriver/commands/event.js.map +1 -1
  9. package/build/lib/basedriver/commands/execute.d.ts +7 -6
  10. package/build/lib/basedriver/commands/execute.d.ts.map +1 -1
  11. package/build/lib/basedriver/commands/execute.js +66 -58
  12. package/build/lib/basedriver/commands/execute.js.map +1 -1
  13. package/build/lib/basedriver/commands/find.d.ts +9 -7
  14. package/build/lib/basedriver/commands/find.d.ts.map +1 -1
  15. package/build/lib/basedriver/commands/find.js +102 -54
  16. package/build/lib/basedriver/commands/find.js.map +1 -1
  17. package/build/lib/basedriver/commands/index.d.ts +3 -7
  18. package/build/lib/basedriver/commands/index.d.ts.map +1 -1
  19. package/build/lib/basedriver/commands/index.js +30 -33
  20. package/build/lib/basedriver/commands/index.js.map +1 -1
  21. package/build/lib/basedriver/commands/log.d.ts +8 -9
  22. package/build/lib/basedriver/commands/log.d.ts.map +1 -1
  23. package/build/lib/basedriver/commands/log.js +54 -38
  24. package/build/lib/basedriver/commands/log.js.map +1 -1
  25. package/build/lib/basedriver/commands/session.d.ts +7 -6
  26. package/build/lib/basedriver/commands/session.d.ts.map +1 -1
  27. package/build/lib/basedriver/commands/session.js +46 -39
  28. package/build/lib/basedriver/commands/session.js.map +1 -1
  29. package/build/lib/basedriver/commands/settings.d.ts +7 -7
  30. package/build/lib/basedriver/commands/settings.d.ts.map +1 -1
  31. package/build/lib/basedriver/commands/settings.js +35 -28
  32. package/build/lib/basedriver/commands/settings.js.map +1 -1
  33. package/build/lib/basedriver/commands/timeout.d.ts +7 -5
  34. package/build/lib/basedriver/commands/timeout.d.ts.map +1 -1
  35. package/build/lib/basedriver/commands/timeout.js +144 -162
  36. package/build/lib/basedriver/commands/timeout.js.map +1 -1
  37. package/build/lib/basedriver/core.d.ts +6 -157
  38. package/build/lib/basedriver/core.d.ts.map +1 -1
  39. package/build/lib/basedriver/core.js +361 -230
  40. package/build/lib/basedriver/core.js.map +1 -1
  41. package/build/lib/basedriver/desired-caps.js +80 -110
  42. package/build/lib/basedriver/desired-caps.js.map +1 -1
  43. package/build/lib/basedriver/device-settings.js +57 -62
  44. package/build/lib/basedriver/device-settings.js.map +1 -1
  45. package/build/lib/basedriver/driver.d.ts +21 -267
  46. package/build/lib/basedriver/driver.d.ts.map +1 -1
  47. package/build/lib/basedriver/driver.js +362 -258
  48. package/build/lib/basedriver/driver.js.map +1 -1
  49. package/build/lib/basedriver/helpers.js +500 -495
  50. package/build/lib/basedriver/helpers.js.map +1 -1
  51. package/build/lib/basedriver/logger.d.ts +1 -1
  52. package/build/lib/basedriver/logger.d.ts.map +1 -1
  53. package/build/lib/basedriver/logger.js +5 -15
  54. package/build/lib/basedriver/logger.js.map +1 -1
  55. package/build/lib/constants.js +14 -14
  56. package/build/lib/constants.js.map +1 -1
  57. package/build/lib/express/crash.js +8 -15
  58. package/build/lib/express/crash.js.map +1 -1
  59. package/build/lib/express/express-logging.js +49 -59
  60. package/build/lib/express/express-logging.js.map +1 -1
  61. package/build/lib/express/idempotency.js +125 -177
  62. package/build/lib/express/idempotency.js.map +1 -1
  63. package/build/lib/express/logger.d.ts +1 -1
  64. package/build/lib/express/logger.d.ts.map +1 -1
  65. package/build/lib/express/logger.js +5 -15
  66. package/build/lib/express/logger.js.map +1 -1
  67. package/build/lib/express/middleware.js +82 -107
  68. package/build/lib/express/middleware.js.map +1 -1
  69. package/build/lib/express/server.d.ts +17 -5
  70. package/build/lib/express/server.d.ts.map +1 -1
  71. package/build/lib/express/server.js +259 -224
  72. package/build/lib/express/server.js.map +1 -1
  73. package/build/lib/express/static.js +64 -81
  74. package/build/lib/express/static.js.map +1 -1
  75. package/build/lib/express/websocket.js +115 -87
  76. package/build/lib/express/websocket.js.map +1 -1
  77. package/build/lib/helpers/capabilities.d.ts +1 -59
  78. package/build/lib/helpers/capabilities.d.ts.map +1 -1
  79. package/build/lib/helpers/capabilities.js +72 -69
  80. package/build/lib/helpers/capabilities.js.map +1 -1
  81. package/build/lib/index.js +64 -180
  82. package/build/lib/index.js.map +1 -1
  83. package/build/lib/jsonwp-proxy/protocol-converter.js +215 -227
  84. package/build/lib/jsonwp-proxy/protocol-converter.js.map +1 -1
  85. package/build/lib/jsonwp-proxy/proxy.d.ts.map +1 -1
  86. package/build/lib/jsonwp-proxy/proxy.js +355 -393
  87. package/build/lib/jsonwp-proxy/proxy.js.map +1 -1
  88. package/build/lib/jsonwp-status/status.js +119 -130
  89. package/build/lib/jsonwp-status/status.js.map +1 -1
  90. package/build/lib/protocol/errors.d.ts +135 -32
  91. package/build/lib/protocol/errors.d.ts.map +1 -1
  92. package/build/lib/protocol/errors.js +871 -919
  93. package/build/lib/protocol/errors.js.map +1 -1
  94. package/build/lib/protocol/helpers.js +37 -37
  95. package/build/lib/protocol/helpers.js.map +1 -1
  96. package/build/lib/protocol/index.js +22 -109
  97. package/build/lib/protocol/index.js.map +1 -1
  98. package/build/lib/protocol/protocol.js +394 -350
  99. package/build/lib/protocol/protocol.js.map +1 -1
  100. package/build/lib/protocol/routes.d.ts +1238 -4
  101. package/build/lib/protocol/routes.d.ts.map +1 -1
  102. package/build/lib/protocol/routes.js +964 -1327
  103. package/build/lib/protocol/routes.js.map +1 -1
  104. package/build/lib/protocol/validators.js +32 -39
  105. package/build/lib/protocol/validators.js.map +1 -1
  106. package/build/tsconfig.tsbuildinfo +1 -1
  107. package/lib/basedriver/capabilities.js +80 -39
  108. package/lib/basedriver/commands/event.js +10 -5
  109. package/lib/basedriver/commands/execute.js +14 -9
  110. package/lib/basedriver/commands/find.js +18 -12
  111. package/lib/basedriver/commands/index.js +21 -16
  112. package/lib/basedriver/commands/log.js +24 -18
  113. package/lib/basedriver/commands/session.js +10 -5
  114. package/lib/basedriver/commands/settings.js +9 -6
  115. package/lib/basedriver/commands/timeout.js +10 -4
  116. package/lib/basedriver/core.js +2 -3
  117. package/lib/basedriver/driver.js +29 -18
  118. package/lib/express/server.js +6 -3
  119. package/lib/protocol/errors.js +155 -44
  120. package/lib/protocol/routes.js +11 -7
  121. package/package.json +14 -16
@@ -1,419 +1,381 @@
1
1
  "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = exports.JWProxy = void 0;
7
-
8
- require("source-map-support/register");
9
-
10
- var _lodash = _interopRequireDefault(require("lodash"));
11
-
12
- var _support = require("@appium/support");
13
-
14
- var _axios = _interopRequireDefault(require("axios"));
15
-
16
- var _status = require("../jsonwp-status/status");
17
-
18
- var _errors = require("../protocol/errors");
19
-
20
- var _protocol = require("../protocol");
21
-
22
- var _constants = require("../constants");
23
-
24
- var _protocolConverter = _interopRequireDefault(require("./protocol-converter"));
25
-
26
- var _helpers = require("../protocol/helpers");
27
-
28
- var _http = _interopRequireDefault(require("http"));
29
-
30
- var _https = _interopRequireDefault(require("https"));
31
-
32
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
33
-
34
- const DEFAULT_LOG = _support.logger.getLogger('WD Proxy');
35
-
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.JWProxy = void 0;
7
+ const lodash_1 = __importDefault(require("lodash"));
8
+ const support_1 = require("@appium/support");
9
+ const axios_1 = __importDefault(require("axios"));
10
+ const status_1 = require("../jsonwp-status/status");
11
+ const errors_1 = require("../protocol/errors");
12
+ const protocol_1 = require("../protocol");
13
+ const constants_1 = require("../constants");
14
+ const protocol_converter_1 = __importDefault(require("./protocol-converter"));
15
+ const helpers_1 = require("../protocol/helpers");
16
+ const http_1 = __importDefault(require("http"));
17
+ const https_1 = __importDefault(require("https"));
18
+ const DEFAULT_LOG = support_1.logger.getLogger('WD Proxy');
36
19
  const DEFAULT_REQUEST_TIMEOUT = 240000;
37
20
  const COMPACT_ERROR_PATTERNS = [/\bECONNREFUSED\b/, /socket hang up/];
38
- const {
39
- MJSONWP,
40
- W3C
41
- } = _constants.PROTOCOLS;
42
- const ALLOWED_OPTS = ['scheme', 'server', 'port', 'base', 'reqBasePath', 'sessionId', 'timeout', 'log', 'keepAlive'];
43
-
21
+ const { MJSONWP, W3C } = constants_1.PROTOCOLS;
22
+ const ALLOWED_OPTS = [
23
+ 'scheme',
24
+ 'server',
25
+ 'port',
26
+ 'base',
27
+ 'reqBasePath',
28
+ 'sessionId',
29
+ 'timeout',
30
+ 'log',
31
+ 'keepAlive',
32
+ ];
44
33
  class JWProxy {
45
- scheme;
46
- server;
47
- port;
48
- base;
49
- reqBasePath;
50
- sessionId;
51
- timeout;
52
-
53
- constructor(opts = {}) {
54
- opts = _lodash.default.pick(opts, ALLOWED_OPTS);
55
-
56
- const options = _lodash.default.defaults(_lodash.default.omit(opts, 'log'), {
57
- scheme: 'http',
58
- server: 'localhost',
59
- port: 4444,
60
- base: _constants.DEFAULT_BASE_PATH,
61
- reqBasePath: _constants.DEFAULT_BASE_PATH,
62
- sessionId: null,
63
- timeout: DEFAULT_REQUEST_TIMEOUT
64
- });
65
-
66
- options.scheme = options.scheme.toLowerCase();
67
- Object.assign(this, options);
68
- this._activeRequests = [];
69
- this._downstreamProtocol = null;
70
- const agentOpts = {
71
- keepAlive: opts.keepAlive ?? true,
72
- maxSockets: 10,
73
- maxFreeSockets: 5
74
- };
75
- this.httpAgent = new _http.default.Agent(agentOpts);
76
- this.httpsAgent = new _https.default.Agent(agentOpts);
77
- this.protocolConverter = new _protocolConverter.default(this.proxy.bind(this), opts.log);
78
- this._log = opts.log;
79
- }
80
-
81
- get log() {
82
- return this._log ?? DEFAULT_LOG;
83
- }
84
-
85
- async request(requestConfig) {
86
- const reqPromise = (0, _axios.default)(requestConfig);
87
-
88
- this._activeRequests.push(reqPromise);
89
-
90
- try {
91
- return await reqPromise;
92
- } finally {
93
- _lodash.default.pull(this._activeRequests, reqPromise);
34
+ constructor(opts = {}) {
35
+ opts = lodash_1.default.pick(opts, ALLOWED_OPTS);
36
+ // omit 'log' in the defaults assignment here because 'log' is a getter and we are going to set
37
+ // it to this._log (which lies behind the getter) further down
38
+ const options = lodash_1.default.defaults(lodash_1.default.omit(opts, 'log'), {
39
+ scheme: 'http',
40
+ server: 'localhost',
41
+ port: 4444,
42
+ base: constants_1.DEFAULT_BASE_PATH,
43
+ reqBasePath: constants_1.DEFAULT_BASE_PATH,
44
+ sessionId: null,
45
+ timeout: DEFAULT_REQUEST_TIMEOUT,
46
+ });
47
+ options.scheme = options.scheme.toLowerCase();
48
+ Object.assign(this, options);
49
+ this._activeRequests = [];
50
+ this._downstreamProtocol = null;
51
+ const agentOpts = {
52
+ keepAlive: opts.keepAlive ?? true,
53
+ maxSockets: 10,
54
+ maxFreeSockets: 5,
55
+ };
56
+ this.httpAgent = new http_1.default.Agent(agentOpts);
57
+ this.httpsAgent = new https_1.default.Agent(agentOpts);
58
+ this.protocolConverter = new protocol_converter_1.default(this.proxy.bind(this), opts.log);
59
+ this._log = opts.log;
94
60
  }
95
- }
96
-
97
- getActiveRequestsCount() {
98
- return this._activeRequests.length;
99
- }
100
-
101
- cancelActiveRequests() {
102
- this._activeRequests = [];
103
- }
104
-
105
- endpointRequiresSessionId(endpoint) {
106
- return !_lodash.default.includes(['/session', '/sessions', '/status'], endpoint);
107
- }
108
-
109
- set downstreamProtocol(value) {
110
- this._downstreamProtocol = value;
111
- this.protocolConverter.downstreamProtocol = value;
112
- }
113
-
114
- get downstreamProtocol() {
115
- return this._downstreamProtocol;
116
- }
117
-
118
- getUrlForProxy(url) {
119
- if (url === '') {
120
- url = '/';
61
+ get log() {
62
+ return this._log ?? DEFAULT_LOG;
121
63
  }
122
-
123
- const proxyBase = `${this.scheme}://${this.server}:${this.port}${this.base}`;
124
- const endpointRe = '(/(session|status))';
125
- let remainingUrl = '';
126
-
127
- if (/^http/.test(url)) {
128
- const first = new RegExp(`(https?://.+)${endpointRe}`).exec(url);
129
-
130
- if (!first) {
131
- throw new Error('Got a complete url but could not extract JWP endpoint');
132
- }
133
-
134
- remainingUrl = url.replace(first[1], '');
135
- } else if (new RegExp('^/').test(url)) {
136
- remainingUrl = url;
137
- } else {
138
- throw new Error(`Did not know what to do with url '${url}'`);
64
+ /**
65
+ * Performs requests to the downstream server
66
+ *
67
+ * @private - Do not call this method directly,
68
+ * it uses client-specific arguments and responses!
69
+ *
70
+ * @param {import('axios').AxiosRequestConfig} requestConfig
71
+ * @returns {Promise<import('axios').AxiosResponse>}
72
+ */
73
+ async request(requestConfig) {
74
+ const reqPromise = (0, axios_1.default)(requestConfig);
75
+ this._activeRequests.push(reqPromise);
76
+ try {
77
+ return await reqPromise;
78
+ }
79
+ finally {
80
+ lodash_1.default.pull(this._activeRequests, reqPromise);
81
+ }
139
82
  }
140
-
141
- const stripPrefixRe = new RegExp('^.*?(/(session|status).*)$');
142
-
143
- if (stripPrefixRe.test(remainingUrl)) {
144
- remainingUrl = stripPrefixRe.exec(remainingUrl)[1];
83
+ getActiveRequestsCount() {
84
+ return this._activeRequests.length;
145
85
  }
146
-
147
- if (!new RegExp(endpointRe).test(remainingUrl)) {
148
- remainingUrl = `/session/${this.sessionId}${remainingUrl}`;
86
+ cancelActiveRequests() {
87
+ this._activeRequests = [];
149
88
  }
150
-
151
- const requiresSessionId = this.endpointRequiresSessionId(remainingUrl);
152
-
153
- if (requiresSessionId && this.sessionId === null) {
154
- throw new Error('Trying to proxy a session command without session id');
89
+ endpointRequiresSessionId(endpoint) {
90
+ return !lodash_1.default.includes(['/session', '/sessions', '/status'], endpoint);
155
91
  }
156
-
157
- const sessionBaseRe = new RegExp('^/session/([^/]+)');
158
-
159
- if (sessionBaseRe.test(remainingUrl)) {
160
- if (this.sessionId === null) {
161
- throw new ReferenceError(`Session ID is not set, but saw a URL path referencing a session (${remainingUrl}). This may be a bug in your client.`);
162
- }
163
-
164
- const match = sessionBaseRe.exec(remainingUrl);
165
- remainingUrl = remainingUrl.replace(match[1], this.sessionId);
166
- } else if (requiresSessionId) {
167
- throw new Error(`Could not find :session section for url: ${remainingUrl}`);
92
+ set downstreamProtocol(value) {
93
+ this._downstreamProtocol = value;
94
+ this.protocolConverter.downstreamProtocol = value;
168
95
  }
169
-
170
- remainingUrl = remainingUrl.replace(/\/$/, '');
171
- return proxyBase + remainingUrl;
172
- }
173
-
174
- async proxy(url, method, body = null) {
175
- method = method.toUpperCase();
176
- const newUrl = this.getUrlForProxy(url);
177
-
178
- const truncateBody = content => _lodash.default.truncate(_lodash.default.isString(content) ? content : JSON.stringify(content), {
179
- length: _constants.MAX_LOG_BODY_LENGTH
180
- });
181
-
182
- const reqOpts = {
183
- url: newUrl,
184
- method,
185
- headers: {
186
- 'content-type': 'application/json; charset=utf-8',
187
- 'user-agent': 'appium',
188
- accept: 'application/json, */*'
189
- },
190
- proxy: false,
191
- timeout: this.timeout,
192
- httpAgent: this.httpAgent,
193
- httpsAgent: this.httpsAgent
194
- };
195
-
196
- if (_support.util.hasValue(body) && method !== 'GET') {
197
- if (typeof body !== 'object') {
198
- try {
199
- reqOpts.data = JSON.parse(body);
200
- } catch (e) {
201
- throw new Error(`Cannot interpret the request body as valid JSON: ${truncateBody(body)}`);
202
- }
203
- } else {
204
- reqOpts.data = body;
205
- }
96
+ get downstreamProtocol() {
97
+ return this._downstreamProtocol;
206
98
  }
207
-
208
- this.log.debug(`Proxying [${method} ${url || '/'}] to [${method} ${newUrl}] ` + (reqOpts.data ? `with body: ${truncateBody(reqOpts.data)}` : 'with no body'));
209
-
210
- const throwProxyError = error => {
211
- const err = new Error(`The request to ${url} has failed`);
212
- err.response = {
213
- data: error,
214
- status: 500
215
- };
216
- throw err;
217
- };
218
-
219
- let isResponseLogged = false;
220
-
221
- try {
222
- const {
223
- data,
224
- status,
225
- headers
226
- } = await this.request(reqOpts);
227
-
228
- if (!_lodash.default.isPlainObject(data)) {
229
- throwProxyError(data);
230
- }
231
-
232
- this.log.debug(`Got response with status ${status}: ${truncateBody(data)}`);
233
- isResponseLogged = true;
234
- const isSessionCreationRequest = /\/session$/.test(url) && method === 'POST';
235
-
236
- if (isSessionCreationRequest) {
237
- if (status === 200) {
238
- this.sessionId = data.sessionId || (data.value || {}).sessionId;
99
+ getUrlForProxy(url) {
100
+ if (url === '') {
101
+ url = '/';
239
102
  }
240
-
241
- this.downstreamProtocol = this.getProtocolFromResBody(data);
242
- this.log.info(`Determined the downstream protocol as '${this.downstreamProtocol}'`);
243
- }
244
-
245
- if (_lodash.default.has(data, 'status') && parseInt(data.status, 10) !== 0) {
246
- throwProxyError(data);
247
- }
248
-
249
- const res = {
250
- statusCode: status,
251
- headers,
252
- body: data
253
- };
254
- return [res, data];
255
- } catch (e) {
256
- var _e$response, _e$response2;
257
-
258
- let proxyErrorMsg = e.message;
259
-
260
- if (_support.util.hasValue(e.response)) {
261
- if (!isResponseLogged) {
262
- const error = truncateBody(e.response.data);
263
- this.log.info(_support.util.hasValue(e.response.status) ? `Got response with status ${e.response.status}: ${error}` : `Got response with unknown status: ${error}`);
103
+ const proxyBase = `${this.scheme}://${this.server}:${this.port}${this.base}`;
104
+ const endpointRe = '(/(session|status))';
105
+ let remainingUrl = '';
106
+ if (/^http/.test(url)) {
107
+ const first = new RegExp(`(https?://.+)${endpointRe}`).exec(url);
108
+ if (!first) {
109
+ throw new Error('Got a complete url but could not extract JWP endpoint');
110
+ }
111
+ remainingUrl = url.replace(first[1], '');
264
112
  }
265
- } else {
266
- proxyErrorMsg = `Could not proxy command to the remote server. Original error: ${e.message}`;
267
-
268
- if (COMPACT_ERROR_PATTERNS.some(p => p.test(e.message))) {
269
- this.log.info(e.message);
270
- } else {
271
- this.log.info(e.stack);
113
+ else if (new RegExp('^/').test(url)) {
114
+ remainingUrl = url;
272
115
  }
273
- }
274
-
275
- throw new _errors.errors.ProxyRequestError(proxyErrorMsg, (_e$response = e.response) === null || _e$response === void 0 ? void 0 : _e$response.data, (_e$response2 = e.response) === null || _e$response2 === void 0 ? void 0 : _e$response2.status);
276
- }
277
- }
278
-
279
- getProtocolFromResBody(resObj) {
280
- if (_lodash.default.isInteger(resObj.status)) {
281
- return MJSONWP;
282
- }
283
-
284
- if (!_lodash.default.isUndefined(resObj.value)) {
285
- return W3C;
286
- }
287
- }
288
-
289
- requestToCommandName(url, method) {
290
- const extractCommandName = pattern => {
291
- const pathMatch = pattern.exec(url);
292
-
293
- if (pathMatch) {
294
- return (0, _protocol.routeToCommandName)(pathMatch[1], method, this.reqBasePath);
295
- }
296
- };
297
-
298
- let commandName = (0, _protocol.routeToCommandName)(url, method, this.reqBasePath);
299
-
300
- if (!commandName && _lodash.default.includes(url, `${this.reqBasePath}/session/`)) {
301
- commandName = extractCommandName(new RegExp(`${_lodash.default.escapeRegExp(this.reqBasePath)}/session/[^/]+(.+)`));
116
+ else {
117
+ throw new Error(`Did not know what to do with url '${url}'`);
118
+ }
119
+ const stripPrefixRe = new RegExp('^.*?(/(session|status).*)$');
120
+ if (stripPrefixRe.test(remainingUrl)) {
121
+ remainingUrl = /** @type {RegExpExecArray} */ (stripPrefixRe.exec(remainingUrl))[1];
122
+ }
123
+ if (!new RegExp(endpointRe).test(remainingUrl)) {
124
+ remainingUrl = `/session/${this.sessionId}${remainingUrl}`;
125
+ }
126
+ const requiresSessionId = this.endpointRequiresSessionId(remainingUrl);
127
+ if (requiresSessionId && this.sessionId === null) {
128
+ throw new Error('Trying to proxy a session command without session id');
129
+ }
130
+ const sessionBaseRe = new RegExp('^/session/([^/]+)');
131
+ if (sessionBaseRe.test(remainingUrl)) {
132
+ if (this.sessionId === null) {
133
+ throw new ReferenceError(`Session ID is not set, but saw a URL path referencing a session (${remainingUrl}). This may be a bug in your client.`);
134
+ }
135
+ // we have something like /session/:id/foobar, so we need to replace
136
+ // the session id
137
+ const match = sessionBaseRe.exec(remainingUrl);
138
+ // TODO: if `requiresSessionId` is `false` and `sessionId` is `null`, this is a bug.
139
+ // are we sure `sessionId` is not `null`?
140
+ remainingUrl = remainingUrl.replace(
141
+ /** @type {RegExpExecArray} */ (match)[1],
142
+ /** @type {string} */ (this.sessionId));
143
+ }
144
+ else if (requiresSessionId) {
145
+ throw new Error(`Could not find :session section for url: ${remainingUrl}`);
146
+ }
147
+ remainingUrl = remainingUrl.replace(/\/$/, ''); // can't have trailing slashes
148
+ return proxyBase + remainingUrl;
302
149
  }
303
-
304
- if (!commandName && _lodash.default.includes(url, this.reqBasePath)) {
305
- commandName = extractCommandName(new RegExp(`${_lodash.default.escapeRegExp(this.reqBasePath)}(/.+)`));
150
+ async proxy(url, method, body = null) {
151
+ method = method.toUpperCase();
152
+ const newUrl = this.getUrlForProxy(url);
153
+ const truncateBody = (content) => lodash_1.default.truncate(lodash_1.default.isString(content) ? content : JSON.stringify(content), {
154
+ length: constants_1.MAX_LOG_BODY_LENGTH,
155
+ });
156
+ /** @type {import('axios').AxiosRequestConfig} */
157
+ const reqOpts = {
158
+ url: newUrl,
159
+ method,
160
+ headers: {
161
+ 'content-type': 'application/json; charset=utf-8',
162
+ 'user-agent': 'appium',
163
+ accept: 'application/json, */*',
164
+ },
165
+ proxy: false,
166
+ timeout: this.timeout,
167
+ httpAgent: this.httpAgent,
168
+ httpsAgent: this.httpsAgent,
169
+ };
170
+ // GET methods shouldn't have any body. Most servers are OK with this, but WebDriverAgent throws 400 errors
171
+ if (support_1.util.hasValue(body) && method !== 'GET') {
172
+ if (typeof body !== 'object') {
173
+ try {
174
+ reqOpts.data = JSON.parse(body);
175
+ }
176
+ catch (e) {
177
+ throw new Error(`Cannot interpret the request body as valid JSON: ${truncateBody(body)}`);
178
+ }
179
+ }
180
+ else {
181
+ reqOpts.data = body;
182
+ }
183
+ }
184
+ this.log.debug(`Proxying [${method} ${url || '/'}] to [${method} ${newUrl}] ` +
185
+ (reqOpts.data ? `with body: ${truncateBody(reqOpts.data)}` : 'with no body'));
186
+ const throwProxyError = (error) => {
187
+ const err = /** @type {ProxyError} */ (new Error(`The request to ${url} has failed`));
188
+ err.response = {
189
+ data: error,
190
+ status: 500,
191
+ };
192
+ throw err;
193
+ };
194
+ let isResponseLogged = false;
195
+ try {
196
+ const { data, status, headers } = await this.request(reqOpts);
197
+ // `data` might be really big
198
+ // Be careful while handling it to avoid memory leaks
199
+ if (!lodash_1.default.isPlainObject(data)) {
200
+ // The response should be a valid JSON object
201
+ // If it cannot be coerced to an object then the response is wrong
202
+ throwProxyError(data);
203
+ }
204
+ this.log.debug(`Got response with status ${status}: ${truncateBody(data)}`);
205
+ isResponseLogged = true;
206
+ const isSessionCreationRequest = /\/session$/.test(url) && method === 'POST';
207
+ if (isSessionCreationRequest) {
208
+ if (status === 200) {
209
+ this.sessionId = data.sessionId || (data.value || {}).sessionId;
210
+ }
211
+ this.downstreamProtocol = this.getProtocolFromResBody(data);
212
+ this.log.info(`Determined the downstream protocol as '${this.downstreamProtocol}'`);
213
+ }
214
+ if (lodash_1.default.has(data, 'status') && parseInt(data.status, 10) !== 0) {
215
+ // Some servers, like chromedriver may return response code 200 for non-zero JSONWP statuses
216
+ throwProxyError(data);
217
+ }
218
+ const res = { statusCode: status, headers, body: data };
219
+ return [res, data];
220
+ }
221
+ catch (e) {
222
+ // We only consider an error unexpected if this was not
223
+ // an async request module error or if the response cannot be cast to
224
+ // a valid JSON
225
+ let proxyErrorMsg = e.message;
226
+ if (support_1.util.hasValue(e.response)) {
227
+ if (!isResponseLogged) {
228
+ const error = truncateBody(e.response.data);
229
+ this.log.info(support_1.util.hasValue(e.response.status)
230
+ ? `Got response with status ${e.response.status}: ${error}`
231
+ : `Got response with unknown status: ${error}`);
232
+ }
233
+ }
234
+ else {
235
+ proxyErrorMsg = `Could not proxy command to the remote server. Original error: ${e.message}`;
236
+ if (COMPACT_ERROR_PATTERNS.some((p) => p.test(e.message))) {
237
+ this.log.info(e.message);
238
+ }
239
+ else {
240
+ this.log.info(e.stack);
241
+ }
242
+ }
243
+ throw new errors_1.errors.ProxyRequestError(proxyErrorMsg, e.response?.data, e.response?.status);
244
+ }
306
245
  }
307
-
308
- return commandName;
309
- }
310
-
311
- async proxyCommand(url, method, body = null) {
312
- const commandName = this.requestToCommandName(url, method);
313
-
314
- if (!commandName) {
315
- return await this.proxy(url, method, body);
246
+ getProtocolFromResBody(resObj) {
247
+ if (lodash_1.default.isInteger(resObj.status)) {
248
+ return MJSONWP;
249
+ }
250
+ if (!lodash_1.default.isUndefined(resObj.value)) {
251
+ return W3C;
252
+ }
316
253
  }
317
-
318
- this.log.debug(`Matched '${url}' to command name '${commandName}'`);
319
- return await this.protocolConverter.convertAndProxy(commandName, url, method, body);
320
- }
321
-
322
- async command(url, method, body = null) {
323
- let response;
324
- let resBodyObj;
325
-
326
- try {
327
- [response, resBodyObj] = await this.proxyCommand(url, method, body);
328
- } catch (err) {
329
- if ((0, _errors.isErrorType)(err, _errors.errors.ProxyRequestError)) {
330
- throw err.getActualError();
331
- }
332
-
333
- throw new _errors.errors.UnknownError(err.message);
254
+ /**
255
+ *
256
+ * @param {string} url
257
+ * @param {import('@appium/types').HTTPMethod} method
258
+ * @returns {string|undefined}
259
+ */
260
+ requestToCommandName(url, method) {
261
+ /**
262
+ *
263
+ * @param {RegExp} pattern
264
+ * @returns {string|undefined}
265
+ */
266
+ const extractCommandName = (pattern) => {
267
+ const pathMatch = pattern.exec(url);
268
+ if (pathMatch) {
269
+ return (0, protocol_1.routeToCommandName)(pathMatch[1], method, this.reqBasePath);
270
+ }
271
+ };
272
+ let commandName = (0, protocol_1.routeToCommandName)(url, method, this.reqBasePath);
273
+ if (!commandName && lodash_1.default.includes(url, `${this.reqBasePath}/session/`)) {
274
+ commandName = extractCommandName(new RegExp(`${lodash_1.default.escapeRegExp(this.reqBasePath)}/session/[^/]+(.+)`));
275
+ }
276
+ if (!commandName && lodash_1.default.includes(url, this.reqBasePath)) {
277
+ commandName = extractCommandName(new RegExp(`${lodash_1.default.escapeRegExp(this.reqBasePath)}(/.+)`));
278
+ }
279
+ return commandName;
334
280
  }
335
-
336
- const protocol = this.getProtocolFromResBody(resBodyObj);
337
-
338
- if (protocol === MJSONWP) {
339
- if (response.statusCode === 200 && resBodyObj.status === 0) {
340
- return resBodyObj.value;
341
- }
342
-
343
- const status = parseInt(resBodyObj.status, 10);
344
-
345
- if (!isNaN(status) && status !== 0) {
346
- let message = resBodyObj.value;
347
-
348
- if (_lodash.default.has(message, 'message')) {
349
- message = message.message;
281
+ async proxyCommand(url, method, body = null) {
282
+ const commandName = this.requestToCommandName(url, method);
283
+ if (!commandName) {
284
+ return await this.proxy(url, method, body);
350
285
  }
351
-
352
- throw (0, _errors.errorFromMJSONWPStatusCode)(status, _lodash.default.isEmpty(message) ? (0, _status.getSummaryByCode)(status) : message);
353
- }
354
- } else if (protocol === W3C) {
355
- if (response.statusCode < 300) {
356
- return resBodyObj.value;
357
- }
358
-
359
- if (_lodash.default.isPlainObject(resBodyObj.value) && resBodyObj.value.error) {
360
- throw (0, _errors.errorFromW3CJsonCode)(resBodyObj.value.error, resBodyObj.value.message, resBodyObj.value.stacktrace);
361
- }
362
- } else if (response.statusCode === 200) {
363
- return resBodyObj;
286
+ this.log.debug(`Matched '${url}' to command name '${commandName}'`);
287
+ return await this.protocolConverter.convertAndProxy(commandName, url, method, body);
364
288
  }
365
-
366
- throw new _errors.errors.UnknownError(`Did not know what to do with response code '${response.statusCode}' ` + `and response body '${_lodash.default.truncate(JSON.stringify(resBodyObj), {
367
- length: 300
368
- })}'`);
369
- }
370
-
371
- getSessionIdFromUrl(url) {
372
- const match = url.match(/\/session\/([^/]+)/);
373
- return match ? match[1] : null;
374
- }
375
-
376
- async proxyReqRes(req, res) {
377
- let statusCode;
378
- let resBodyObj;
379
-
380
- try {
381
- let response;
382
- [response, resBodyObj] = await this.proxyCommand(req.originalUrl, req.method, req.body);
383
- res.headers = response.headers;
384
- statusCode = response.statusCode;
385
- } catch (err) {
386
- [statusCode, resBodyObj] = (0, _errors.getResponseForW3CError)((0, _errors.isErrorType)(err, _errors.errors.ProxyRequestError) ? err.getActualError() : err);
289
+ async command(url, method, body = null) {
290
+ let response;
291
+ let resBodyObj;
292
+ try {
293
+ [response, resBodyObj] = await this.proxyCommand(url, method, body);
294
+ }
295
+ catch (err) {
296
+ if ((0, errors_1.isErrorType)(err, errors_1.errors.ProxyRequestError)) {
297
+ throw err.getActualError();
298
+ }
299
+ throw new errors_1.errors.UnknownError(err.message);
300
+ }
301
+ const protocol = this.getProtocolFromResBody(resBodyObj);
302
+ if (protocol === MJSONWP) {
303
+ // Got response in MJSONWP format
304
+ if (response.statusCode === 200 && resBodyObj.status === 0) {
305
+ return resBodyObj.value;
306
+ }
307
+ const status = parseInt(resBodyObj.status, 10);
308
+ if (!isNaN(status) && status !== 0) {
309
+ let message = resBodyObj.value;
310
+ if (lodash_1.default.has(message, 'message')) {
311
+ message = message.message;
312
+ }
313
+ throw (0, errors_1.errorFromMJSONWPStatusCode)(status, lodash_1.default.isEmpty(message) ? (0, status_1.getSummaryByCode)(status) : message);
314
+ }
315
+ }
316
+ else if (protocol === W3C) {
317
+ // Got response in W3C format
318
+ if (response.statusCode < 300) {
319
+ return resBodyObj.value;
320
+ }
321
+ if (lodash_1.default.isPlainObject(resBodyObj.value) && resBodyObj.value.error) {
322
+ throw (0, errors_1.errorFromW3CJsonCode)(resBodyObj.value.error, resBodyObj.value.message, resBodyObj.value.stacktrace);
323
+ }
324
+ }
325
+ else if (response.statusCode === 200) {
326
+ // Unknown protocol. Keeping it because of the backward compatibility
327
+ return resBodyObj;
328
+ }
329
+ throw new errors_1.errors.UnknownError(`Did not know what to do with response code '${response.statusCode}' ` +
330
+ `and response body '${lodash_1.default.truncate(JSON.stringify(resBodyObj), {
331
+ length: 300,
332
+ })}'`);
387
333
  }
388
-
389
- res.set('content-type', 'application/json; charset=utf-8');
390
-
391
- if (!_lodash.default.isPlainObject(resBodyObj)) {
392
- const error = new _errors.errors.UnknownError(`The downstream server response with the status code ${statusCode} is not a valid JSON object: ` + _lodash.default.truncate(`${resBodyObj}`, {
393
- length: 300
394
- }));
395
- [statusCode, resBodyObj] = (0, _errors.getResponseForW3CError)(error);
334
+ getSessionIdFromUrl(url) {
335
+ const match = url.match(/\/session\/([^/]+)/);
336
+ return match ? match[1] : null;
396
337
  }
397
-
398
- if (_lodash.default.has(resBodyObj, 'sessionId')) {
399
- const reqSessionId = this.getSessionIdFromUrl(req.originalUrl);
400
-
401
- if (reqSessionId) {
402
- this.log.info(`Replacing sessionId ${resBodyObj.sessionId} with ${reqSessionId}`);
403
- resBodyObj.sessionId = reqSessionId;
404
- } else if (this.sessionId) {
405
- this.log.info(`Replacing sessionId ${resBodyObj.sessionId} with ${this.sessionId}`);
406
- resBodyObj.sessionId = this.sessionId;
407
- }
338
+ async proxyReqRes(req, res) {
339
+ // ! this method must not throw any exceptions
340
+ // ! make sure to call res.send before return
341
+ let statusCode;
342
+ let resBodyObj;
343
+ try {
344
+ let response;
345
+ [response, resBodyObj] = await this.proxyCommand(req.originalUrl, req.method, req.body);
346
+ res.headers = response.headers;
347
+ statusCode = response.statusCode;
348
+ }
349
+ catch (err) {
350
+ [statusCode, resBodyObj] = (0, errors_1.getResponseForW3CError)((0, errors_1.isErrorType)(err, errors_1.errors.ProxyRequestError) ? err.getActualError() : err);
351
+ }
352
+ res.set('content-type', 'application/json; charset=utf-8');
353
+ if (!lodash_1.default.isPlainObject(resBodyObj)) {
354
+ const error = new errors_1.errors.UnknownError(`The downstream server response with the status code ${statusCode} is not a valid JSON object: ` +
355
+ lodash_1.default.truncate(`${resBodyObj}`, { length: 300 }));
356
+ [statusCode, resBodyObj] = (0, errors_1.getResponseForW3CError)(error);
357
+ }
358
+ // if the proxied response contains a sessionId that the downstream
359
+ // driver has generated, we don't want to return that to the client.
360
+ // Instead, return the id from the request or from current session
361
+ if (lodash_1.default.has(resBodyObj, 'sessionId')) {
362
+ const reqSessionId = this.getSessionIdFromUrl(req.originalUrl);
363
+ if (reqSessionId) {
364
+ this.log.info(`Replacing sessionId ${resBodyObj.sessionId} with ${reqSessionId}`);
365
+ resBodyObj.sessionId = reqSessionId;
366
+ }
367
+ else if (this.sessionId) {
368
+ this.log.info(`Replacing sessionId ${resBodyObj.sessionId} with ${this.sessionId}`);
369
+ resBodyObj.sessionId = this.sessionId;
370
+ }
371
+ }
372
+ resBodyObj.value = (0, helpers_1.formatResponseValue)(resBodyObj.value);
373
+ res.status(statusCode).send(JSON.stringify((0, helpers_1.formatStatus)(resBodyObj)));
408
374
  }
409
-
410
- resBodyObj.value = (0, _helpers.formatResponseValue)(resBodyObj.value);
411
- res.status(statusCode).send(JSON.stringify((0, _helpers.formatStatus)(resBodyObj)));
412
- }
413
-
414
375
  }
415
-
416
376
  exports.JWProxy = JWProxy;
417
- var _default = JWProxy;
418
- exports.default = _default;
419
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJERUZBVUxUX0xPRyIsImxvZ2dlciIsImdldExvZ2dlciIsIkRFRkFVTFRfUkVRVUVTVF9USU1FT1VUIiwiQ09NUEFDVF9FUlJPUl9QQVRURVJOUyIsIk1KU09OV1AiLCJXM0MiLCJQUk9UT0NPTFMiLCJBTExPV0VEX09QVFMiLCJKV1Byb3h5Iiwic2NoZW1lIiwic2VydmVyIiwicG9ydCIsImJhc2UiLCJyZXFCYXNlUGF0aCIsInNlc3Npb25JZCIsInRpbWVvdXQiLCJjb25zdHJ1Y3RvciIsIm9wdHMiLCJfIiwicGljayIsIm9wdGlvbnMiLCJkZWZhdWx0cyIsIm9taXQiLCJERUZBVUxUX0JBU0VfUEFUSCIsInRvTG93ZXJDYXNlIiwiT2JqZWN0IiwiYXNzaWduIiwiX2FjdGl2ZVJlcXVlc3RzIiwiX2Rvd25zdHJlYW1Qcm90b2NvbCIsImFnZW50T3B0cyIsImtlZXBBbGl2ZSIsIm1heFNvY2tldHMiLCJtYXhGcmVlU29ja2V0cyIsImh0dHBBZ2VudCIsImh0dHAiLCJBZ2VudCIsImh0dHBzQWdlbnQiLCJodHRwcyIsInByb3RvY29sQ29udmVydGVyIiwiUHJvdG9jb2xDb252ZXJ0ZXIiLCJwcm94eSIsImJpbmQiLCJsb2ciLCJfbG9nIiwicmVxdWVzdCIsInJlcXVlc3RDb25maWciLCJyZXFQcm9taXNlIiwiYXhpb3MiLCJwdXNoIiwicHVsbCIsImdldEFjdGl2ZVJlcXVlc3RzQ291bnQiLCJsZW5ndGgiLCJjYW5jZWxBY3RpdmVSZXF1ZXN0cyIsImVuZHBvaW50UmVxdWlyZXNTZXNzaW9uSWQiLCJlbmRwb2ludCIsImluY2x1ZGVzIiwiZG93bnN0cmVhbVByb3RvY29sIiwidmFsdWUiLCJnZXRVcmxGb3JQcm94eSIsInVybCIsInByb3h5QmFzZSIsImVuZHBvaW50UmUiLCJyZW1haW5pbmdVcmwiLCJ0ZXN0IiwiZmlyc3QiLCJSZWdFeHAiLCJleGVjIiwiRXJyb3IiLCJyZXBsYWNlIiwic3RyaXBQcmVmaXhSZSIsInJlcXVpcmVzU2Vzc2lvbklkIiwic2Vzc2lvbkJhc2VSZSIsIlJlZmVyZW5jZUVycm9yIiwibWF0Y2giLCJtZXRob2QiLCJib2R5IiwidG9VcHBlckNhc2UiLCJuZXdVcmwiLCJ0cnVuY2F0ZUJvZHkiLCJjb250ZW50IiwidHJ1bmNhdGUiLCJpc1N0cmluZyIsIkpTT04iLCJzdHJpbmdpZnkiLCJNQVhfTE9HX0JPRFlfTEVOR1RIIiwicmVxT3B0cyIsImhlYWRlcnMiLCJhY2NlcHQiLCJ1dGlsIiwiaGFzVmFsdWUiLCJkYXRhIiwicGFyc2UiLCJlIiwiZGVidWciLCJ0aHJvd1Byb3h5RXJyb3IiLCJlcnJvciIsImVyciIsInJlc3BvbnNlIiwic3RhdHVzIiwiaXNSZXNwb25zZUxvZ2dlZCIsImlzUGxhaW5PYmplY3QiLCJpc1Nlc3Npb25DcmVhdGlvblJlcXVlc3QiLCJnZXRQcm90b2NvbEZyb21SZXNCb2R5IiwiaW5mbyIsImhhcyIsInBhcnNlSW50IiwicmVzIiwic3RhdHVzQ29kZSIsInByb3h5RXJyb3JNc2ciLCJtZXNzYWdlIiwic29tZSIsInAiLCJzdGFjayIsImVycm9ycyIsIlByb3h5UmVxdWVzdEVycm9yIiwicmVzT2JqIiwiaXNJbnRlZ2VyIiwiaXNVbmRlZmluZWQiLCJyZXF1ZXN0VG9Db21tYW5kTmFtZSIsImV4dHJhY3RDb21tYW5kTmFtZSIsInBhdHRlcm4iLCJwYXRoTWF0Y2giLCJyb3V0ZVRvQ29tbWFuZE5hbWUiLCJjb21tYW5kTmFtZSIsImVzY2FwZVJlZ0V4cCIsInByb3h5Q29tbWFuZCIsImNvbnZlcnRBbmRQcm94eSIsImNvbW1hbmQiLCJyZXNCb2R5T2JqIiwiaXNFcnJvclR5cGUiLCJnZXRBY3R1YWxFcnJvciIsIlVua25vd25FcnJvciIsInByb3RvY29sIiwiaXNOYU4iLCJlcnJvckZyb21NSlNPTldQU3RhdHVzQ29kZSIsImlzRW1wdHkiLCJnZXRTdW1tYXJ5QnlDb2RlIiwiZXJyb3JGcm9tVzNDSnNvbkNvZGUiLCJzdGFja3RyYWNlIiwiZ2V0U2Vzc2lvbklkRnJvbVVybCIsInByb3h5UmVxUmVzIiwicmVxIiwib3JpZ2luYWxVcmwiLCJnZXRSZXNwb25zZUZvclczQ0Vycm9yIiwic2V0IiwicmVxU2Vzc2lvbklkIiwiZm9ybWF0UmVzcG9uc2VWYWx1ZSIsInNlbmQiLCJmb3JtYXRTdGF0dXMiXSwic291cmNlcyI6WyIuLi8uLi8uLi9saWIvanNvbndwLXByb3h5L3Byb3h5LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5pbXBvcnQge2xvZ2dlciwgdXRpbH0gZnJvbSAnQGFwcGl1bS9zdXBwb3J0JztcbmltcG9ydCBheGlvcyBmcm9tICdheGlvcyc7XG5pbXBvcnQge2dldFN1bW1hcnlCeUNvZGV9IGZyb20gJy4uL2pzb253cC1zdGF0dXMvc3RhdHVzJztcbmltcG9ydCB7XG4gIGVycm9ycyxcbiAgaXNFcnJvclR5cGUsXG4gIGVycm9yRnJvbU1KU09OV1BTdGF0dXNDb2RlLFxuICBlcnJvckZyb21XM0NKc29uQ29kZSxcbiAgZ2V0UmVzcG9uc2VGb3JXM0NFcnJvcixcbn0gZnJvbSAnLi4vcHJvdG9jb2wvZXJyb3JzJztcbmltcG9ydCB7cm91dGVUb0NvbW1hbmROYW1lfSBmcm9tICcuLi9wcm90b2NvbCc7XG5pbXBvcnQge01BWF9MT0dfQk9EWV9MRU5HVEgsIERFRkFVTFRfQkFTRV9QQVRILCBQUk9UT0NPTFN9IGZyb20gJy4uL2NvbnN0YW50cyc7XG5pbXBvcnQgUHJvdG9jb2xDb252ZXJ0ZXIgZnJvbSAnLi9wcm90b2NvbC1jb252ZXJ0ZXInO1xuaW1wb3J0IHtmb3JtYXRSZXNwb25zZVZhbHVlLCBmb3JtYXRTdGF0dXN9IGZyb20gJy4uL3Byb3RvY29sL2hlbHBlcnMnO1xuaW1wb3J0IGh0dHAgZnJvbSAnaHR0cCc7XG5pbXBvcnQgaHR0cHMgZnJvbSAnaHR0cHMnO1xuXG5jb25zdCBERUZBVUxUX0xPRyA9IGxvZ2dlci5nZXRMb2dnZXIoJ1dEIFByb3h5Jyk7XG5jb25zdCBERUZBVUxUX1JFUVVFU1RfVElNRU9VVCA9IDI0MDAwMDtcbmNvbnN0IENPTVBBQ1RfRVJST1JfUEFUVEVSTlMgPSBbL1xcYkVDT05OUkVGVVNFRFxcYi8sIC9zb2NrZXQgaGFuZyB1cC9dO1xuXG5jb25zdCB7TUpTT05XUCwgVzNDfSA9IFBST1RPQ09MUztcblxuY29uc3QgQUxMT1dFRF9PUFRTID0gW1xuICAnc2NoZW1lJyxcbiAgJ3NlcnZlcicsXG4gICdwb3J0JyxcbiAgJ2Jhc2UnLFxuICAncmVxQmFzZVBhdGgnLFxuICAnc2Vzc2lvbklkJyxcbiAgJ3RpbWVvdXQnLFxuICAnbG9nJyxcbiAgJ2tlZXBBbGl2ZScsXG5dO1xuXG5jbGFzcyBKV1Byb3h5IHtcbiAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gIHNjaGVtZTtcbiAgLyoqIEB0eXBlIHtzdHJpbmd9ICovXG4gIHNlcnZlcjtcbiAgLyoqIEB0eXBlIHtudW1iZXJ9ICovXG4gIHBvcnQ7XG4gIC8qKiBAdHlwZSB7c3RyaW5nfSAqL1xuICBiYXNlO1xuICAvKiogQHR5cGUge3N0cmluZ30gKi9cbiAgcmVxQmFzZVBhdGg7XG4gIC8qKiBAdHlwZSB7c3RyaW5nP30gKi9cbiAgc2Vzc2lvbklkO1xuICAvKiogQHR5cGUge251bWJlcn0gKi9cbiAgdGltZW91dDtcblxuICBjb25zdHJ1Y3RvcihvcHRzID0ge30pIHtcbiAgICBvcHRzID0gXy5waWNrKG9wdHMsIEFMTE9XRURfT1BUUyk7XG5cbiAgICAvLyBvbWl0ICdsb2cnIGluIHRoZSBkZWZhdWx0cyBhc3NpZ25tZW50IGhlcmUgYmVjYXVzZSAnbG9nJyBpcyBhIGdldHRlciBhbmQgd2UgYXJlIGdvaW5nIHRvIHNldFxuICAgIC8vIGl0IHRvIHRoaXMuX2xvZyAod2hpY2ggbGllcyBiZWhpbmQgdGhlIGdldHRlcikgZnVydGhlciBkb3duXG4gICAgY29uc3Qgb3B0aW9ucyA9IF8uZGVmYXVsdHMoXy5vbWl0KG9wdHMsICdsb2cnKSwge1xuICAgICAgc2NoZW1lOiAnaHR0cCcsXG4gICAgICBzZXJ2ZXI6ICdsb2NhbGhvc3QnLFxuICAgICAgcG9ydDogNDQ0NCxcbiAgICAgIGJhc2U6IERFRkFVTFRfQkFTRV9QQVRILFxuICAgICAgcmVxQmFzZVBhdGg6IERFRkFVTFRfQkFTRV9QQVRILFxuICAgICAgc2Vzc2lvbklkOiBudWxsLFxuICAgICAgdGltZW91dDogREVGQVVMVF9SRVFVRVNUX1RJTUVPVVQsXG4gICAgfSk7XG4gICAgb3B0aW9ucy5zY2hlbWUgPSBvcHRpb25zLnNjaGVtZS50b0xvd2VyQ2FzZSgpO1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywgb3B0aW9ucyk7XG5cbiAgICB0aGlzLl9hY3RpdmVSZXF1ZXN0cyA9IFtdO1xuICAgIHRoaXMuX2Rvd25zdHJlYW1Qcm90b2NvbCA9IG51bGw7XG4gICAgY29uc3QgYWdlbnRPcHRzID0ge1xuICAgICAga2VlcEFsaXZlOiBvcHRzLmtlZXBBbGl2ZSA/PyB0cnVlLFxuICAgICAgbWF4U29ja2V0czogMTAsXG4gICAgICBtYXhGcmVlU29ja2V0czogNSxcbiAgICB9O1xuICAgIHRoaXMuaHR0cEFnZW50ID0gbmV3IGh0dHAuQWdlbnQoYWdlbnRPcHRzKTtcbiAgICB0aGlzLmh0dHBzQWdlbnQgPSBuZXcgaHR0cHMuQWdlbnQoYWdlbnRPcHRzKTtcbiAgICB0aGlzLnByb3RvY29sQ29udmVydGVyID0gbmV3IFByb3RvY29sQ29udmVydGVyKHRoaXMucHJveHkuYmluZCh0aGlzKSwgb3B0cy5sb2cpO1xuICAgIHRoaXMuX2xvZyA9IG9wdHMubG9nO1xuICB9XG5cbiAgZ2V0IGxvZygpIHtcbiAgICByZXR1cm4gdGhpcy5fbG9nID8/IERFRkFVTFRfTE9HO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIHJlcXVlc3RzIHRvIHRoZSBkb3duc3RyZWFtIHNlcnZlclxuICAgKlxuICAgKiBAcHJpdmF0ZSAtIERvIG5vdCBjYWxsIHRoaXMgbWV0aG9kIGRpcmVjdGx5LFxuICAgKiBpdCB1c2VzIGNsaWVudC1zcGVjaWZpYyBhcmd1bWVudHMgYW5kIHJlc3BvbnNlcyFcbiAgICpcbiAgICogQHBhcmFtIHtpbXBvcnQoJ2F4aW9zJykuQXhpb3NSZXF1ZXN0Q29uZmlnfSByZXF1ZXN0Q29uZmlnXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPGltcG9ydCgnYXhpb3MnKS5BeGlvc1Jlc3BvbnNlPn1cbiAgICovXG4gIGFzeW5jIHJlcXVlc3QocmVxdWVzdENvbmZpZykge1xuICAgIGNvbnN0IHJlcVByb21pc2UgPSBheGlvcyhyZXF1ZXN0Q29uZmlnKTtcbiAgICB0aGlzLl9hY3RpdmVSZXF1ZXN0cy5wdXNoKHJlcVByb21pc2UpO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgcmVxUHJvbWlzZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgXy5wdWxsKHRoaXMuX2FjdGl2ZVJlcXVlc3RzLCByZXFQcm9taXNlKTtcbiAgICB9XG4gIH1cblxuICBnZXRBY3RpdmVSZXF1ZXN0c0NvdW50KCkge1xuICAgIHJldHVybiB0aGlzLl9hY3RpdmVSZXF1ZXN0cy5sZW5ndGg7XG4gIH1cblxuICBjYW5jZWxBY3RpdmVSZXF1ZXN0cygpIHtcbiAgICB0aGlzLl9hY3RpdmVSZXF1ZXN0cyA9IFtdO1xuICB9XG5cbiAgZW5kcG9pbnRSZXF1aXJlc1Nlc3Npb25JZChlbmRwb2ludCkge1xuICAgIHJldHVybiAhXy5pbmNsdWRlcyhbJy9zZXNzaW9uJywgJy9zZXNzaW9ucycsICcvc3RhdHVzJ10sIGVuZHBvaW50KTtcbiAgfVxuXG4gIHNldCBkb3duc3RyZWFtUHJvdG9jb2wodmFsdWUpIHtcbiAgICB0aGlzLl9kb3duc3RyZWFtUHJvdG9jb2wgPSB2YWx1ZTtcbiAgICB0aGlzLnByb3RvY29sQ29udmVydGVyLmRvd25zdHJlYW1Qcm90b2NvbCA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IGRvd25zdHJlYW1Qcm90b2NvbCgpIHtcbiAgICByZXR1cm4gdGhpcy5fZG93bnN0cmVhbVByb3RvY29sO1xuICB9XG5cbiAgZ2V0VXJsRm9yUHJveHkodXJsKSB7XG4gICAgaWYgKHVybCA9PT0gJycpIHtcbiAgICAgIHVybCA9ICcvJztcbiAgICB9XG4gICAgY29uc3QgcHJveHlCYXNlID0gYCR7dGhpcy5zY2hlbWV9Oi8vJHt0aGlzLnNlcnZlcn06JHt0aGlzLnBvcnR9JHt0aGlzLmJhc2V9YDtcbiAgICBjb25zdCBlbmRwb2ludFJlID0gJygvKHNlc3Npb258c3RhdHVzKSknO1xuICAgIGxldCByZW1haW5pbmdVcmwgPSAnJztcbiAgICBpZiAoL15odHRwLy50ZXN0KHVybCkpIHtcbiAgICAgIGNvbnN0IGZpcnN0ID0gbmV3IFJlZ0V4cChgKGh0dHBzPzovLy4rKSR7ZW5kcG9pbnRSZX1gKS5leGVjKHVybCk7XG4gICAgICBpZiAoIWZpcnN0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignR290IGEgY29tcGxldGUgdXJsIGJ1dCBjb3VsZCBub3QgZXh0cmFjdCBKV1AgZW5kcG9pbnQnKTtcbiAgICAgIH1cbiAgICAgIHJlbWFpbmluZ1VybCA9IHVybC5yZXBsYWNlKGZpcnN0WzFdLCAnJyk7XG4gICAgfSBlbHNlIGlmIChuZXcgUmVnRXhwKCdeLycpLnRlc3QodXJsKSkge1xuICAgICAgcmVtYWluaW5nVXJsID0gdXJsO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYERpZCBub3Qga25vdyB3aGF0IHRvIGRvIHdpdGggdXJsICcke3VybH0nYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgc3RyaXBQcmVmaXhSZSA9IG5ldyBSZWdFeHAoJ14uKj8oLyhzZXNzaW9ufHN0YXR1cykuKikkJyk7XG4gICAgaWYgKHN0cmlwUHJlZml4UmUudGVzdChyZW1haW5pbmdVcmwpKSB7XG4gICAgICByZW1haW5pbmdVcmwgPSAvKiogQHR5cGUge1JlZ0V4cEV4ZWNBcnJheX0gKi8gKHN0cmlwUHJlZml4UmUuZXhlYyhyZW1haW5pbmdVcmwpKVsxXTtcbiAgICB9XG5cbiAgICBpZiAoIW5ldyBSZWdFeHAoZW5kcG9pbnRSZSkudGVzdChyZW1haW5pbmdVcmwpKSB7XG4gICAgICByZW1haW5pbmdVcmwgPSBgL3Nlc3Npb24vJHt0aGlzLnNlc3Npb25JZH0ke3JlbWFpbmluZ1VybH1gO1xuICAgIH1cblxuICAgIGNvbnN0IHJlcXVpcmVzU2Vzc2lvbklkID0gdGhpcy5lbmRwb2ludFJlcXVpcmVzU2Vzc2lvbklkKHJlbWFpbmluZ1VybCk7XG5cbiAgICBpZiAocmVxdWlyZXNTZXNzaW9uSWQgJiYgdGhpcy5zZXNzaW9uSWQgPT09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVHJ5aW5nIHRvIHByb3h5IGEgc2Vzc2lvbiBjb21tYW5kIHdpdGhvdXQgc2Vzc2lvbiBpZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHNlc3Npb25CYXNlUmUgPSBuZXcgUmVnRXhwKCdeL3Nlc3Npb24vKFteL10rKScpO1xuICAgIGlmIChzZXNzaW9uQmFzZVJlLnRlc3QocmVtYWluaW5nVXJsKSkge1xuICAgICAgaWYgKHRoaXMuc2Vzc2lvbklkID09PSBudWxsKSB7XG4gICAgICAgIHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcbiAgICAgICAgICBgU2Vzc2lvbiBJRCBpcyBub3Qgc2V0LCBidXQgc2F3IGEgVVJMIHBhdGggcmVmZXJlbmNpbmcgYSBzZXNzaW9uICgke3JlbWFpbmluZ1VybH0pLiBUaGlzIG1heSBiZSBhIGJ1ZyBpbiB5b3VyIGNsaWVudC5gXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICAvLyB3ZSBoYXZlIHNvbWV0aGluZyBsaWtlIC9zZXNzaW9uLzppZC9mb29iYXIsIHNvIHdlIG5lZWQgdG8gcmVwbGFjZVxuICAgICAgLy8gdGhlIHNlc3Npb24gaWRcbiAgICAgIGNvbnN0IG1hdGNoID0gc2Vzc2lvbkJhc2VSZS5leGVjKHJlbWFpbmluZ1VybCk7XG4gICAgICAvLyBUT0RPOiBpZiBgcmVxdWlyZXNTZXNzaW9uSWRgIGlzIGBmYWxzZWAgYW5kIGBzZXNzaW9uSWRgIGlzIGBudWxsYCwgdGhpcyBpcyBhIGJ1Zy5cbiAgICAgIC8vIGFyZSB3ZSBzdXJlIGBzZXNzaW9uSWRgIGlzIG5vdCBgbnVsbGA/XG4gICAgICByZW1haW5pbmdVcmwgPSByZW1haW5pbmdVcmwucmVwbGFjZShcbiAgICAgICAgLyoqIEB0eXBlIHtSZWdFeHBFeGVjQXJyYXl9ICovIChtYXRjaClbMV0sXG4gICAgICAgIC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAodGhpcy5zZXNzaW9uSWQpXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAocmVxdWlyZXNTZXNzaW9uSWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGZpbmQgOnNlc3Npb24gc2VjdGlvbiBmb3IgdXJsOiAke3JlbWFpbmluZ1VybH1gKTtcbiAgICB9XG4gICAgcmVtYWluaW5nVXJsID0gcmVtYWluaW5nVXJsLnJlcGxhY2UoL1xcLyQvLCAnJyk7IC8vIGNhbid0IGhhdmUgdHJhaWxpbmcgc2xhc2hlc1xuXG4gICAgcmV0dXJuIHByb3h5QmFzZSArIHJlbWFpbmluZ1VybDtcbiAgfVxuXG4gIGFzeW5jIHByb3h5KHVybCwgbWV0aG9kLCBib2R5ID0gbnVsbCkge1xuICAgIG1ldGhvZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpO1xuICAgIGNvbnN0IG5ld1VybCA9IHRoaXMuZ2V0VXJsRm9yUHJveHkodXJsKTtcbiAgICBjb25zdCB0cnVuY2F0ZUJvZHkgPSAoY29udGVudCkgPT5cbiAgICAgIF8udHJ1bmNhdGUoXy5pc1N0cmluZyhjb250ZW50KSA/IGNvbnRlbnQgOiBKU09OLnN0cmluZ2lmeShjb250ZW50KSwge1xuICAgICAgICBsZW5ndGg6IE1BWF9MT0dfQk9EWV9MRU5HVEgsXG4gICAgICB9KTtcbiAgICAvKiogQHR5cGUge2ltcG9ydCgnYXhpb3MnKS5BeGlvc1JlcXVlc3RDb25maWd9ICovXG4gICAgY29uc3QgcmVxT3B0cyA9IHtcbiAgICAgIHVybDogbmV3VXJsLFxuICAgICAgbWV0aG9kLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnY29udGVudC10eXBlJzogJ2FwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLTgnLFxuICAgICAgICAndXNlci1hZ2VudCc6ICdhcHBpdW0nLFxuICAgICAgICBhY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uLCAqLyonLFxuICAgICAgfSxcbiAgICAgIHByb3h5OiBmYWxzZSxcbiAgICAgIHRpbWVvdXQ6IHRoaXMudGltZW91dCxcbiAgICAgIGh0dHBBZ2VudDogdGhpcy5odHRwQWdlbnQsXG4gICAgICBodHRwc0FnZW50OiB0aGlzLmh0dHBzQWdlbnQsXG4gICAgfTtcbiAgICAvLyBHRVQgbWV0aG9kcyBzaG91bGRuJ3QgaGF2ZSBhbnkgYm9keS4gTW9zdCBzZXJ2ZXJzIGFyZSBPSyB3aXRoIHRoaXMsIGJ1dCBXZWJEcml2ZXJBZ2VudCB0aHJvd3MgNDAwIGVycm9yc1xuICAgIGlmICh1dGlsLmhhc1ZhbHVlKGJvZHkpICYmIG1ldGhvZCAhPT0gJ0dFVCcpIHtcbiAgICAgIGlmICh0eXBlb2YgYm9keSAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXFPcHRzLmRhdGEgPSBKU09OLnBhcnNlKGJvZHkpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgaW50ZXJwcmV0IHRoZSByZXF1ZXN0IGJvZHkgYXMgdmFsaWQgSlNPTjogJHt0cnVuY2F0ZUJvZHkoYm9keSl9YCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcU9wdHMuZGF0YSA9IGJvZHk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5sb2cuZGVidWcoXG4gICAgICBgUHJveHlpbmcgWyR7bWV0aG9kfSAke3VybCB8fCAnLyd9XSB0byBbJHttZXRob2R9ICR7bmV3VXJsfV0gYCArXG4gICAgICAgIChyZXFPcHRzLmRhdGEgPyBgd2l0aCBib2R5OiAke3RydW5jYXRlQm9keShyZXFPcHRzLmRhdGEpfWAgOiAnd2l0aCBubyBib2R5JylcbiAgICApO1xuXG4gICAgY29uc3QgdGhyb3dQcm94eUVycm9yID0gKGVycm9yKSA9PiB7XG4gICAgICBjb25zdCBlcnIgPSAvKiogQHR5cGUge1Byb3h5RXJyb3J9ICovIChuZXcgRXJyb3IoYFRoZSByZXF1ZXN0IHRvICR7dXJsfSBoYXMgZmFpbGVkYCkpO1xuICAgICAgZXJyLnJlc3BvbnNlID0ge1xuICAgICAgICBkYXRhOiBlcnJvcixcbiAgICAgICAgc3RhdHVzOiA1MDAsXG4gICAgICB9O1xuICAgICAgdGhyb3cgZXJyO1xuICAgIH07XG4gICAgbGV0IGlzUmVzcG9uc2VMb2dnZWQgPSBmYWxzZTtcbiAgICB0cnkge1xuICAgICAgY29uc3Qge2RhdGEsIHN0YXR1cywgaGVhZGVyc30gPSBhd2FpdCB0aGlzLnJlcXVlc3QocmVxT3B0cyk7XG4gICAgICAvLyBgZGF0YWAgbWlnaHQgYmUgcmVhbGx5IGJpZ1xuICAgICAgLy8gQmUgY2FyZWZ1bCB3aGlsZSBoYW5kbGluZyBpdCB0byBhdm9pZCBtZW1vcnkgbGVha3NcbiAgICAgIGlmICghXy5pc1BsYWluT2JqZWN0KGRhdGEpKSB7XG4gICAgICAgIC8vIFRoZSByZXNwb25zZSBzaG91bGQgYmUgYSB2YWxpZCBKU09OIG9iamVjdFxuICAgICAgICAvLyBJZiBpdCBjYW5ub3QgYmUgY29lcmNlZCB0byBhbiBvYmplY3QgdGhlbiB0aGUgcmVzcG9uc2UgaXMgd3JvbmdcbiAgICAgICAgdGhyb3dQcm94eUVycm9yKGRhdGEpO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2cuZGVidWcoYEdvdCByZXNwb25zZSB3aXRoIHN0YXR1cyAke3N0YXR1c306ICR7dHJ1bmNhdGVCb2R5KGRhdGEpfWApO1xuICAgICAgaXNSZXNwb25zZUxvZ2dlZCA9IHRydWU7XG4gICAgICBjb25zdCBpc1Nlc3Npb25DcmVhdGlvblJlcXVlc3QgPSAvXFwvc2Vzc2lvbiQvLnRlc3QodXJsKSAmJiBtZXRob2QgPT09ICdQT1NUJztcbiAgICAgIGlmIChpc1Nlc3Npb25DcmVhdGlvblJlcXVlc3QpIHtcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgdGhpcy5zZXNzaW9uSWQgPSBkYXRhLnNlc3Npb25JZCB8fCAoZGF0YS52YWx1ZSB8fCB7fSkuc2Vzc2lvbklkO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZG93bnN0cmVhbVByb3RvY29sID0gdGhpcy5nZXRQcm90b2NvbEZyb21SZXNCb2R5KGRhdGEpO1xuICAgICAgICB0aGlzLmxvZy5pbmZvKGBEZXRlcm1pbmVkIHRoZSBkb3duc3RyZWFtIHByb3RvY29sIGFzICcke3RoaXMuZG93bnN0cmVhbVByb3RvY29sfSdgKTtcbiAgICAgIH1cbiAgICAgIGlmIChfLmhhcyhkYXRhLCAnc3RhdHVzJykgJiYgcGFyc2VJbnQoZGF0YS5zdGF0dXMsIDEwKSAhPT0gMCkge1xuICAgICAgICAvLyBTb21lIHNlcnZlcnMsIGxpa2UgY2hyb21lZHJpdmVyIG1heSByZXR1cm4gcmVzcG9uc2UgY29kZSAyMDAgZm9yIG5vbi16ZXJvIEpTT05XUCBzdGF0dXNlc1xuICAgICAgICB0aHJvd1Byb3h5RXJyb3IoZGF0YSk7XG4gICAgICB9XG4gICAgICBjb25zdCByZXMgPSB7c3RhdHVzQ29kZTogc3RhdHVzLCBoZWFkZXJzLCBib2R5OiBkYXRhfTtcbiAgICAgIHJldHVybiBbcmVzLCBkYXRhXTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBXZSBvbmx5IGNvbnNpZGVyIGFuIGVycm9yIHVuZXhwZWN0ZWQgaWYgdGhpcyB3YXMgbm90XG4gICAgICAvLyBhbiBhc3luYyByZXF1ZXN0IG1vZHVsZSBlcnJvciBvciBpZiB0aGUgcmVzcG9uc2UgY2Fubm90IGJlIGNhc3QgdG9cbiAgICAgIC8vIGEgdmFsaWQgSlNPTlxuICAgICAgbGV0IHByb3h5RXJyb3JNc2cgPSBlLm1lc3NhZ2U7XG4gICAgICBpZiAodXRpbC5oYXNWYWx1ZShlLnJlc3BvbnNlKSkge1xuICAgICAgICBpZiAoIWlzUmVzcG9uc2VMb2dnZWQpIHtcbiAgICAgICAgICBjb25zdCBlcnJvciA9IHRydW5jYXRlQm9keShlLnJlc3BvbnNlLmRhdGEpO1xuICAgICAgICAgIHRoaXMubG9nLmluZm8oXG4gICAgICAgICAgICB1dGlsLmhhc1ZhbHVlKGUucmVzcG9uc2Uuc3RhdHVzKVxuICAgICAgICAgICAgICA/IGBHb3QgcmVzcG9uc2Ugd2l0aCBzdGF0dXMgJHtlLnJlc3BvbnNlLnN0YXR1c306ICR7ZXJyb3J9YFxuICAgICAgICAgICAgICA6IGBHb3QgcmVzcG9uc2Ugd2l0aCB1bmtub3duIHN0YXR1czogJHtlcnJvcn1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcHJveHlFcnJvck1zZyA9IGBDb3VsZCBub3QgcHJveHkgY29tbWFuZCB0byB0aGUgcmVtb3RlIHNlcnZlci4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWA7XG4gICAgICAgIGlmIChDT01QQUNUX0VSUk9SX1BBVFRFUk5TLnNvbWUoKHApID0+IHAudGVzdChlLm1lc3NhZ2UpKSkge1xuICAgICAgICAgIHRoaXMubG9nLmluZm8oZS5tZXNzYWdlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmxvZy5pbmZvKGUuc3RhY2spO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLlByb3h5UmVxdWVzdEVycm9yKHByb3h5RXJyb3JNc2csIGUucmVzcG9uc2U/LmRhdGEsIGUucmVzcG9uc2U/LnN0YXR1cyk7XG4gICAgfVxuICB9XG5cbiAgZ2V0UHJvdG9jb2xGcm9tUmVzQm9keShyZXNPYmopIHtcbiAgICBpZiAoXy5pc0ludGVnZXIocmVzT2JqLnN0YXR1cykpIHtcbiAgICAgIHJldHVybiBNSlNPTldQO1xuICAgIH1cbiAgICBpZiAoIV8uaXNVbmRlZmluZWQocmVzT2JqLnZhbHVlKSkge1xuICAgICAgcmV0dXJuIFczQztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHVybFxuICAgKiBAcGFyYW0ge2ltcG9ydCgnQGFwcGl1bS90eXBlcycpLkhUVFBNZXRob2R9IG1ldGhvZFxuICAgKiBAcmV0dXJucyB7c3RyaW5nfHVuZGVmaW5lZH1cbiAgICovXG4gIHJlcXVlc3RUb0NvbW1hbmROYW1lKHVybCwgbWV0aG9kKSB7XG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1JlZ0V4cH0gcGF0dGVyblxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8dW5kZWZpbmVkfVxuICAgICAqL1xuICAgIGNvbnN0IGV4dHJhY3RDb21tYW5kTmFtZSA9IChwYXR0ZXJuKSA9PiB7XG4gICAgICBjb25zdCBwYXRoTWF0Y2ggPSBwYXR0ZXJuLmV4ZWModXJsKTtcbiAgICAgIGlmIChwYXRoTWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIHJvdXRlVG9Db21tYW5kTmFtZShwYXRoTWF0Y2hbMV0sIG1ldGhvZCwgdGhpcy5yZXFCYXNlUGF0aCk7XG4gICAgICB9XG4gICAgfTtcbiAgICBsZXQgY29tbWFuZE5hbWUgPSByb3V0ZVRvQ29tbWFuZE5hbWUodXJsLCBtZXRob2QsIHRoaXMucmVxQmFzZVBhdGgpO1xuICAgIGlmICghY29tbWFuZE5hbWUgJiYgXy5pbmNsdWRlcyh1cmwsIGAke3RoaXMucmVxQmFzZVBhdGh9L3Nlc3Npb24vYCkpIHtcbiAgICAgIGNvbW1hbmROYW1lID0gZXh0cmFjdENvbW1hbmROYW1lKFxuICAgICAgICBuZXcgUmVnRXhwKGAke18uZXNjYXBlUmVnRXhwKHRoaXMucmVxQmFzZVBhdGgpfS9zZXNzaW9uL1teL10rKC4rKWApXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIWNvbW1hbmROYW1lICYmIF8uaW5jbHVkZXModXJsLCB0aGlzLnJlcUJhc2VQYXRoKSkge1xuICAgICAgY29tbWFuZE5hbWUgPSBleHRyYWN0Q29tbWFuZE5hbWUobmV3IFJlZ0V4cChgJHtfLmVzY2FwZVJlZ0V4cCh0aGlzLnJlcUJhc2VQYXRoKX0oLy4rKWApKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbW1hbmROYW1lO1xuICB9XG5cbiAgYXN5bmMgcHJveHlDb21tYW5kKHVybCwgbWV0aG9kLCBib2R5ID0gbnVsbCkge1xuICAgIGNvbnN0IGNvbW1hbmROYW1lID0gdGhpcy5yZXF1ZXN0VG9Db21tYW5kTmFtZSh1cmwsIG1ldGhvZCk7XG4gICAgaWYgKCFjb21tYW5kTmFtZSkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucHJveHkodXJsLCBtZXRob2QsIGJvZHkpO1xuICAgIH1cbiAgICB0aGlzLmxvZy5kZWJ1ZyhgTWF0Y2hlZCAnJHt1cmx9JyB0byBjb21tYW5kIG5hbWUgJyR7Y29tbWFuZE5hbWV9J2ApO1xuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMucHJvdG9jb2xDb252ZXJ0ZXIuY29udmVydEFuZFByb3h5KGNvbW1hbmROYW1lLCB1cmwsIG1ldGhvZCwgYm9keSk7XG4gIH1cblxuICBhc3luYyBjb21tYW5kKHVybCwgbWV0aG9kLCBib2R5ID0gbnVsbCkge1xuICAgIGxldCByZXNwb25zZTtcbiAgICBsZXQgcmVzQm9keU9iajtcbiAgICB0cnkge1xuICAgICAgW3Jlc3BvbnNlLCByZXNCb2R5T2JqXSA9IGF3YWl0IHRoaXMucHJveHlDb21tYW5kKHVybCwgbWV0aG9kLCBib2R5KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChpc0Vycm9yVHlwZShlcnIsIGVycm9ycy5Qcm94eVJlcXVlc3RFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZXJyLmdldEFjdHVhbEVycm9yKCk7XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgZXJyb3JzLlVua25vd25FcnJvcihlcnIubWVzc2FnZSk7XG4gICAgfVxuICAgIGNvbnN0IHByb3RvY29sID0gdGhpcy5nZXRQcm90b2NvbEZyb21SZXNCb2R5KHJlc0JvZHlPYmopO1xuICAgIGlmIChwcm90b2NvbCA9PT0gTUpTT05XUCkge1xuICAgICAgLy8gR290IHJlc3BvbnNlIGluIE1KU09OV1AgZm9ybWF0XG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzQ29kZSA9PT0gMjAwICYmIHJlc0JvZHlPYmouc3RhdHVzID09PSAwKSB7XG4gICAgICAgIHJldHVybiByZXNCb2R5T2JqLnZhbHVlO1xuICAgICAgfVxuICAgICAgY29uc3Qgc3RhdHVzID0gcGFyc2VJbnQocmVzQm9keU9iai5zdGF0dXMsIDEwKTtcbiAgICAgIGlmICghaXNOYU4oc3RhdHVzKSAmJiBzdGF0dXMgIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSByZXNCb2R5T2JqLnZhbHVlO1xuICAgICAgICBpZiAoXy5oYXMobWVzc2FnZSwgJ21lc3NhZ2UnKSkge1xuICAgICAgICAgIG1lc3NhZ2UgPSBtZXNzYWdlLm1lc3NhZ2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZXJyb3JGcm9tTUpTT05XUFN0YXR1c0NvZGUoXG4gICAgICAgICAgc3RhdHVzLFxuICAgICAgICAgIF8uaXNFbXB0eShtZXNzYWdlKSA/IGdldFN1bW1hcnlCeUNvZGUoc3RhdHVzKSA6IG1lc3NhZ2VcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHByb3RvY29sID09PSBXM0MpIHtcbiAgICAgIC8vIEdvdCByZXNwb25zZSBpbiBXM0MgZm9ybWF0XG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzQ29kZSA8IDMwMCkge1xuICAgICAgICByZXR1cm4gcmVzQm9keU9iai52YWx1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChfLmlzUGxhaW5PYmplY3QocmVzQm9keU9iai52YWx1ZSkgJiYgcmVzQm9keU9iai52YWx1ZS5lcnJvcikge1xuICAgICAgICB0aHJvdyBlcnJvckZyb21XM0NKc29uQ29kZShcbiAgICAgICAgICByZXNCb2R5T2JqLnZhbHVlLmVycm9yLFxuICAgICAgICAgIHJlc0JvZHlPYmoudmFsdWUubWVzc2FnZSxcbiAgICAgICAgICByZXNCb2R5T2JqLnZhbHVlLnN0YWNrdHJhY2VcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPT09IDIwMCkge1xuICAgICAgLy8gVW5rbm93biBwcm90b2NvbC4gS2VlcGluZyBpdCBiZWNhdXNlIG9mIHRoZSBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgICByZXR1cm4gcmVzQm9keU9iajtcbiAgICB9XG4gICAgdGhyb3cgbmV3IGVycm9ycy5Vbmtub3duRXJyb3IoXG4gICAgICBgRGlkIG5vdCBrbm93IHdoYXQgdG8gZG8gd2l0aCByZXNwb25zZSBjb2RlICcke3Jlc3BvbnNlLnN0YXR1c0NvZGV9JyBgICtcbiAgICAgICAgYGFuZCByZXNwb25zZSBib2R5ICcke18udHJ1bmNhdGUoSlNPTi5zdHJpbmdpZnkocmVzQm9keU9iaiksIHtcbiAgICAgICAgICBsZW5ndGg6IDMwMCxcbiAgICAgICAgfSl9J2BcbiAgICApO1xuICB9XG5cbiAgZ2V0U2Vzc2lvbklkRnJvbVVybCh1cmwpIHtcbiAgICBjb25zdCBtYXRjaCA9IHVybC5tYXRjaCgvXFwvc2Vzc2lvblxcLyhbXi9dKykvKTtcbiAgICByZXR1cm4gbWF0Y2ggPyBtYXRjaFsxXSA6IG51bGw7XG4gIH1cblxuICBhc3luYyBwcm94eVJlcVJlcyhyZXEsIHJlcykge1xuICAgIC8vICEgdGhpcyBtZXRob2QgbXVzdCBub3QgdGhyb3cgYW55IGV4Y2VwdGlvbnNcbiAgICAvLyAhIG1ha2Ugc3VyZSB0byBjYWxsIHJlcy5zZW5kIGJlZm9yZSByZXR1cm5cbiAgICBsZXQgc3RhdHVzQ29kZTtcbiAgICBsZXQgcmVzQm9keU9iajtcbiAgICB0cnkge1xuICAgICAgbGV0IHJlc3BvbnNlO1xuICAgICAgW3Jlc3BvbnNlLCByZXNCb2R5T2JqXSA9IGF3YWl0IHRoaXMucHJveHlDb21tYW5kKHJlcS5vcmlnaW5hbFVybCwgcmVxLm1ldGhvZCwgcmVxLmJvZHkpO1xuICAgICAgcmVzLmhlYWRlcnMgPSByZXNwb25zZS5oZWFkZXJzO1xuICAgICAgc3RhdHVzQ29kZSA9IHJlc3BvbnNlLnN0YXR1c0NvZGU7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBbc3RhdHVzQ29kZSwgcmVzQm9keU9ial0gPSBnZXRSZXNwb25zZUZvclczQ0Vycm9yKFxuICAgICAgICBpc0Vycm9yVHlwZShlcnIsIGVycm9ycy5Qcm94eVJlcXVlc3RFcnJvcikgPyBlcnIuZ2V0QWN0dWFsRXJyb3IoKSA6IGVyclxuICAgICAgKTtcbiAgICB9XG4gICAgcmVzLnNldCgnY29udGVudC10eXBlJywgJ2FwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9dXRmLTgnKTtcbiAgICBpZiAoIV8uaXNQbGFpbk9iamVjdChyZXNCb2R5T2JqKSkge1xuICAgICAgY29uc3QgZXJyb3IgPSBuZXcgZXJyb3JzLlVua25vd25FcnJvcihcbiAgICAgICAgYFRoZSBkb3duc3RyZWFtIHNlcnZlciByZXNwb25zZSB3aXRoIHRoZSBzdGF0dXMgY29kZSAke3N0YXR1c0NvZGV9IGlzIG5vdCBhIHZhbGlkIEpTT04gb2JqZWN0OiBgICtcbiAgICAgICAgICBfLnRydW5jYXRlKGAke3Jlc0JvZHlPYmp9YCwge2xlbmd0aDogMzAwfSlcbiAgICAgICk7XG4gICAgICBbc3RhdHVzQ29kZSwgcmVzQm9keU9ial0gPSBnZXRSZXNwb25zZUZvclczQ0Vycm9yKGVycm9yKTtcbiAgICB9XG5cbiAgICAvLyBpZiB0aGUgcHJveGllZCByZXNwb25zZSBjb250YWlucyBhIHNlc3Npb25JZCB0aGF0IHRoZSBkb3duc3RyZWFtXG4gICAgLy8gZHJpdmVyIGhhcyBnZW5lcmF0ZWQsIHdlIGRvbid0IHdhbnQgdG8gcmV0dXJuIHRoYXQgdG8gdGhlIGNsaWVudC5cbiAgICAvLyBJbnN0ZWFkLCByZXR1cm4gdGhlIGlkIGZyb20gdGhlIHJlcXVlc3Qgb3IgZnJvbSBjdXJyZW50IHNlc3Npb25cbiAgICBpZiAoXy5oYXMocmVzQm9keU9iaiwgJ3Nlc3Npb25JZCcpKSB7XG4gICAgICBjb25zdCByZXFTZXNzaW9uSWQgPSB0aGlzLmdldFNlc3Npb25JZEZyb21VcmwocmVxLm9yaWdpbmFsVXJsKTtcbiAgICAgIGlmIChyZXFTZXNzaW9uSWQpIHtcbiAgICAgICAgdGhpcy5sb2cuaW5mbyhgUmVwbGFjaW5nIHNlc3Npb25JZCAke3Jlc0JvZHlPYmouc2Vzc2lvbklkfSB3aXRoICR7cmVxU2Vzc2lvbklkfWApO1xuICAgICAgICByZXNCb2R5T2JqLnNlc3Npb25JZCA9IHJlcVNlc3Npb25JZDtcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXNzaW9uSWQpIHtcbiAgICAgICAgdGhpcy5sb2cuaW5mbyhgUmVwbGFjaW5nIHNlc3Npb25JZCAke3Jlc0JvZHlPYmouc2Vzc2lvbklkfSB3aXRoICR7dGhpcy5zZXNzaW9uSWR9YCk7XG4gICAgICAgIHJlc0JvZHlPYmouc2Vzc2lvbklkID0gdGhpcy5zZXNzaW9uSWQ7XG4gICAgICB9XG4gICAgfVxuICAgIHJlc0JvZHlPYmoudmFsdWUgPSBmb3JtYXRSZXNwb25zZVZhbHVlKHJlc0JvZHlPYmoudmFsdWUpO1xuICAgIHJlcy5zdGF0dXMoc3RhdHVzQ29kZSkuc2VuZChKU09OLnN0cmluZ2lmeShmb3JtYXRTdGF0dXMocmVzQm9keU9iaikpKTtcbiAgfVxufVxuXG5leHBvcnQge0pXUHJveHl9O1xuZXhwb3J0IGRlZmF1bHQgSldQcm94eTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7RXJyb3IgJiB7cmVzcG9uc2U6IHtkYXRhOiBpbXBvcnQoJ3R5cGUtZmVzdCcpLkpzb25PYmplY3QsIHN0YXR1czogaW1wb3J0KCdodHRwLXN0YXR1cy1jb2RlcycpLlN0YXR1c0NvZGVzfX19IFByb3h5RXJyb3JcbiAqL1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7QUFBQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFPQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUVBLE1BQU1BLFdBQVcsR0FBR0MsZUFBQSxDQUFPQyxTQUFQLENBQWlCLFVBQWpCLENBQXBCOztBQUNBLE1BQU1DLHVCQUF1QixHQUFHLE1BQWhDO0FBQ0EsTUFBTUMsc0JBQXNCLEdBQUcsQ0FBQyxrQkFBRCxFQUFxQixnQkFBckIsQ0FBL0I7QUFFQSxNQUFNO0VBQUNDLE9B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
377
+ exports.default = JWProxy;
378
+ /**
379
+ * @typedef {Error & {response: {data: import('type-fest').JsonObject, status: import('http-status-codes').StatusCodes}}} ProxyError
380
+ */
381
+ //# sourceMappingURL=proxy.js.map