@purepageio/fetch-engines 0.1.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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/dist/FetchEngine.d.ts +46 -0
  4. package/dist/FetchEngine.d.ts.map +1 -0
  5. package/dist/FetchEngine.js +137 -0
  6. package/dist/FetchEngine.js.map +1 -0
  7. package/dist/FetchEngine.test.d.ts +2 -0
  8. package/dist/FetchEngine.test.d.ts.map +1 -0
  9. package/dist/FetchEngine.test.js +44 -0
  10. package/dist/FetchEngine.test.js.map +1 -0
  11. package/dist/HybridEngine.d.ts +15 -0
  12. package/dist/HybridEngine.d.ts.map +1 -0
  13. package/dist/HybridEngine.js +45 -0
  14. package/dist/HybridEngine.js.map +1 -0
  15. package/dist/IEngine.d.ts +22 -0
  16. package/dist/IEngine.d.ts.map +1 -0
  17. package/dist/IEngine.js +2 -0
  18. package/dist/IEngine.js.map +1 -0
  19. package/dist/PlaywrightEngine.d.ts +88 -0
  20. package/dist/PlaywrightEngine.d.ts.map +1 -0
  21. package/dist/PlaywrightEngine.js +484 -0
  22. package/dist/PlaywrightEngine.js.map +1 -0
  23. package/dist/PlaywrightEngine.test.d.ts +2 -0
  24. package/dist/PlaywrightEngine.test.d.ts.map +1 -0
  25. package/dist/PlaywrightEngine.test.js +299 -0
  26. package/dist/PlaywrightEngine.test.js.map +1 -0
  27. package/dist/PuppeteerEngine.d.ts +21 -0
  28. package/dist/PuppeteerEngine.d.ts.map +1 -0
  29. package/dist/PuppeteerEngine.js +412 -0
  30. package/dist/PuppeteerEngine.js.map +1 -0
  31. package/dist/browser/BrowserPool.d.ts +29 -0
  32. package/dist/browser/BrowserPool.d.ts.map +1 -0
  33. package/dist/browser/BrowserPool.js +378 -0
  34. package/dist/browser/BrowserPool.js.map +1 -0
  35. package/dist/browser/PlaywrightBrowserPool.d.ts +78 -0
  36. package/dist/browser/PlaywrightBrowserPool.d.ts.map +1 -0
  37. package/dist/browser/PlaywrightBrowserPool.js +429 -0
  38. package/dist/browser/PlaywrightBrowserPool.js.map +1 -0
  39. package/dist/browser/PlaywrightBrowserPool.test.d.ts +2 -0
  40. package/dist/browser/PlaywrightBrowserPool.test.d.ts.map +1 -0
  41. package/dist/browser/PlaywrightBrowserPool.test.js +422 -0
  42. package/dist/browser/PlaywrightBrowserPool.test.js.map +1 -0
  43. package/dist/errors.d.ts +20 -0
  44. package/dist/errors.d.ts.map +1 -0
  45. package/dist/errors.js +30 -0
  46. package/dist/errors.js.map +1 -0
  47. package/dist/index.d.ts +8 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +5 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/types.d.ts +151 -0
  52. package/dist/types.d.ts.map +1 -0
  53. package/dist/types.js +2 -0
  54. package/dist/types.js.map +1 -0
  55. package/package.json +72 -0
@@ -0,0 +1,378 @@
1
+ import { chromium } from "playwright";
2
+ // Puppeteer-extra and stealth plugin are removed as Playwright handles this differently or it's not directly needed.
3
+ export class BrowserPool {
4
+ pool = [];
5
+ maxBrowsers;
6
+ maxPagesPerBrowser; // This might map to pages per context in Playwright
7
+ maxBrowserAge; // Max age in ms
8
+ healthCheckInterval; // Interval in ms
9
+ healthCheckTimer;
10
+ maxIdleTime = 5 * 60 * 1000; // 5 minutes idle timeout
11
+ isCleaningUp = false; // Flag to prevent operations during cleanup
12
+ constructor(maxBrowsers = 2, maxPagesPerBrowser = 4, // Revisit how this limit is applied with Playwright contexts
13
+ maxBrowserAge = 30 * 60 * 1000, // 30 minutes
14
+ healthCheckInterval = 30 * 1000 // 30 seconds
15
+ ) {
16
+ this.maxBrowsers = maxBrowsers;
17
+ this.maxPagesPerBrowser = maxPagesPerBrowser;
18
+ this.maxBrowserAge = maxBrowserAge;
19
+ this.healthCheckInterval = healthCheckInterval;
20
+ // Initialization moved to async initialize() method
21
+ }
22
+ // Create a Playwright Browser (using Chromium for now)
23
+ async createBrowser() {
24
+ console.log("Creating new Playwright browser instance (Chromium)...");
25
+ // Map Puppeteer args to Playwright launch options where applicable
26
+ const options = {
27
+ headless: true,
28
+ args: [
29
+ "--no-sandbox",
30
+ "--disable-setuid-sandbox",
31
+ "--disable-dev-shm-usage",
32
+ "--disable-gpu",
33
+ // Playwright manages many flags automatically, fewer needed explicitly
34
+ "--mute-audio",
35
+ "--disable-background-networking",
36
+ "--disable-background-timer-throttling",
37
+ "--disable-breakpad",
38
+ "--disable-client-side-phishing-detection",
39
+ "--disable-component-update",
40
+ "--disable-default-apps",
41
+ "--disable-domain-reliability",
42
+ "--disable-features=AudioServiceOutOfProcess",
43
+ "--disable-hang-monitor",
44
+ "--disable-ipc-flooding-protection",
45
+ "--disable-notifications",
46
+ "--disable-offer-store-unmasked-wallet-cards",
47
+ "--disable-popup-blocking",
48
+ "--disable-print-preview",
49
+ "--disable-prompt-on-repost",
50
+ "--disable-renderer-backgrounding",
51
+ "--disable-sync",
52
+ "--disable-translate",
53
+ "--metrics-recording-only",
54
+ "--no-default-browser-check",
55
+ "--password-store=basic",
56
+ "--use-mock-keychain",
57
+ ],
58
+ // Consider proxy settings, viewport, user agent etc. if needed
59
+ };
60
+ let browser;
61
+ try {
62
+ // Launch Chromium browser using Playwright
63
+ browser = await chromium.launch(options);
64
+ }
65
+ catch (launchError) {
66
+ console.error("Playwright launch failed:", launchError);
67
+ throw launchError; // Re-throw after logging
68
+ }
69
+ // Create a default context for simplicity, could manage multiple contexts later
70
+ const context = await browser.newContext();
71
+ const instance = {
72
+ browser,
73
+ context, // Store the context
74
+ metrics: {
75
+ id: `playwright-${Date.now()}-${Math.random().toString(16).slice(2)}`, // Unique ID for Playwright
76
+ pagesCreated: 0,
77
+ activePages: 0,
78
+ lastUsed: new Date(),
79
+ errors: 0,
80
+ totalRequests: 0,
81
+ avgResponseTime: 0,
82
+ createdAt: new Date(),
83
+ isHealthy: true,
84
+ engine: "playwright", // Identify engine as Playwright
85
+ },
86
+ isHealthy: true,
87
+ };
88
+ console.log(`Playwright browser instance created (ID: ${instance.metrics.id})`);
89
+ // Handle disconnection gracefully using Playwright's event
90
+ browser.on("disconnected", () => {
91
+ console.warn(`Browser disconnected (ID: ${instance.metrics.id}), marking as unhealthy.`);
92
+ instance.isHealthy = false;
93
+ instance.metrics.isHealthy = false; // Ensure metric reflects state
94
+ // Health check will handle removal
95
+ });
96
+ return instance;
97
+ }
98
+ // Close browser and its context
99
+ async closeAndRemoveBrowser(instance) {
100
+ if (!instance || this.isCleaningUp)
101
+ return; // Prevent removal during cleanup
102
+ console.log(`Closing and removing browser instance (ID: ${instance.metrics.id})`);
103
+ // Remove from pool immediately to prevent reuse
104
+ this.pool = this.pool.filter((b) => b !== instance);
105
+ try {
106
+ // Ensure context is closed before browser
107
+ if (instance.context) {
108
+ await instance.context.close();
109
+ }
110
+ await instance.browser.close();
111
+ console.log(`Browser instance (ID: ${instance.metrics.id}) closed successfully.`);
112
+ }
113
+ catch (error) {
114
+ console.error(`Error closing browser (ID: ${instance.metrics.id}):`, error);
115
+ // Mark as unhealthy even if close fails, though it's already removed from pool
116
+ instance.isHealthy = false;
117
+ instance.metrics.isHealthy = false;
118
+ }
119
+ // Attempt to maintain pool size if not cleaning up
120
+ if (!this.isCleaningUp && this.pool.length < this.maxBrowsers) {
121
+ console.log("Attempting to create replacement browser...");
122
+ this.ensureMinimumBrowsers().catch((err) => {
123
+ console.error("Failed to ensure minimum browser count after removal:", err);
124
+ });
125
+ }
126
+ }
127
+ // Health check adapted for Playwright
128
+ async healthCheck() {
129
+ if (this.isCleaningUp)
130
+ return; // Skip health check during cleanup
131
+ console.log(`Running health check on ${this.pool.length} browser(s)...`);
132
+ const now = Date.now();
133
+ let browsersChanged = false;
134
+ // Iterate backwards for safe removal
135
+ for (let i = this.pool.length - 1; i >= 0; i--) {
136
+ const instance = this.pool[i];
137
+ let shouldRemove = false;
138
+ let reason = "";
139
+ // 1. Check browser age
140
+ const browserAge = now - instance.metrics.createdAt.getTime();
141
+ if (browserAge > this.maxBrowserAge) {
142
+ shouldRemove = true;
143
+ reason = "Browser max age exceeded";
144
+ }
145
+ // 2. Check idle time (only if pool size > 1)
146
+ const idleTime = now - instance.metrics.lastUsed.getTime();
147
+ // Check active pages using the context's pages
148
+ const currentPages = instance.context?.pages() ?? [];
149
+ instance.metrics.activePages = currentPages.length; // Update metric
150
+ if (!shouldRemove && this.pool.length > 1 && instance.metrics.activePages === 0 && idleTime > this.maxIdleTime) {
151
+ shouldRemove = true;
152
+ reason = "Browser idle timeout exceeded";
153
+ }
154
+ // 3. Check explicit health status (e.g., disconnected event)
155
+ if (!shouldRemove && !instance.isHealthy) {
156
+ shouldRemove = true;
157
+ reason = "Browser marked as unhealthy"; // Generic reason if already marked
158
+ }
159
+ // 4. Check responsiveness (using isConnected)
160
+ if (!shouldRemove && instance.isHealthy) {
161
+ try {
162
+ if (!instance.browser.isConnected()) {
163
+ shouldRemove = true;
164
+ reason = "Browser responsiveness check failed (not connected)";
165
+ instance.isHealthy = false; // Mark as unhealthy
166
+ instance.metrics.isHealthy = false;
167
+ }
168
+ else {
169
+ // Update active page count based on reality from the context
170
+ const pages = instance.context?.pages() ?? [];
171
+ instance.metrics.activePages = pages.length;
172
+ // Optionally add a more robust check like browser.version()
173
+ // await instance.browser.version();
174
+ }
175
+ }
176
+ catch (error) {
177
+ console.error(`Browser responsiveness check failed (ID: ${instance.metrics.id}):`, error);
178
+ shouldRemove = true;
179
+ reason = "Browser responsiveness check failed (error)";
180
+ instance.isHealthy = false; // Mark as unhealthy
181
+ instance.metrics.isHealthy = false;
182
+ }
183
+ }
184
+ if (shouldRemove) {
185
+ console.log(`${reason}. Removing browser (ID: ${instance.metrics.id}).`);
186
+ // Use closeAndRemoveBrowser which handles removal from pool and closing
187
+ this.closeAndRemoveBrowser(instance).catch((err) => console.error(`Error during async browser removal: ${err}`));
188
+ browsersChanged = true;
189
+ }
190
+ else {
191
+ // If not removed, ensure metric health status matches instance status
192
+ instance.metrics.isHealthy = instance.isHealthy;
193
+ }
194
+ }
195
+ // Ensure minimum browser count if changes occurred or pool is empty
196
+ if (browsersChanged || this.pool.length === 0) {
197
+ await this.ensureMinimumBrowsers();
198
+ }
199
+ }
200
+ // ensureMinimumBrowsers remains largely the same, relies on createBrowser
201
+ async ensureMinimumBrowsers() {
202
+ if (this.isCleaningUp)
203
+ return;
204
+ // Ensure at least one, or half max browsers (configurable maybe?)
205
+ const minBrowsers = Math.max(1, Math.floor(this.maxBrowsers / 2));
206
+ const browsersNeeded = minBrowsers - this.pool.filter((b) => b.isHealthy).length;
207
+ if (browsersNeeded > 0) {
208
+ console.log(`Healthy browsers below minimum (${minBrowsers}), attempting to create ${browsersNeeded} browser(s)...`);
209
+ for (let i = 0; i < browsersNeeded; i++) {
210
+ if (this.pool.length >= this.maxBrowsers) {
211
+ console.log("Reached max browser limit during replenishment.");
212
+ break; // Stop if we hit the overall max
213
+ }
214
+ try {
215
+ const newInstance = await this.createBrowser();
216
+ this.pool.push(newInstance);
217
+ }
218
+ catch (error) {
219
+ console.error("Failed to create browser during pool replenishment:", error);
220
+ // Maybe add a delay before next attempt or stop trying after failures?
221
+ break; // Stop trying if one fails
222
+ }
223
+ }
224
+ }
225
+ }
226
+ // startHealthChecks remains the same logic
227
+ startHealthChecks() {
228
+ if (this.healthCheckTimer) {
229
+ clearInterval(this.healthCheckTimer); // Clear existing timer if any - Cast to NodeJS.Timeout
230
+ }
231
+ console.log(`Starting browser pool health checks every ${this.healthCheckInterval / 1000} seconds.`);
232
+ this.healthCheckTimer = setInterval(() => this.healthCheck().catch((err) => {
233
+ console.error("Unhandled error in healthCheck:", err);
234
+ }), this.healthCheckInterval);
235
+ this.healthCheckTimer.unref(); // Allow Node.js process to exit if this is the only timer
236
+ }
237
+ /**
238
+ * Asynchronously initializes the browser pool, creating the first browser instance
239
+ * and starting health checks. Should be called before acquiring pages.
240
+ */
241
+ async initialize() {
242
+ if (this.pool.length > 0 || this.isCleaningUp) {
243
+ console.log("Browser pool already initialized or cleaning up.");
244
+ return;
245
+ }
246
+ console.log("Initializing browser pool...");
247
+ await this.ensureMinimumBrowsers(); // Create initial browser(s)
248
+ this.startHealthChecks(); // Start checks after initial browser is created
249
+ console.log("Browser pool initialized.");
250
+ }
251
+ // Acquire page adapted for Playwright using context
252
+ async acquirePage() {
253
+ if (this.isCleaningUp) {
254
+ throw new Error("Cannot acquire page: Browser pool is cleaning up.");
255
+ }
256
+ // Find a healthy browser/context with capacity
257
+ let targetInstance;
258
+ // Prioritize instances with fewer pages
259
+ const sortedPool = this.pool
260
+ .filter((instance) => instance.isHealthy)
261
+ .sort((a, b) => (a.context?.pages()?.length ?? Infinity) - (b.context?.pages()?.length ?? Infinity));
262
+ for (const instance of sortedPool) {
263
+ const currentPages = instance.context?.pages()?.length ?? Infinity;
264
+ if (currentPages < this.maxPagesPerBrowser) {
265
+ targetInstance = instance;
266
+ break;
267
+ }
268
+ }
269
+ // If no suitable browser/context found, and pool size is below max, try creating one
270
+ if (!targetInstance && this.pool.length < this.maxBrowsers) {
271
+ console.log("No available browser with capacity, attempting to create a new one...");
272
+ try {
273
+ const newInstance = await this.createBrowser();
274
+ this.pool.push(newInstance);
275
+ // Check if the new instance has capacity (should always be true initially)
276
+ if ((newInstance.context?.pages()?.length ?? Infinity) < this.maxPagesPerBrowser) {
277
+ targetInstance = newInstance;
278
+ }
279
+ else {
280
+ console.warn("Newly created browser instance unexpectedly has no page capacity.");
281
+ }
282
+ }
283
+ catch (error) {
284
+ console.error("Failed to create new browser instance on demand:", error);
285
+ // Fallback strategy if creation fails (optional): use least loaded regardless of limit
286
+ if (!targetInstance && sortedPool.length > 0) {
287
+ targetInstance = sortedPool[0]; // Least loaded existing healthy one
288
+ console.warn(`Using potentially overloaded browser (ID: ${targetInstance.metrics.id}) as fallback after creation failure.`);
289
+ }
290
+ }
291
+ }
292
+ // If still no browser after all attempts
293
+ if (!targetInstance || !targetInstance.context) {
294
+ // Check context existence as well
295
+ console.error("Failed to find or create a healthy browser instance with a valid context.");
296
+ throw new Error("No healthy browsers/contexts available in the pool.");
297
+ }
298
+ try {
299
+ const activePages = targetInstance.context.pages().length;
300
+ console.log(`Acquiring page from browser (ID: ${targetInstance.metrics.id}, Active Pages: ${activePages})`);
301
+ // Create page within the instance's context
302
+ const page = await targetInstance.context.newPage();
303
+ targetInstance.metrics.pagesCreated++;
304
+ // Active page count will be updated by health check or can be done here
305
+ targetInstance.metrics.activePages = targetInstance.context.pages().length;
306
+ targetInstance.metrics.lastUsed = new Date(); // Update last used time
307
+ // Track page close to potentially update metrics (less critical if health check does it)
308
+ // Playwright pages emit 'close' event
309
+ page.on("close", () => {
310
+ try {
311
+ // Update metrics if the instance still exists in the pool
312
+ const instanceInPool = this.pool.find((inst) => inst === targetInstance);
313
+ if (instanceInPool && instanceInPool.context) {
314
+ instanceInPool.metrics.activePages = instanceInPool.context.pages().length;
315
+ // console.log(`Page closed event, browser active pages: ${instanceInPool.metrics.activePages} (ID: ${instanceInPool.metrics.id})`);
316
+ }
317
+ }
318
+ catch (e) {
319
+ // Ignore errors here, health check is the safety net
320
+ console.warn("Minor error updating metrics on page close event:", e);
321
+ }
322
+ });
323
+ return page;
324
+ }
325
+ catch (error) {
326
+ console.error(`Failed to create page in browser/context (ID: ${targetInstance.metrics.id}):`, error);
327
+ targetInstance.metrics.errors++;
328
+ // Mark browser as unhealthy if page creation fails
329
+ targetInstance.isHealthy = false;
330
+ targetInstance.metrics.isHealthy = false;
331
+ this.healthCheck().catch((err) => console.error("Error running immediate health check after page fail:", err)); // Trigger health check
332
+ throw new Error(`Failed to create page: ${error.message}`); // Re-throw
333
+ }
334
+ }
335
+ // cleanup needs to close contexts as well
336
+ async cleanup() {
337
+ if (this.isCleaningUp)
338
+ return; // Prevent concurrent cleanup
339
+ this.isCleaningUp = true;
340
+ console.log("Cleaning up browser pool...");
341
+ // Stop health checks immediately
342
+ if (this.healthCheckTimer) {
343
+ clearInterval(this.healthCheckTimer); // Cast to NodeJS.Timeout
344
+ this.healthCheckTimer = undefined;
345
+ console.log("Health checks stopped.");
346
+ }
347
+ // Create a copy of the pool to iterate over
348
+ const browsersToClose = [...this.pool];
349
+ console.log(`Closing ${browsersToClose.length} browser instance(s)...`);
350
+ // Close browsers and their contexts concurrently
351
+ await Promise.allSettled(browsersToClose.map(async (instance) => {
352
+ try {
353
+ // Ensure context is closed first if it exists
354
+ if (instance.context) {
355
+ await instance.context.close();
356
+ }
357
+ await instance.browser.close();
358
+ }
359
+ catch (error) {
360
+ console.error(`Error closing browser or context (ID: ${instance.metrics.id}) during cleanup:`, error);
361
+ }
362
+ }));
363
+ this.pool = []; // Ensure pool is empty
364
+ this.isCleaningUp = false;
365
+ console.log("Browser pool cleanup complete.");
366
+ }
367
+ // getMetrics remains largely the same, ensure it reflects Playwright structure
368
+ getMetrics() {
369
+ // Return a deep copy of metrics to prevent external modification
370
+ return this.pool.map((instance) => ({
371
+ ...instance.metrics,
372
+ // Ensure isHealthy and activePages are correctly sourced if not updated elsewhere
373
+ isHealthy: instance.isHealthy,
374
+ activePages: instance.context?.pages()?.length ?? instance.metrics.activePages ?? 0, // Get latest count from context if possible
375
+ }));
376
+ }
377
+ }
378
+ //# sourceMappingURL=BrowserPool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BrowserPool.js","sourceRoot":"","sources":["../../src/browser/BrowserPool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ import type { Page } from "playwright";
2
+ import type { BrowserMetrics } from "../types.js";
3
+ /**
4
+ * Manages a pool of Playwright Browser instances for efficient reuse.
5
+ */
6
+ export declare class PlaywrightBrowserPool {
7
+ private pool;
8
+ private readonly maxBrowsers;
9
+ private readonly maxPagesPerContext;
10
+ private readonly maxBrowserAge;
11
+ private readonly healthCheckInterval;
12
+ private healthCheckTimer;
13
+ private readonly maxIdleTime;
14
+ private isCleaningUp;
15
+ private readonly useHeadedMode;
16
+ private readonly blockedDomains;
17
+ private readonly blockedResourceTypes;
18
+ private readonly proxyConfig?;
19
+ private static readonly DEFAULT_BLOCKED_DOMAINS;
20
+ private static readonly DEFAULT_BLOCKED_RESOURCE_TYPES;
21
+ private readonly acquireQueue;
22
+ constructor(config?: {
23
+ maxBrowsers?: number;
24
+ maxPagesPerContext?: number;
25
+ maxBrowserAge?: number;
26
+ healthCheckInterval?: number;
27
+ useHeadedMode?: boolean;
28
+ blockedDomains?: string[];
29
+ blockedResourceTypes?: string[];
30
+ proxy?: {
31
+ server: string;
32
+ username?: string;
33
+ password?: string;
34
+ };
35
+ maxIdleTime?: number;
36
+ });
37
+ /**
38
+ * Initializes the pool and starts health checks.
39
+ */
40
+ initialize(): Promise<void>;
41
+ /**
42
+ * Schedules the next health check.
43
+ */
44
+ private scheduleHealthCheck;
45
+ /**
46
+ * Ensures the pool has the configured maximum number of browser instances.
47
+ */
48
+ private ensureMinimumInstances;
49
+ /**
50
+ * Creates a new Playwright Browser instance and adds it to the pool.
51
+ */
52
+ private createBrowserInstance;
53
+ /**
54
+ * Acquires a Page from a healthy browser instance in the pool.
55
+ */
56
+ acquirePage(): Promise<Page>;
57
+ /**
58
+ * Performs health checks on all instances.
59
+ */
60
+ private healthCheck;
61
+ /**
62
+ * Closes and removes a browser instance from the pool.
63
+ */
64
+ private closeAndRemoveInstance;
65
+ /**
66
+ * Releases a page back to the pool, closing it.
67
+ */
68
+ releasePage(page: Page): Promise<void>;
69
+ /**
70
+ * Stops health checks and closes all browser instances.
71
+ */
72
+ cleanup(): Promise<void>;
73
+ /**
74
+ * Retrieves metrics for each browser instance in the pool.
75
+ */
76
+ getMetrics(): BrowserMetrics[];
77
+ }
78
+ //# sourceMappingURL=PlaywrightBrowserPool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlaywrightBrowserPool.d.ts","sourceRoot":"","sources":["../../src/browser/PlaywrightBrowserPool.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,IAAI,EAIL,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AA4BlD;;GAEG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,IAAI,CAA6C;IACzD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IAExC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAW;IAEhD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAI3B;IAGF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAwB7C;IACF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,8BAA8B,CAOpD;IAEF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA0C;gBAGrE,MAAM,GAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;QAChC,KAAK,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACjE,WAAW,CAAC,EAAE,MAAM,CAAC;KACjB;IAqBR;;OAEG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAc3B;;OAEG;YACW,sBAAsB;IAapC;;OAEG;YACW,qBAAqB;IA+FnC;;OAEG;IACI,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAqEnC;;OAEG;YACW,WAAW;IAiEzB;;OAEG;YACW,sBAAsB;IAoBpC;;OAEG;IACU,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCnD;;OAEG;IACU,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBrC;;OAEG;IACI,UAAU,IAAI,cAAc,EAAE;CAQtC"}