webpeel 0.14.2 → 0.14.4

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 (107) hide show
  1. package/dist/cache.d.ts.map +1 -1
  2. package/dist/cache.js +11 -4
  3. package/dist/cache.js.map +1 -1
  4. package/dist/cli.bundle.cjs +159248 -0
  5. package/dist/cli.js +1 -1
  6. package/dist/cli.js.map +1 -1
  7. package/dist/core/agent.js +12 -8
  8. package/dist/core/agent.js.map +1 -1
  9. package/dist/core/application-tracker.js +3 -2
  10. package/dist/core/application-tracker.js.map +1 -1
  11. package/dist/core/auto-extract.js +6 -4
  12. package/dist/core/auto-extract.js.map +1 -1
  13. package/dist/core/browser-fetch.d.ts +90 -0
  14. package/dist/core/browser-fetch.d.ts.map +1 -0
  15. package/dist/core/browser-fetch.js +599 -0
  16. package/dist/core/browser-fetch.js.map +1 -0
  17. package/dist/core/browser-pool.d.ts +70 -0
  18. package/dist/core/browser-pool.d.ts.map +1 -0
  19. package/dist/core/browser-pool.js +378 -0
  20. package/dist/core/browser-pool.js.map +1 -0
  21. package/dist/core/change-tracking.js +3 -2
  22. package/dist/core/change-tracking.js.map +1 -1
  23. package/dist/core/diff.js +3 -2
  24. package/dist/core/diff.js.map +1 -1
  25. package/dist/core/domain-extractors.js +3 -2
  26. package/dist/core/domain-extractors.js.map +1 -1
  27. package/dist/core/extract-inline.js +6 -4
  28. package/dist/core/extract-inline.js.map +1 -1
  29. package/dist/core/fetcher.d.ts +9 -116
  30. package/dist/core/fetcher.d.ts.map +1 -1
  31. package/dist/core/fetcher.js +10 -1484
  32. package/dist/core/fetcher.js.map +1 -1
  33. package/dist/core/http-fetch.d.ts +37 -0
  34. package/dist/core/http-fetch.d.ts.map +1 -0
  35. package/dist/core/http-fetch.js +618 -0
  36. package/dist/core/http-fetch.js.map +1 -0
  37. package/dist/core/metadata.js +18 -12
  38. package/dist/core/metadata.js.map +1 -1
  39. package/dist/core/pipeline.d.ts +104 -0
  40. package/dist/core/pipeline.d.ts.map +1 -0
  41. package/dist/core/pipeline.js +623 -0
  42. package/dist/core/pipeline.js.map +1 -0
  43. package/dist/core/profiles.js +15 -10
  44. package/dist/core/profiles.js.map +1 -1
  45. package/dist/core/quick-answer.d.ts.map +1 -1
  46. package/dist/core/quick-answer.js +120 -9
  47. package/dist/core/quick-answer.js.map +1 -1
  48. package/dist/core/rate-governor.js +3 -2
  49. package/dist/core/rate-governor.js.map +1 -1
  50. package/dist/core/readability.d.ts.map +1 -1
  51. package/dist/core/readability.js +19 -6
  52. package/dist/core/readability.js.map +1 -1
  53. package/dist/core/research.js +9 -6
  54. package/dist/core/research.js.map +1 -1
  55. package/dist/core/search-provider.js +12 -8
  56. package/dist/core/search-provider.js.map +1 -1
  57. package/dist/core/strategies.d.ts.map +1 -1
  58. package/dist/core/strategies.js +14 -5
  59. package/dist/core/strategies.js.map +1 -1
  60. package/dist/core/timing.d.ts +22 -0
  61. package/dist/core/timing.d.ts.map +1 -0
  62. package/dist/core/timing.js +34 -0
  63. package/dist/core/timing.js.map +1 -0
  64. package/dist/core/youtube.d.ts.map +1 -1
  65. package/dist/core/youtube.js +19 -6
  66. package/dist/core/youtube.js.map +1 -1
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +13 -444
  70. package/dist/index.js.map +1 -1
  71. package/dist/mcp/server.js +1 -1
  72. package/dist/mcp/server.js.map +1 -1
  73. package/dist/server/middleware/auth.js +3 -2
  74. package/dist/server/middleware/auth.js.map +1 -1
  75. package/dist/server/routes/answer.d.ts.map +1 -1
  76. package/dist/server/routes/answer.js +5 -0
  77. package/dist/server/routes/answer.js.map +1 -1
  78. package/dist/server/routes/compat.js +3 -2
  79. package/dist/server/routes/compat.js.map +1 -1
  80. package/dist/server/routes/deep-fetch.d.ts.map +1 -1
  81. package/dist/server/routes/deep-fetch.js +5 -0
  82. package/dist/server/routes/deep-fetch.js.map +1 -1
  83. package/dist/server/routes/fetch.d.ts.map +1 -1
  84. package/dist/server/routes/fetch.js +44 -4
  85. package/dist/server/routes/fetch.js.map +1 -1
  86. package/dist/server/routes/health.js +3 -2
  87. package/dist/server/routes/health.js.map +1 -1
  88. package/dist/server/routes/mcp.js +1 -1
  89. package/dist/server/routes/mcp.js.map +1 -1
  90. package/dist/server/routes/quick-answer.d.ts.map +1 -1
  91. package/dist/server/routes/quick-answer.js +5 -0
  92. package/dist/server/routes/quick-answer.js.map +1 -1
  93. package/dist/server/routes/search.js +6 -4
  94. package/dist/server/routes/search.js.map +1 -1
  95. package/dist/server/routes/users.js +3 -2
  96. package/dist/server/routes/users.js.map +1 -1
  97. package/dist/server/routes/webhooks.d.ts +1 -0
  98. package/dist/server/routes/webhooks.d.ts.map +1 -1
  99. package/dist/server/routes/webhooks.js +1 -0
  100. package/dist/server/routes/webhooks.js.map +1 -1
  101. package/dist/server/routes/youtube.d.ts.map +1 -1
  102. package/dist/server/routes/youtube.js +5 -0
  103. package/dist/server/routes/youtube.js.map +1 -1
  104. package/dist/types.d.ts +2 -0
  105. package/dist/types.d.ts.map +1 -1
  106. package/dist/types.js.map +1 -1
  107. package/package.json +5 -2
@@ -0,0 +1,618 @@
1
+ /**
2
+ * Pure HTTP fetching — no browser dependencies.
3
+ * Handles connection pooling, conditional caching, SSRF validation, and simpleFetch.
4
+ */
5
+ // Force IPv4-first DNS resolution globally.
6
+ // Prevents IPv6 connection failures (TLS errors, timeouts) on hosts that
7
+ // advertise AAAA records but can't actually route IPv6 (e.g. Render containers).
8
+ // Must run before any network library is used.
9
+ import dns from 'dns';
10
+ dns.setDefaultResultOrder('ipv4first');
11
+ import { getRealisticUserAgent, getSecCHUA, getSecCHUAPlatform } from './user-agents.js';
12
+ import { fetch as undiciFetch, Agent, ProxyAgent } from 'undici';
13
+ import { TimeoutError, BlockedError, NetworkError, WebPeelError } from '../types.js';
14
+ import { getCached } from './cache.js';
15
+ import { cachedLookup, resolveAndCache, startDnsWarmup } from './dns-cache.js';
16
+ import { detectChallenge } from './challenge-detection.js';
17
+ // ── HTTP status text fallbacks (HTTP/2 omits reason phrases) ──────────────────
18
+ const HTTP_STATUS_TEXT = {
19
+ 400: 'Bad Request',
20
+ 401: 'Unauthorized',
21
+ 402: 'Payment Required',
22
+ 403: 'Forbidden',
23
+ 404: 'Not Found',
24
+ 405: 'Method Not Allowed',
25
+ 408: 'Request Timeout',
26
+ 410: 'Gone',
27
+ 429: 'Too Many Requests',
28
+ 451: 'Unavailable For Legal Reasons',
29
+ 500: 'Internal Server Error',
30
+ 502: 'Bad Gateway',
31
+ 503: 'Service Unavailable',
32
+ 504: 'Gateway Timeout',
33
+ 520: 'Unknown Error (Cloudflare)',
34
+ 521: 'Web Server Is Down (Cloudflare)',
35
+ 522: 'Connection Timed Out (Cloudflare)',
36
+ 523: 'Origin Is Unreachable (Cloudflare)',
37
+ 524: 'A Timeout Occurred (Cloudflare)',
38
+ 525: 'SSL Handshake Failed (Cloudflare)',
39
+ };
40
+ // ── HTTP connection pool ──────────────────────────────────────────────────────
41
+ function createHttpPool() {
42
+ return new Agent({
43
+ connections: 20,
44
+ pipelining: 6,
45
+ keepAliveTimeout: 60000,
46
+ keepAliveMaxTimeout: 60000,
47
+ allowH2: true,
48
+ connect: {
49
+ lookup: cachedLookup,
50
+ },
51
+ });
52
+ }
53
+ let httpPool = createHttpPool();
54
+ startDnsWarmup();
55
+ export async function closePool() {
56
+ const oldPool = httpPool;
57
+ httpPool = createHttpPool();
58
+ await oldPool.close().catch(() => { });
59
+ }
60
+ const CONDITIONAL_CACHE_MAX_ENTRIES = 2000;
61
+ const conditionalValidatorsByUrl = new Map();
62
+ function normalizeUrlForConditionalCache(url) {
63
+ try {
64
+ const normalized = new URL(url);
65
+ normalized.hash = '';
66
+ normalized.hostname = normalized.hostname.toLowerCase();
67
+ if ((normalized.protocol === 'http:' && normalized.port === '80') ||
68
+ (normalized.protocol === 'https:' && normalized.port === '443')) {
69
+ normalized.port = '';
70
+ }
71
+ if (!normalized.pathname) {
72
+ normalized.pathname = '/';
73
+ }
74
+ const sortedParams = [...normalized.searchParams.entries()]
75
+ .sort(([a], [b]) => a.localeCompare(b));
76
+ normalized.search = '';
77
+ for (const [key, value] of sortedParams) {
78
+ normalized.searchParams.append(key, value);
79
+ }
80
+ return normalized.toString();
81
+ }
82
+ catch (e) {
83
+ // Non-fatal: URL normalization failed, returning raw trimmed URL
84
+ if (process.env.DEBUG)
85
+ console.debug('[webpeel]', 'URL normalization:', e instanceof Error ? e.message : e);
86
+ return url.trim();
87
+ }
88
+ }
89
+ function getConditionalValidators(url) {
90
+ const key = normalizeUrlForConditionalCache(url);
91
+ const existing = conditionalValidatorsByUrl.get(key);
92
+ if (!existing) {
93
+ return null;
94
+ }
95
+ // LRU touch
96
+ conditionalValidatorsByUrl.delete(key);
97
+ conditionalValidatorsByUrl.set(key, existing);
98
+ return existing;
99
+ }
100
+ function setConditionalValidators(url, validators) {
101
+ const key = normalizeUrlForConditionalCache(url);
102
+ if (conditionalValidatorsByUrl.has(key)) {
103
+ conditionalValidatorsByUrl.delete(key);
104
+ }
105
+ conditionalValidatorsByUrl.set(key, validators);
106
+ while (conditionalValidatorsByUrl.size > CONDITIONAL_CACHE_MAX_ENTRIES) {
107
+ const oldestKey = conditionalValidatorsByUrl.keys().next().value;
108
+ if (!oldestKey) {
109
+ break;
110
+ }
111
+ conditionalValidatorsByUrl.delete(oldestKey);
112
+ }
113
+ }
114
+ function rememberConditionalValidators(url, response) {
115
+ const etag = response.headers.get('etag') || undefined;
116
+ const lastModified = response.headers.get('last-modified') || undefined;
117
+ if (!etag && !lastModified) {
118
+ return;
119
+ }
120
+ setConditionalValidators(url, { etag, lastModified });
121
+ }
122
+ function hasHeader(headers, name) {
123
+ const lowered = name.toLowerCase();
124
+ return Object.keys(headers).some((header) => header.toLowerCase() === lowered);
125
+ }
126
+ function getCachedResultFor304(url, fallbackUrl) {
127
+ const cached = getCached(url) || (fallbackUrl ? getCached(fallbackUrl) : null);
128
+ if (!cached) {
129
+ return null;
130
+ }
131
+ return {
132
+ html: cached.html,
133
+ buffer: cached.buffer,
134
+ url: cached.url || url,
135
+ statusCode: 304,
136
+ contentType: cached.contentType,
137
+ screenshot: cached.screenshot,
138
+ };
139
+ }
140
+ export function createAbortError() {
141
+ const error = new Error('Operation aborted');
142
+ error.name = 'AbortError';
143
+ return error;
144
+ }
145
+ // ── SSRF / URL validation ─────────────────────────────────────────────────────
146
+ /**
147
+ * SECURITY: Validate URL to prevent SSRF attacks
148
+ * Blocks localhost, private IPs, link-local, and various bypass techniques
149
+ */
150
+ export function validateUrl(urlString) {
151
+ // Length check
152
+ if (urlString.length > 2048) {
153
+ throw new WebPeelError('URL too long (max 2048 characters)');
154
+ }
155
+ // Check for control characters and suspicious encoding
156
+ if (/[\x00-\x1F\x7F]/.test(urlString)) {
157
+ throw new WebPeelError('URL contains invalid control characters');
158
+ }
159
+ let url;
160
+ try {
161
+ url = new URL(urlString);
162
+ }
163
+ catch {
164
+ throw new WebPeelError('Invalid URL format');
165
+ }
166
+ // Only allow HTTP(S)
167
+ if (!['http:', 'https:'].includes(url.protocol)) {
168
+ throw new WebPeelError('Only HTTP and HTTPS protocols are allowed');
169
+ }
170
+ // Validate hostname is not empty
171
+ if (!url.hostname) {
172
+ throw new WebPeelError('Invalid hostname');
173
+ }
174
+ const hostname = url.hostname.toLowerCase();
175
+ // Block localhost patterns
176
+ const localhostPatterns = ['localhost', '0.0.0.0'];
177
+ if (localhostPatterns.some(pattern => hostname === pattern || hostname.endsWith('.' + pattern))) {
178
+ throw new WebPeelError('Access to localhost is not allowed');
179
+ }
180
+ // ENHANCED: Parse and validate IP addresses (handles hex, octal, decimal, mixed)
181
+ const ipv4Info = parseAndValidateIPv4(hostname);
182
+ if (ipv4Info) {
183
+ validateIPv4Address(ipv4Info);
184
+ }
185
+ // ENHANCED: Comprehensive IPv6 validation
186
+ if (hostname.includes(':')) {
187
+ validateIPv6Address(hostname);
188
+ }
189
+ }
190
+ /**
191
+ * Parse IPv4 address in any format (dotted, hex, octal, decimal, mixed)
192
+ * Returns null if not an IPv4 address
193
+ */
194
+ function parseAndValidateIPv4(hostname) {
195
+ // Remove brackets if present
196
+ const cleaned = hostname.replace(/^\[|\]$/g, '');
197
+ // Standard dotted notation: 192.168.1.1
198
+ const dottedRegex = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
199
+ const dottedMatch = cleaned.match(dottedRegex);
200
+ if (dottedMatch) {
201
+ const octets = dottedMatch.slice(1).map(Number);
202
+ if (octets.every(o => o >= 0 && o <= 255)) {
203
+ return octets;
204
+ }
205
+ throw new WebPeelError('Invalid IPv4 address');
206
+ }
207
+ // Hex notation: 0x7f000001
208
+ if (/^0x[0-9a-fA-F]+$/.test(cleaned)) {
209
+ const num = parseInt(cleaned, 16);
210
+ return [
211
+ (num >>> 24) & 0xff,
212
+ (num >>> 16) & 0xff,
213
+ (num >>> 8) & 0xff,
214
+ num & 0xff,
215
+ ];
216
+ }
217
+ // Octal notation: 0177.0.0.1 or full octal 017700000001
218
+ if (/^0[0-7]/.test(cleaned)) {
219
+ // Full octal (all digits)
220
+ if (/^0[0-7]+$/.test(cleaned)) {
221
+ const num = parseInt(cleaned, 8);
222
+ if (num <= 0xffffffff) {
223
+ return [
224
+ (num >>> 24) & 0xff,
225
+ (num >>> 16) & 0xff,
226
+ (num >>> 8) & 0xff,
227
+ num & 0xff,
228
+ ];
229
+ }
230
+ }
231
+ // Mixed octal-decimal: 0177.0.0.1
232
+ const parts = cleaned.split('.');
233
+ if (parts.length === 4) {
234
+ const octets = parts.map(p => parseInt(p, /^0[0-7]/.test(p) ? 8 : 10));
235
+ if (octets.every(o => o >= 0 && o <= 255)) {
236
+ return octets;
237
+ }
238
+ }
239
+ }
240
+ // Decimal notation: 2130706433
241
+ if (/^\d+$/.test(cleaned)) {
242
+ const num = parseInt(cleaned, 10);
243
+ if (num <= 0xffffffff) {
244
+ return [
245
+ (num >>> 24) & 0xff,
246
+ (num >>> 16) & 0xff,
247
+ (num >>> 8) & 0xff,
248
+ num & 0xff,
249
+ ];
250
+ }
251
+ }
252
+ return null;
253
+ }
254
+ /**
255
+ * Validate IPv4 address against private/reserved ranges
256
+ */
257
+ function validateIPv4Address(octets) {
258
+ const [a, b, c, d] = octets;
259
+ // Loopback: 127.0.0.0/8
260
+ if (a === 127) {
261
+ throw new WebPeelError('Access to loopback addresses is not allowed');
262
+ }
263
+ // Private: 10.0.0.0/8
264
+ if (a === 10) {
265
+ throw new WebPeelError('Access to private IP addresses is not allowed');
266
+ }
267
+ // Private: 172.16.0.0/12
268
+ if (a === 172 && b >= 16 && b <= 31) {
269
+ throw new WebPeelError('Access to private IP addresses is not allowed');
270
+ }
271
+ // Private: 192.168.0.0/16
272
+ if (a === 192 && b === 168) {
273
+ throw new WebPeelError('Access to private IP addresses is not allowed');
274
+ }
275
+ // Link-local: 169.254.0.0/16
276
+ if (a === 169 && b === 254) {
277
+ throw new WebPeelError('Access to link-local addresses is not allowed');
278
+ }
279
+ // Broadcast: 255.255.255.255
280
+ if (a === 255 && b === 255 && c === 255 && d === 255) {
281
+ throw new WebPeelError('Access to broadcast address is not allowed');
282
+ }
283
+ // This network: 0.0.0.0/8
284
+ if (a === 0) {
285
+ throw new WebPeelError('Access to "this network" addresses is not allowed');
286
+ }
287
+ }
288
+ /**
289
+ * Validate IPv6 address against private/reserved ranges
290
+ */
291
+ function validateIPv6Address(hostname) {
292
+ // Remove brackets
293
+ const addr = hostname.replace(/^\[|\]$/g, '').toLowerCase();
294
+ // Loopback: ::1
295
+ if (addr === '::1' || addr === '0:0:0:0:0:0:0:1') {
296
+ throw new WebPeelError('Access to loopback addresses is not allowed');
297
+ }
298
+ // IPv6 mapped IPv4: ::ffff:192.168.1.1 or ::ffff:c0a8:0101
299
+ if (addr.startsWith('::ffff:')) {
300
+ // Extract the IPv4 part
301
+ const ipv4Part = addr.substring(7);
302
+ // Could be dotted (::ffff:192.168.1.1) or hex (::ffff:c0a8:0101)
303
+ if (ipv4Part.includes('.')) {
304
+ // Parse dotted IPv4
305
+ const parts = ipv4Part.split('.');
306
+ if (parts.length === 4) {
307
+ const octets = parts.map(p => parseInt(p, 10));
308
+ if (octets.every(o => !isNaN(o) && o >= 0 && o <= 255)) {
309
+ validateIPv4Address(octets);
310
+ }
311
+ }
312
+ }
313
+ else {
314
+ // Parse hex IPv4 (e.g., c0a80101 = 192.168.1.1)
315
+ const hexStr = ipv4Part.replace(/:/g, '');
316
+ if (/^[0-9a-f]{1,8}$/.test(hexStr)) {
317
+ const num = parseInt(hexStr, 16);
318
+ const octets = [
319
+ (num >>> 24) & 0xff,
320
+ (num >>> 16) & 0xff,
321
+ (num >>> 8) & 0xff,
322
+ num & 0xff,
323
+ ];
324
+ validateIPv4Address(octets);
325
+ }
326
+ }
327
+ throw new WebPeelError('Access to IPv6-mapped IPv4 addresses is not allowed');
328
+ }
329
+ // Unique local addresses: fc00::/7 (fc00:: to fdff::)
330
+ if (addr.startsWith('fc') || addr.startsWith('fd')) {
331
+ throw new WebPeelError('Access to unique local IPv6 addresses is not allowed');
332
+ }
333
+ // Link-local: fe80::/10
334
+ if (addr.startsWith('fe8') || addr.startsWith('fe9') ||
335
+ addr.startsWith('fea') || addr.startsWith('feb')) {
336
+ throw new WebPeelError('Access to link-local IPv6 addresses is not allowed');
337
+ }
338
+ }
339
+ /**
340
+ * Validate and sanitize user agent string
341
+ */
342
+ export function validateUserAgent(userAgent) {
343
+ if (userAgent.length > 500) {
344
+ throw new WebPeelError('User agent too long (max 500 characters)');
345
+ }
346
+ // Allow only printable ASCII characters
347
+ if (!/^[\x20-\x7E]*$/.test(userAgent)) {
348
+ throw new WebPeelError('User agent contains invalid characters');
349
+ }
350
+ return userAgent;
351
+ }
352
+ // ── simpleFetch ───────────────────────────────────────────────────────────────
353
+ /**
354
+ * Simple HTTP fetch using native fetch + Cheerio
355
+ * Fast and lightweight, but can be blocked by Cloudflare/bot detection
356
+ * SECURITY: Manual redirect handling with SSRF re-validation
357
+ */
358
+ export async function simpleFetch(url, userAgent, timeoutMs = 30000, customHeaders, abortSignal, proxy) {
359
+ // SECURITY: Validate URL to prevent SSRF
360
+ validateUrl(url);
361
+ if (abortSignal?.aborted) {
362
+ throw createAbortError();
363
+ }
364
+ // Validate user agent if provided
365
+ // SEC.gov requires a User-Agent with contact info (their documented automated access policy)
366
+ const hostname = new URL(url).hostname.toLowerCase();
367
+ const isSecGov = hostname === 'sec.gov' || hostname.endsWith('.sec.gov');
368
+ const validatedUserAgent = isSecGov
369
+ ? 'WebPeel/1.0 (support@webpeel.dev)'
370
+ : (userAgent ? validateUserAgent(userAgent) : getRealisticUserAgent());
371
+ // SECURITY: Merge custom headers with defaults, block Host header override
372
+ const defaultHeaders = {
373
+ 'User-Agent': validatedUserAgent,
374
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
375
+ 'Accept-Language': 'en-US,en;q=0.9',
376
+ 'Accept-Encoding': 'br, gzip, deflate',
377
+ 'DNT': '1',
378
+ 'Connection': 'keep-alive',
379
+ 'Upgrade-Insecure-Requests': '1',
380
+ 'Sec-CH-UA': getSecCHUA(validatedUserAgent),
381
+ 'Sec-CH-UA-Mobile': '?0',
382
+ 'Sec-CH-UA-Platform': getSecCHUAPlatform(validatedUserAgent),
383
+ 'Sec-Fetch-Dest': 'document',
384
+ 'Sec-Fetch-Mode': 'navigate',
385
+ 'Sec-Fetch-Site': 'none',
386
+ 'Sec-Fetch-User': '?1',
387
+ 'Cache-Control': 'max-age=0',
388
+ 'Priority': 'u=0, i',
389
+ };
390
+ const mergedHeaders = { ...defaultHeaders };
391
+ if (customHeaders) {
392
+ for (const [key, value] of Object.entries(customHeaders)) {
393
+ // SECURITY: Block Host header override
394
+ if (key.toLowerCase() === 'host') {
395
+ throw new WebPeelError('Custom Host header is not allowed');
396
+ }
397
+ mergedHeaders[key] = value;
398
+ }
399
+ }
400
+ const MAX_REDIRECTS = 10;
401
+ let redirectCount = 0;
402
+ let currentUrl = url;
403
+ const seenUrls = new Set();
404
+ try {
405
+ const hostname = new URL(url).hostname;
406
+ void resolveAndCache(hostname).catch(() => {
407
+ // Best-effort optimization only.
408
+ });
409
+ }
410
+ catch (e) {
411
+ // Ignore URL parsing errors here; validation handles invalid input below.
412
+ if (process.env.DEBUG)
413
+ console.debug('[webpeel]', 'DNS prefetch (initial URL):', e instanceof Error ? e.message : e);
414
+ }
415
+ while (redirectCount <= MAX_REDIRECTS) {
416
+ // Detect redirect loops
417
+ if (seenUrls.has(currentUrl)) {
418
+ throw new WebPeelError('Redirect loop detected');
419
+ }
420
+ seenUrls.add(currentUrl);
421
+ // Re-validate on each redirect
422
+ validateUrl(currentUrl);
423
+ const timeoutController = new AbortController();
424
+ const timer = setTimeout(() => timeoutController.abort(), timeoutMs);
425
+ const signal = abortSignal
426
+ ? AbortSignal.any([timeoutController.signal, abortSignal])
427
+ : timeoutController.signal;
428
+ try {
429
+ const requestHeaders = { ...mergedHeaders };
430
+ const validators = getConditionalValidators(currentUrl);
431
+ if (validators?.etag && !hasHeader(requestHeaders, 'if-none-match')) {
432
+ requestHeaders['If-None-Match'] = validators.etag;
433
+ }
434
+ if (validators?.lastModified && !hasHeader(requestHeaders, 'if-modified-since')) {
435
+ requestHeaders['If-Modified-Since'] = validators.lastModified;
436
+ }
437
+ // Use proxy if provided, otherwise use shared connection pool
438
+ const dispatcher = proxy ? new ProxyAgent(proxy) : httpPool;
439
+ const response = await undiciFetch(currentUrl, {
440
+ headers: requestHeaders,
441
+ signal,
442
+ dispatcher,
443
+ redirect: 'manual', // SECURITY: Manual redirect handling
444
+ });
445
+ clearTimeout(timer);
446
+ if (response.status === 304) {
447
+ const cachedResult = getCachedResultFor304(currentUrl, url);
448
+ if (cachedResult) {
449
+ return cachedResult;
450
+ }
451
+ throw new NetworkError('HTTP 304 received but no cached response is available');
452
+ }
453
+ // Handle redirects manually
454
+ if (response.status >= 300 && response.status < 400) {
455
+ const location = response.headers.get('location');
456
+ if (!location) {
457
+ throw new NetworkError('Redirect response missing Location header');
458
+ }
459
+ // Resolve relative URLs
460
+ currentUrl = new URL(location, currentUrl).href;
461
+ try {
462
+ const hostname = new URL(currentUrl).hostname;
463
+ void resolveAndCache(hostname).catch(() => {
464
+ // Best-effort optimization only.
465
+ });
466
+ }
467
+ catch (e) {
468
+ // Ignore URL parsing errors here; validation handles invalid input below.
469
+ if (process.env.DEBUG)
470
+ console.debug('[webpeel]', 'DNS prefetch (redirect URL):', e instanceof Error ? e.message : e);
471
+ }
472
+ redirectCount++;
473
+ continue;
474
+ }
475
+ if (!response.ok) {
476
+ if (response.status === 403 || response.status === 503) {
477
+ throw new BlockedError(`HTTP ${response.status}: Site may be blocking requests. Try --render for browser mode.`);
478
+ }
479
+ const statusText = response.statusText || HTTP_STATUS_TEXT[response.status] || 'Unknown Error';
480
+ throw new NetworkError(`HTTP ${response.status}: ${statusText}`);
481
+ }
482
+ rememberConditionalValidators(currentUrl, response);
483
+ // Content-Type detection
484
+ const contentType = response.headers.get('content-type') || '';
485
+ const contentTypeLower = contentType.toLowerCase();
486
+ const urlLower = currentUrl.toLowerCase();
487
+ // Support binary documents (PDF/DOCX) in the simple HTTP path.
488
+ const isPdf = contentTypeLower.includes('application/pdf') || urlLower.endsWith('.pdf');
489
+ const isDocx = contentTypeLower.includes('application/vnd.openxmlformats-officedocument.wordprocessingml.document') || urlLower.endsWith('.docx');
490
+ const isBinaryDoc = isPdf || isDocx;
491
+ // Accept a wide range of text-based content, plus supported binary documents.
492
+ const ALLOWED_TYPES = [
493
+ 'text/html', 'application/xhtml+xml',
494
+ 'text/plain', 'text/markdown', 'text/csv',
495
+ 'application/json', 'text/json',
496
+ 'text/xml', 'application/xml', 'application/rss+xml', 'application/atom+xml',
497
+ 'application/javascript', 'text/javascript', 'text/css',
498
+ // Documents
499
+ 'application/pdf',
500
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
501
+ ];
502
+ const isAllowed = !contentTypeLower ||
503
+ ALLOWED_TYPES.some(t => contentTypeLower.includes(t)) ||
504
+ // Many servers mislabel docs as octet-stream; allow when URL implies a supported document.
505
+ (contentTypeLower.includes('application/octet-stream') && isBinaryDoc);
506
+ if (!isAllowed) {
507
+ // Check if it's at least text-based
508
+ const isTexty = contentTypeLower.startsWith('text/') ||
509
+ contentTypeLower.includes('json') ||
510
+ contentTypeLower.includes('xml');
511
+ if (!isTexty) {
512
+ throw new WebPeelError(`Binary content type: ${contentType}. WebPeel handles text-based content and PDF/DOCX documents only.`);
513
+ }
514
+ }
515
+ // SECURITY: Stream response with size limit (prevent memory exhaustion)
516
+ const chunks = [];
517
+ let totalSize = 0;
518
+ const MAX_SIZE = 10 * 1024 * 1024; // 10MB
519
+ const reader = response.body?.getReader();
520
+ if (!reader) {
521
+ throw new NetworkError('Response body is not readable');
522
+ }
523
+ try {
524
+ while (true) {
525
+ const { done, value } = await reader.read();
526
+ if (done)
527
+ break;
528
+ totalSize += value.length;
529
+ if (totalSize > MAX_SIZE) {
530
+ reader.cancel();
531
+ throw new WebPeelError('Response too large (max 10MB)');
532
+ }
533
+ chunks.push(value);
534
+ }
535
+ }
536
+ finally {
537
+ reader.releaseLock();
538
+ }
539
+ // Combine chunks
540
+ const combined = new Uint8Array(totalSize);
541
+ let offset = 0;
542
+ for (const chunk of chunks) {
543
+ combined.set(chunk, offset);
544
+ offset += chunk.length;
545
+ }
546
+ const buffer = Buffer.from(combined);
547
+ const html = isBinaryDoc ? '' : new TextDecoder().decode(combined);
548
+ // For HTML content, check for suspiciously small responses (bot blocks)
549
+ // Non-HTML content (JSON, text, XML) can legitimately be short
550
+ const isHtmlContent = !isBinaryDoc && (contentTypeLower.includes('html') || contentTypeLower.includes('xhtml'));
551
+ if (isHtmlContent && (!html || html.length < 100)) {
552
+ throw new BlockedError('Empty or suspiciously small response. Site may require JavaScript.');
553
+ }
554
+ if (!isBinaryDoc && !html) {
555
+ throw new NetworkError('Empty response body');
556
+ }
557
+ if (isBinaryDoc && buffer.length === 0) {
558
+ throw new NetworkError('Empty response body');
559
+ }
560
+ // Check for Cloudflare challenge (only relevant for HTML)
561
+ if (isHtmlContent && (html.includes('cf-browser-verification') || html.includes('Just a moment...'))) {
562
+ throw new BlockedError('Cloudflare challenge detected. Try --render for browser mode.');
563
+ }
564
+ // Run full challenge detection for HTML content
565
+ // Note: skip empty-shell type — in simple HTTP mode, SPA shells are expected and
566
+ // the caller's escalation logic upgrades to browser/stealth rendering.
567
+ if (isHtmlContent) {
568
+ const challengeResult = detectChallenge(html, response.status);
569
+ if (challengeResult.isChallenge && challengeResult.type !== 'empty-shell') {
570
+ throw new BlockedError(`Challenge page detected (${challengeResult.type || 'unknown'}, confidence: ${challengeResult.confidence.toFixed(2)}). ` +
571
+ `Site requires human verification. Try a different approach or use a CAPTCHA solving service.`);
572
+ }
573
+ }
574
+ return {
575
+ html,
576
+ buffer: isBinaryDoc ? buffer : undefined,
577
+ url: currentUrl,
578
+ statusCode: response.status,
579
+ contentType,
580
+ };
581
+ }
582
+ catch (error) {
583
+ clearTimeout(timer);
584
+ if (error instanceof BlockedError || error instanceof NetworkError || error instanceof WebPeelError) {
585
+ throw error;
586
+ }
587
+ if (error instanceof Error && error.name === 'AbortError') {
588
+ if (abortSignal?.aborted && !timeoutController.signal.aborted) {
589
+ throw createAbortError();
590
+ }
591
+ throw new TimeoutError(`Request timed out after ${timeoutMs}ms`);
592
+ }
593
+ // Provide specific error messages based on the actual cause
594
+ const cause = error instanceof Error && error.cause;
595
+ const causeMsg = cause?.message || cause?.code || '';
596
+ if (causeMsg.includes('certificate') || causeMsg.includes('CERT') || causeMsg.includes('SSL') || causeMsg.includes('TLS')) {
597
+ throw new NetworkError(`TLS/SSL certificate error for ${new URL(currentUrl).hostname}. The site's certificate may be expired, self-signed, or untrusted.`);
598
+ }
599
+ if (causeMsg.includes('ENOTFOUND') || causeMsg.includes('getaddrinfo')) {
600
+ throw new NetworkError(`DNS resolution failed: ${new URL(currentUrl).hostname} not found. Check the URL or your network connection.`);
601
+ }
602
+ if (causeMsg.includes('ECONNREFUSED')) {
603
+ throw new NetworkError(`Connection refused by ${new URL(currentUrl).hostname}. The server may be down.`);
604
+ }
605
+ if (causeMsg.includes('ECONNRESET') || causeMsg.includes('EPIPE')) {
606
+ throw new NetworkError(`Connection reset by ${new URL(currentUrl).hostname}. Try again or use --render.`);
607
+ }
608
+ if (causeMsg.includes('ETIMEDOUT') || causeMsg.includes('ENETUNREACH')) {
609
+ throw new TimeoutError(`Network unreachable or connection timed out for ${new URL(currentUrl).hostname}.`);
610
+ }
611
+ const msg = error instanceof Error ? error.message : 'Unknown error';
612
+ const causeDetail = causeMsg ? ` (${causeMsg})` : '';
613
+ throw new NetworkError(`Failed to fetch: ${msg}${causeDetail}`);
614
+ }
615
+ }
616
+ throw new WebPeelError(`Too many redirects (max ${MAX_REDIRECTS})`);
617
+ }
618
+ //# sourceMappingURL=http-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-fetch.js","sourceRoot":"","sources":["../../src/core/http-fetch.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,4CAA4C;AAC5C,yEAAyE;AACzE,iFAAiF;AACjF,+CAA+C;AAC/C,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,GAAG,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;AAEvC,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,KAAK,EAAE,UAAU,EAAiB,MAAM,QAAQ,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,iFAAiF;AAEjF,MAAM,gBAAgB,GAA2B;IAC/C,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,cAAc;IACnB,GAAG,EAAE,kBAAkB;IACvB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,WAAW;IAChB,GAAG,EAAE,oBAAoB;IACzB,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,MAAM;IACX,GAAG,EAAE,mBAAmB;IACxB,GAAG,EAAE,+BAA+B;IACpC,GAAG,EAAE,uBAAuB;IAC5B,GAAG,EAAE,aAAa;IAClB,GAAG,EAAE,qBAAqB;IAC1B,GAAG,EAAE,iBAAiB;IACtB,GAAG,EAAE,4BAA4B;IACjC,GAAG,EAAE,iCAAiC;IACtC,GAAG,EAAE,mCAAmC;IACxC,GAAG,EAAE,oCAAoC;IACzC,GAAG,EAAE,iCAAiC;IACtC,GAAG,EAAE,mCAAmC;CACzC,CAAC;AAEF,iFAAiF;AAEjF,SAAS,cAAc;IACrB,OAAO,IAAI,KAAK,CAAC;QACf,WAAW,EAAE,EAAE;QACf,UAAU,EAAE,CAAC;QACb,gBAAgB,EAAE,KAAK;QACvB,mBAAmB,EAAE,KAAK;QAC1B,OAAO,EAAE,IAAI;QACb,OAAO,EAAE;YACP,MAAM,EAAE,YAAqB;SAC9B;KACF,CAAC,CAAC;AACL,CAAC;AAED,IAAI,QAAQ,GAAG,cAAc,EAAE,CAAC;AAChC,cAAc,EAAE,CAAC;AAEjB,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,OAAO,GAAG,QAAQ,CAAC;IACzB,QAAQ,GAAG,cAAc,EAAE,CAAC;IAC5B,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACxC,CAAC;AASD,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAC3C,MAAM,0BAA0B,GAAG,IAAI,GAAG,EAAiC,CAAC;AAE5E,SAAS,+BAA+B,CAAC,GAAW;IAClD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAChC,UAAU,CAAC,IAAI,GAAG,EAAE,CAAC;QACrB,UAAU,CAAC,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAExD,IAAI,CAAC,UAAU,CAAC,QAAQ,KAAK,OAAO,IAAI,UAAU,CAAC,IAAI,KAAK,IAAI,CAAC;YAC7D,CAAC,UAAU,CAAC,QAAQ,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YACpE,UAAU,CAAC,IAAI,GAAG,EAAE,CAAC;QACvB,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;YACzB,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC;QAC5B,CAAC;QAED,MAAM,YAAY,GAAG,CAAC,GAAG,UAAU,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;aACxD,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,YAAY,EAAE,CAAC;YACxC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7C,CAAC;QAED,OAAO,UAAU,CAAC,QAAQ,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,iEAAiE;QACjE,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK;YAAE,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,oBAAoB,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5G,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,GAAW;IAC3C,MAAM,GAAG,GAAG,+BAA+B,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,YAAY;IACZ,0BAA0B,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACvC,0BAA0B,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC9C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,wBAAwB,CAAC,GAAW,EAAE,UAAiC;IAC9E,MAAM,GAAG,GAAG,+BAA+B,CAAC,GAAG,CAAC,CAAC;IAEjD,IAAI,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACxC,0BAA0B,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,0BAA0B,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAEhD,OAAO,0BAA0B,CAAC,IAAI,GAAG,6BAA6B,EAAE,CAAC;QACvE,MAAM,SAAS,GAAG,0BAA0B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QACjE,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM;QACR,CAAC;QACD,0BAA0B,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,SAAS,6BAA6B,CAAC,GAAW,EAAE,QAAkB;IACpE,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC;IACvD,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,SAAS,CAAC;IAExE,IAAI,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,wBAAwB,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,SAAS,CAAC,OAA+B,EAAE,IAAY;IAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,OAAO,CAAC,CAAC;AACjF,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAW,EAAE,WAAoB;IAC9D,MAAM,MAAM,GAAG,SAAS,CAAc,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAc,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACzG,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,GAAG,EAAE,MAAM,CAAC,GAAG,IAAI,GAAG;QACtB,UAAU,EAAE,GAAG;QACf,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,GAAG,YAAY,CAAC;IAC1B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,eAAe;IACf,IAAI,SAAS,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,YAAY,CAAC,oCAAoC,CAAC,CAAC;IAC/D,CAAC;IAED,uDAAuD;IACvD,IAAI,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,YAAY,CAAC,yCAAyC,CAAC,CAAC;IACpE,CAAC;IAED,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,YAAY,CAAC,oBAAoB,CAAC,CAAC;IAC/C,CAAC;IAED,qBAAqB;IACrB,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,YAAY,CAAC,2CAA2C,CAAC,CAAC;IACtE,CAAC;IAED,iCAAiC;IACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAClB,MAAM,IAAI,YAAY,CAAC,kBAAkB,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAE5C,2BAA2B;IAC3B,MAAM,iBAAiB,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACnD,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,KAAK,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;QAChG,MAAM,IAAI,YAAY,CAAC,oCAAoC,CAAC,CAAC;IAC/D,CAAC;IAED,iFAAiF;IACjF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IAChD,IAAI,QAAQ,EAAE,CAAC;QACb,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,0CAA0C;IAC1C,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3B,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAAC,QAAgB;IAC5C,6BAA6B;IAC7B,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAEjD,wCAAwC;IACxC,MAAM,WAAW,GAAG,8CAA8C,CAAC;IACnE,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChD,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC1C,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,IAAI,YAAY,CAAC,sBAAsB,CAAC,CAAC;IACjD,CAAC;IAED,2BAA2B;IAC3B,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAClC,OAAO;YACL,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI;YACnB,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI;YACnB,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI;YAClB,GAAG,GAAG,IAAI;SACX,CAAC;IACJ,CAAC;IAED,wDAAwD;IACxD,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,0BAA0B;QAC1B,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACjC,IAAI,GAAG,IAAI,UAAU,EAAE,CAAC;gBACtB,OAAO;oBACL,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI;oBACnB,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI;oBACnB,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI;oBAClB,GAAG,GAAG,IAAI;iBACX,CAAC;YACJ,CAAC;QACH,CAAC;QACD,kCAAkC;QAClC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACvE,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC1C,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;IACH,CAAC;IAED,+BAA+B;IAC/B,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAClC,IAAI,GAAG,IAAI,UAAU,EAAE,CAAC;YACtB,OAAO;gBACL,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI;gBACnB,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI;gBACnB,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI;gBAClB,GAAG,GAAG,IAAI;aACX,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,MAAgB;IAC3C,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC;IAE5B,wBAAwB;IACxB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QACd,MAAM,IAAI,YAAY,CAAC,6CAA6C,CAAC,CAAC;IACxE,CAAC;IAED,sBAAsB;IACtB,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QACb,MAAM,IAAI,YAAY,CAAC,+CAA+C,CAAC,CAAC;IAC1E,CAAC;IAED,yBAAyB;IACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,YAAY,CAAC,+CAA+C,CAAC,CAAC;IAC1E,CAAC;IAED,0BAA0B;IAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAC3B,MAAM,IAAI,YAAY,CAAC,+CAA+C,CAAC,CAAC;IAC1E,CAAC;IAED,6BAA6B;IAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAC3B,MAAM,IAAI,YAAY,CAAC,+CAA+C,CAAC,CAAC;IAC1E,CAAC;IAED,6BAA6B;IAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QACrD,MAAM,IAAI,YAAY,CAAC,4CAA4C,CAAC,CAAC;IACvE,CAAC;IAED,0BAA0B;IAC1B,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACZ,MAAM,IAAI,YAAY,CAAC,mDAAmD,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,kBAAkB;IAClB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAE5D,gBAAgB;IAChB,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,iBAAiB,EAAE,CAAC;QACjD,MAAM,IAAI,YAAY,CAAC,6CAA6C,CAAC,CAAC;IACxE,CAAC;IAED,2DAA2D;IAC3D,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,wBAAwB;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QAEnC,iEAAiE;QACjE,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,oBAAoB;YACpB,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC/C,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;oBACvD,mBAAmB,CAAC,MAAM,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,gDAAgD;YAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBACjC,MAAM,MAAM,GAAG;oBACb,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI;oBACnB,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI;oBACnB,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,IAAI;oBAClB,GAAG,GAAG,IAAI;iBACX,CAAC;gBACF,mBAAmB,CAAC,MAAM,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;QACD,MAAM,IAAI,YAAY,CAAC,qDAAqD,CAAC,CAAC;IAChF,CAAC;IAED,sDAAsD;IACtD,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,YAAY,CAAC,sDAAsD,CAAC,CAAC;IACjF,CAAC;IAED,wBAAwB;IACxB,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,YAAY,CAAC,oDAAoD,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,IAAI,SAAS,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC3B,MAAM,IAAI,YAAY,CAAC,0CAA0C,CAAC,CAAC;IACrE,CAAC;IACD,wCAAwC;IACxC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,YAAY,CAAC,wCAAwC,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAoBD,iFAAiF;AAEjF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,GAAW,EACX,SAAkB,EAClB,YAAoB,KAAK,EACzB,aAAsC,EACtC,WAAyB,EACzB,KAAc;IAEd,yCAAyC;IACzC,WAAW,CAAC,GAAG,CAAC,CAAC;IAEjB,IAAI,WAAW,EAAE,OAAO,EAAE,CAAC;QACzB,MAAM,gBAAgB,EAAE,CAAC;IAC3B,CAAC;IAED,kCAAkC;IAClC,6FAA6F;IAC7F,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrD,MAAM,QAAQ,GAAG,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACzE,MAAM,kBAAkB,GAAG,QAAQ;QACjC,CAAC,CAAC,mCAAmC;QACrC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,qBAAqB,EAAE,CAAC,CAAC;IAEzE,2EAA2E;IAC3E,MAAM,cAAc,GAA2B;QAC7C,YAAY,EAAE,kBAAkB;QAChC,QAAQ,EAAE,yIAAyI;QACnJ,iBAAiB,EAAE,gBAAgB;QACnC,iBAAiB,EAAE,mBAAmB;QACtC,KAAK,EAAE,GAAG;QACV,YAAY,EAAE,YAAY;QAC1B,2BAA2B,EAAE,GAAG;QAChC,WAAW,EAAE,UAAU,CAAC,kBAAkB,CAAC;QAC3C,kBAAkB,EAAE,IAAI;QACxB,oBAAoB,EAAE,kBAAkB,CAAC,kBAAkB,CAAC;QAC5D,gBAAgB,EAAE,UAAU;QAC5B,gBAAgB,EAAE,UAAU;QAC5B,gBAAgB,EAAE,MAAM;QACxB,gBAAgB,EAAE,IAAI;QACtB,eAAe,EAAE,WAAW;QAC5B,UAAU,EAAE,QAAQ;KACrB,CAAC;IAEF,MAAM,aAAa,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC;IAE5C,IAAI,aAAa,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YACzD,uCAAuC;YACvC,IAAI,GAAG,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;gBACjC,MAAM,IAAI,YAAY,CAAC,mCAAmC,CAAC,CAAC;YAC9D,CAAC;YACD,aAAa,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,MAAM,aAAa,GAAG,EAAE,CAAC;IACzB,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,UAAU,GAAG,GAAG,CAAC;IACrB,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACvC,KAAK,eAAe,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACxC,iCAAiC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,0EAA0E;QAC1E,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK;YAAE,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,6BAA6B,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvH,CAAC;IAED,OAAO,aAAa,IAAI,aAAa,EAAE,CAAC;QACtC,wBAAwB;QACxB,IAAI,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,YAAY,CAAC,wBAAwB,CAAC,CAAC;QACnD,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAEzB,+BAA+B;QAC/B,WAAW,CAAC,UAAU,CAAC,CAAC;QAExB,MAAM,iBAAiB,GAAG,IAAI,eAAe,EAAE,CAAC;QAChD,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,WAAW;YACxB,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YAC1D,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC;QAE7B,IAAI,CAAC;YACH,MAAM,cAAc,GAA2B,EAAE,GAAG,aAAa,EAAE,CAAC;YACpE,MAAM,UAAU,GAAG,wBAAwB,CAAC,UAAU,CAAC,CAAC;YACxD,IAAI,UAAU,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,eAAe,CAAC,EAAE,CAAC;gBACpE,cAAc,CAAC,eAAe,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC;YACpD,CAAC;YACD,IAAI,UAAU,EAAE,YAAY,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,mBAAmB,CAAC,EAAE,CAAC;gBAChF,cAAc,CAAC,mBAAmB,CAAC,GAAG,UAAU,CAAC,YAAY,CAAC;YAChE,CAAC;YAED,8DAA8D;YAC9D,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YAE5D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE;gBAC7C,OAAO,EAAE,cAAc;gBACvB,MAAM;gBACN,UAAU;gBACV,QAAQ,EAAE,QAAQ,EAAE,qCAAqC;aAC1D,CAAC,CAAC;YAEH,YAAY,CAAC,KAAK,CAAC,CAAC;YAEpB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,YAAY,GAAG,qBAAqB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;gBAC5D,IAAI,YAAY,EAAE,CAAC;oBACjB,OAAO,YAAY,CAAC;gBACtB,CAAC;gBAED,MAAM,IAAI,YAAY,CAAC,uDAAuD,CAAC,CAAC;YAClF,CAAC;YAED,4BAA4B;YAC5B,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACpD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;gBAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,MAAM,IAAI,YAAY,CAAC,2CAA2C,CAAC,CAAC;gBACtE,CAAC;gBAED,wBAAwB;gBACxB,UAAU,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC;gBAChD,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC;oBAC9C,KAAK,eAAe,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;wBACxC,iCAAiC;oBACnC,CAAC,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,0EAA0E;oBAC1E,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK;wBAAE,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,8BAA8B,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACxH,CAAC;gBACD,aAAa,EAAE,CAAC;gBAChB,SAAS;YACX,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBACvD,MAAM,IAAI,YAAY,CACpB,QAAQ,QAAQ,CAAC,MAAM,iEAAiE,CACzF,CAAC;gBACJ,CAAC;gBACD,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,IAAI,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC;gBAC/F,MAAM,IAAI,YAAY,CAAC,QAAQ,QAAQ,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC,CAAC;YACnE,CAAC;YAED,6BAA6B,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAEpD,yBAAyB;YACzB,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAC/D,MAAM,gBAAgB,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YAE1C,+DAA+D;YAC/D,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YACxF,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,yEAAyE,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAClJ,MAAM,WAAW,GAAG,KAAK,IAAI,MAAM,CAAC;YAEpC,8EAA8E;YAC9E,MAAM,aAAa,GAAG;gBACpB,WAAW,EAAE,uBAAuB;gBACpC,YAAY,EAAE,eAAe,EAAE,UAAU;gBACzC,kBAAkB,EAAE,WAAW;gBAC/B,UAAU,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,sBAAsB;gBAC5E,wBAAwB,EAAE,iBAAiB,EAAE,UAAU;gBACvD,YAAY;gBACZ,iBAAiB;gBACjB,yEAAyE;aAC1E,CAAC;YAEF,MAAM,SAAS,GACb,CAAC,gBAAgB;gBACjB,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACrD,2FAA2F;gBAC3F,CAAC,gBAAgB,CAAC,QAAQ,CAAC,0BAA0B,CAAC,IAAI,WAAW,CAAC,CAAC;YAEzE,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,oCAAoC;gBACpC,MAAM,OAAO,GACX,gBAAgB,CAAC,UAAU,CAAC,OAAO,CAAC;oBACpC,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC;oBACjC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAEnC,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,MAAM,IAAI,YAAY,CAAC,wBAAwB,WAAW,mEAAmE,CAAC,CAAC;gBACjI,CAAC;YACH,CAAC;YAED,wEAAwE;YACxE,MAAM,MAAM,GAAiB,EAAE,CAAC;YAChC,IAAI,SAAS,GAAG,CAAC,CAAC;YAClB,MAAM,QAAQ,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;YAE1C,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,YAAY,CAAC,+BAA+B,CAAC,CAAC;YAC1D,CAAC;YAED,IAAI,CAAC;gBACH,OAAO,IAAI,EAAE,CAAC;oBACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;oBAC5C,IAAI,IAAI;wBAAE,MAAM;oBAEhB,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC;oBAC1B,IAAI,SAAS,GAAG,QAAQ,EAAE,CAAC;wBACzB,MAAM,CAAC,MAAM,EAAE,CAAC;wBAChB,MAAM,IAAI,YAAY,CAAC,+BAA+B,CAAC,CAAC;oBAC1D,CAAC;oBAED,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,CAAC;YAED,iBAAiB;YACjB,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC;YAC3C,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;YACzB,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAEnE,wEAAwE;YACxE,+DAA+D;YAC/D,MAAM,aAAa,GAAG,CAAC,WAAW,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;YAChH,IAAI,aAAa,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC;gBAClD,MAAM,IAAI,YAAY,CAAC,oEAAoE,CAAC,CAAC;YAC/F,CAAC;YAED,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC1B,MAAM,IAAI,YAAY,CAAC,qBAAqB,CAAC,CAAC;YAChD,CAAC;YAED,IAAI,WAAW,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvC,MAAM,IAAI,YAAY,CAAC,qBAAqB,CAAC,CAAC;YAChD,CAAC;YAED,0DAA0D;YAC1D,IAAI,aAAa,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC;gBACrG,MAAM,IAAI,YAAY,CAAC,+DAA+D,CAAC,CAAC;YAC1F,CAAC;YAED,gDAAgD;YAChD,iFAAiF;YACjF,uEAAuE;YACvE,IAAI,aAAa,EAAE,CAAC;gBAClB,MAAM,eAAe,GAAG,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC/D,IAAI,eAAe,CAAC,WAAW,IAAI,eAAe,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;oBAC1E,MAAM,IAAI,YAAY,CACpB,4BAA4B,eAAe,CAAC,IAAI,IAAI,SAAS,iBAAiB,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK;wBACxH,8FAA8F,CAC/F,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,OAAO;gBACL,IAAI;gBACJ,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;gBACxC,GAAG,EAAE,UAAU;gBACf,UAAU,EAAE,QAAQ,CAAC,MAAM;gBAC3B,WAAW;aACZ,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YAEpB,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,YAAY,YAAY,IAAI,KAAK,YAAY,YAAY,EAAE,CAAC;gBACpG,MAAM,KAAK,CAAC;YACd,CAAC;YAED,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC1D,IAAI,WAAW,EAAE,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;oBAC9D,MAAM,gBAAgB,EAAE,CAAC;gBAC3B,CAAC;gBACD,MAAM,IAAI,YAAY,CAAC,2BAA2B,SAAS,IAAI,CAAC,CAAC;YACnE,CAAC;YAED,4DAA4D;YAC5D,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,IAAK,KAAa,CAAC,KAAK,CAAC;YAC7D,MAAM,QAAQ,GAAG,KAAK,EAAE,OAAO,IAAI,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC;YAErD,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC1H,MAAM,IAAI,YAAY,CAAC,iCAAiC,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,QAAQ,qEAAqE,CAAC,CAAC;YAC7J,CAAC;YACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACvE,MAAM,IAAI,YAAY,CAAC,0BAA0B,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,QAAQ,uDAAuD,CAAC,CAAC;YACxI,CAAC;YACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,YAAY,CAAC,yBAAyB,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,QAAQ,2BAA2B,CAAC,CAAC;YAC3G,CAAC;YACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAClE,MAAM,IAAI,YAAY,CAAC,uBAAuB,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,QAAQ,8BAA8B,CAAC,CAAC;YAC5G,CAAC;YACD,IAAI,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACvE,MAAM,IAAI,YAAY,CAAC,mDAAmD,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC;YAC7G,CAAC;YAED,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;YACrE,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,YAAY,CAAC,oBAAoB,GAAG,GAAG,WAAW,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,MAAM,IAAI,YAAY,CAAC,2BAA2B,aAAa,GAAG,CAAC,CAAC;AACtE,CAAC"}