@crawlee/http-client 4.0.0-beta.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,153 @@
1
+ <h1 align="center">
2
+ <a href="https://crawlee.dev">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-dark.svg?sanitize=true">
5
+ <img alt="Crawlee" src="https://raw.githubusercontent.com/apify/crawlee/master/website/static/img/crawlee-light.svg?sanitize=true" width="500">
6
+ </picture>
7
+ </a>
8
+ <br>
9
+ <small>A web scraping and browser automation library</small>
10
+ </h1>
11
+
12
+ <p align=center>
13
+ <a href="https://trendshift.io/repositories/5179" target="_blank"><img src="https://trendshift.io/api/badge/repositories/5179" alt="apify%2Fcrawlee | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
14
+ </p>
15
+
16
+ <p align=center>
17
+ <a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/v/@crawlee/core.svg" alt="NPM latest version" data-canonical-src="https://img.shields.io/npm/v/@crawlee/core/next.svg" style="max-width: 100%;"></a>
18
+ <a href="https://www.npmjs.com/package/@crawlee/core" rel="nofollow"><img src="https://img.shields.io/npm/dm/@crawlee/core.svg" alt="Downloads" data-canonical-src="https://img.shields.io/npm/dm/@crawlee/core.svg" style="max-width: 100%;"></a>
19
+ <a href="https://discord.gg/jyEM2PRvMU" rel="nofollow"><img src="https://img.shields.io/discord/801163717915574323?label=discord" alt="Chat on discord" data-canonical-src="https://img.shields.io/discord/801163717915574323?label=discord" style="max-width: 100%;"></a>
20
+ <a href="https://github.com/apify/crawlee/actions/workflows/test-ci.yml"><img src="https://github.com/apify/crawlee/actions/workflows/test-ci.yml/badge.svg?branch=master" alt="Build Status" style="max-width: 100%;"></a>
21
+ </p>
22
+
23
+ Crawlee covers your crawling and scraping end-to-end and **helps you build reliable scrapers. Fast.**
24
+
25
+ Your crawlers will appear human-like and fly under the radar of modern bot protections even with the default configuration. Crawlee gives you the tools to crawl the web for links, scrape data, and store it to disk or cloud while staying configurable to suit your project's needs.
26
+
27
+ Crawlee is available as the [`crawlee`](https://www.npmjs.com/package/crawlee) NPM package.
28
+
29
+ > 👉 **View full documentation, guides and examples on the [Crawlee project website](https://crawlee.dev)** 👈
30
+
31
+ > Do you prefer 🐍 Python instead of JavaScript? [👉 Checkout Crawlee for Python 👈](https://github.com/apify/crawlee-python).
32
+
33
+ ## Installation
34
+
35
+ We recommend visiting the [Introduction tutorial](https://crawlee.dev/js/docs/introduction) in Crawlee documentation for more information.
36
+
37
+ > Crawlee requires **Node.js 16 or higher**.
38
+
39
+ ### With Crawlee CLI
40
+
41
+ The fastest way to try Crawlee out is to use the **Crawlee CLI** and choose the **Getting started example**. The CLI will install all the necessary dependencies and add boilerplate code for you to play with.
42
+
43
+ ```bash
44
+ npx crawlee create my-crawler
45
+ ```
46
+
47
+ ```bash
48
+ cd my-crawler
49
+ npm start
50
+ ```
51
+
52
+ ### Manual installation
53
+ If you prefer adding Crawlee **into your own project**, try the example below. Because it uses `PlaywrightCrawler` we also need to install [Playwright](https://playwright.dev). It's not bundled with Crawlee to reduce install size.
54
+
55
+ ```bash
56
+ npm install crawlee playwright
57
+ ```
58
+
59
+ ```js
60
+ import { PlaywrightCrawler, Dataset } from 'crawlee';
61
+
62
+ // PlaywrightCrawler crawls the web using a headless
63
+ // browser controlled by the Playwright library.
64
+ const crawler = new PlaywrightCrawler({
65
+ // Use the requestHandler to process each of the crawled pages.
66
+ async requestHandler({ request, page, enqueueLinks, log }) {
67
+ const title = await page.title();
68
+ log.info(`Title of ${request.loadedUrl} is '${title}'`);
69
+
70
+ // Save results as JSON to ./storage/datasets/default
71
+ await Dataset.pushData({ title, url: request.loadedUrl });
72
+
73
+ // Extract links from the current page
74
+ // and add them to the crawling queue.
75
+ await enqueueLinks();
76
+ },
77
+ // Uncomment this option to see the browser window.
78
+ // headless: false,
79
+ });
80
+
81
+ // Add first URL to the queue and start the crawl.
82
+ await crawler.run(['https://crawlee.dev']);
83
+ ```
84
+
85
+ By default, Crawlee stores data to `./storage` in the current working directory. You can override this directory via Crawlee configuration. For details, see [Configuration guide](https://crawlee.dev/js/docs/guides/configuration), [Request storage](https://crawlee.dev/js/docs/guides/request-storage) and [Result storage](https://crawlee.dev/js/docs/guides/result-storage).
86
+
87
+ ### Installing pre-release versions
88
+
89
+ We provide automated beta builds for every merged code change in Crawlee. You can find them in the npm [list of releases](https://www.npmjs.com/package/crawlee?activeTab=versions). If you want to test new features or bug fixes before we release them, feel free to install a beta build like this:
90
+
91
+ ```bash
92
+ npm install crawlee@3.12.3-beta.13
93
+ ```
94
+
95
+ If you also use the [Apify SDK](https://github.com/apify/apify-sdk-js), you need to specify dependency overrides in your `package.json` file so that you don't end up with multiple versions of Crawlee installed:
96
+
97
+ ```json
98
+ {
99
+ "overrides": {
100
+ "apify": {
101
+ "@crawlee/core": "3.12.3-beta.13",
102
+ "@crawlee/types": "3.12.3-beta.13",
103
+ "@crawlee/utils": "3.12.3-beta.13"
104
+ }
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## 🛠 Features
110
+
111
+ - Single interface for **HTTP and headless browser** crawling
112
+ - Persistent **queue** for URLs to crawl (breadth & depth first)
113
+ - Pluggable **storage** of both tabular data and files
114
+ - Automatic **scaling** with available system resources
115
+ - Integrated **proxy rotation** and session management
116
+ - Lifecycles customizable with **hooks**
117
+ - **CLI** to bootstrap your projects
118
+ - Configurable **routing**, **error handling** and **retries**
119
+ - **Dockerfiles** ready to deploy
120
+ - Written in **TypeScript** with generics
121
+
122
+ ### 👾 HTTP crawling
123
+
124
+ - Zero config **HTTP2 support**, even for proxies
125
+ - Automatic generation of **browser-like headers**
126
+ - Replication of browser **TLS fingerprints**
127
+ - Integrated fast **HTML parsers**. Cheerio and JSDOM
128
+ - Yes, you can scrape **JSON APIs** as well
129
+
130
+ ### 💻 Real browser crawling
131
+
132
+ - JavaScript **rendering** and **screenshots**
133
+ - **Headless** and **headful** support
134
+ - Zero-config generation of **human-like fingerprints**
135
+ - Automatic **browser management**
136
+ - Use **Playwright** and **Puppeteer** with the same interface
137
+ - **Chrome**, **Firefox**, **Webkit** and many others
138
+
139
+ ## Usage on the Apify platform
140
+
141
+ Crawlee is open-source and runs anywhere, but since it's developed by [Apify](https://apify.com), it's easy to set up on the Apify platform and run in the cloud. Visit the [Apify SDK website](https://sdk.apify.com) to learn more about deploying Crawlee to the Apify platform.
142
+
143
+ ## Support
144
+
145
+ If you find any bug or issue with Crawlee, please [submit an issue on GitHub](https://github.com/apify/crawlee/issues). For questions, you can ask on [Stack Overflow](https://stackoverflow.com/questions/tagged/apify), in GitHub Discussions or you can join our [Discord server](https://discord.com/invite/jyEM2PRvMU).
146
+
147
+ ## Contributing
148
+
149
+ Your code contributions are welcome, and you'll be praised to eternity! If you have any ideas for improvements, either submit an issue or create a pull request. For contribution guidelines and the code of conduct, see [CONTRIBUTING.md](https://github.com/apify/crawlee/blob/master/CONTRIBUTING.md).
150
+
151
+ ## License
152
+
153
+ This project is licensed under the Apache License 2.0 - see the [LICENSE.md](https://github.com/apify/crawlee/blob/master/LICENSE.md) file for details.
@@ -0,0 +1,27 @@
1
+ import type { BaseHttpClient as BaseHttpClientInterface, SendRequestOptions } from '@crawlee/types';
2
+ export interface CustomFetchOptions {
3
+ proxyUrl?: string;
4
+ }
5
+ /**
6
+ * Base HTTP client that provides fetch-like `sendRequest` with Crawlee-managed
7
+ * behaviors (redirect handling, proxy and cookie handling). Concrete clients
8
+ * implement only the low-level network call in `fetch`.
9
+ */
10
+ export declare abstract class BaseHttpClient implements BaseHttpClientInterface {
11
+ /**
12
+ * Perform the raw network request and return a single Response without any
13
+ * automatic redirect following or special error handling.
14
+ */
15
+ protected abstract fetch(input: Request, init?: RequestInit & CustomFetchOptions): Promise<Response>;
16
+ private applyCookies;
17
+ private setCookies;
18
+ private resolveRequestContext;
19
+ private createAbortSignal;
20
+ private isRedirect;
21
+ private buildRedirectRequest;
22
+ /**
23
+ * Public fetch-like method that handles redirects and uses provided proxy and cookie jar.
24
+ */
25
+ sendRequest(initialRequest: Request, options?: SendRequestOptions): Promise<Response>;
26
+ }
27
+ //# sourceMappingURL=base-http-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-http-client.d.ts","sourceRoot":"","sources":["../src/base-http-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,IAAI,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGpG,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,8BAAsB,cAAe,YAAW,uBAAuB;IACnE;;;OAGG;IACH,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;YAEtF,YAAY;YASZ,UAAU;IAMxB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,oBAAoB;IA+B5B;;OAEG;IACG,WAAW,CAAC,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;CA8B9F"}
@@ -0,0 +1,85 @@
1
+ import { CookieJar } from 'tough-cookie';
2
+ /**
3
+ * Base HTTP client that provides fetch-like `sendRequest` with Crawlee-managed
4
+ * behaviors (redirect handling, proxy and cookie handling). Concrete clients
5
+ * implement only the low-level network call in `fetch`.
6
+ */
7
+ export class BaseHttpClient {
8
+ async applyCookies(request, cookieJar) {
9
+ const cookies = (await cookieJar.getCookies(request.url)).map((x) => x.cookieString().trim()).filter(Boolean);
10
+ if (cookies?.length > 0) {
11
+ request.headers.set('cookie', cookies.join('; '));
12
+ }
13
+ return request;
14
+ }
15
+ async setCookies(response, cookieJar) {
16
+ const setCookieHeaders = response.headers.getSetCookie();
17
+ await Promise.all(setCookieHeaders.map((header) => cookieJar.setCookie(header, response.url)));
18
+ }
19
+ resolveRequestContext(options) {
20
+ const proxyUrl = options?.proxyUrl ?? options?.session?.proxyInfo?.url;
21
+ const cookieJar = options?.cookieJar ?? options?.session?.cookieJar ?? new CookieJar();
22
+ const timeout = options?.timeout;
23
+ return { proxyUrl, cookieJar: cookieJar, timeout };
24
+ }
25
+ createAbortSignal(timeout) {
26
+ return timeout ? AbortSignal.timeout(timeout) : undefined;
27
+ }
28
+ isRedirect(response) {
29
+ const status = response.status;
30
+ return status >= 300 && status < 400 && !!response.headers.get('location');
31
+ }
32
+ buildRedirectRequest(currentRequest, response, initialRequest) {
33
+ const location = response.headers.get('location');
34
+ const nextUrl = new URL(location, response.url ?? currentRequest.url);
35
+ const prevMethod = (currentRequest.method ?? 'GET').toUpperCase();
36
+ let nextMethod = prevMethod;
37
+ let nextBody = null;
38
+ if (response.status === 303 ||
39
+ ((response.status === 301 || response.status === 302) && prevMethod === 'POST')) {
40
+ nextMethod = 'GET';
41
+ nextBody = null;
42
+ }
43
+ else {
44
+ const clonedRequest = initialRequest.clone();
45
+ nextBody = clonedRequest.body;
46
+ }
47
+ const nextHeaders = new Headers();
48
+ currentRequest.headers.forEach((value, key) => nextHeaders.set(key, value));
49
+ return new Request(nextUrl.toString(), {
50
+ method: nextMethod,
51
+ headers: nextHeaders,
52
+ body: nextBody,
53
+ credentials: currentRequest.credentials,
54
+ redirect: 'manual',
55
+ });
56
+ }
57
+ /**
58
+ * Public fetch-like method that handles redirects and uses provided proxy and cookie jar.
59
+ */
60
+ async sendRequest(initialRequest, options) {
61
+ const maxRedirects = 10;
62
+ let currentRequest = initialRequest;
63
+ let redirectCount = 0;
64
+ const { proxyUrl, cookieJar, timeout } = this.resolveRequestContext(options);
65
+ currentRequest = initialRequest.clone();
66
+ while (true) {
67
+ await this.applyCookies(currentRequest, cookieJar);
68
+ const response = await this.fetch(currentRequest, {
69
+ signal: this.createAbortSignal(timeout),
70
+ proxyUrl,
71
+ redirect: 'manual',
72
+ });
73
+ await this.setCookies(response, cookieJar);
74
+ if (this.isRedirect(response)) {
75
+ if (redirectCount++ >= maxRedirects) {
76
+ throw new Error(`Too many redirects (${maxRedirects}) while requesting ${currentRequest.url}`);
77
+ }
78
+ currentRequest = this.buildRedirectRequest(currentRequest, response, initialRequest);
79
+ continue;
80
+ }
81
+ return response;
82
+ }
83
+ }
84
+ }
85
+ //# sourceMappingURL=base-http-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-http-client.js","sourceRoot":"","sources":["../src/base-http-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { BaseHttpClient, type CustomFetchOptions } from './base-http-client.js';
2
+ /**
3
+ * A HTTP client implementation using the native `fetch` API.
4
+ *
5
+ * This implementation does not support proxying.
6
+ */
7
+ export declare class FetchHttpClient extends BaseHttpClient {
8
+ fetch(request: Request, options?: RequestInit & CustomFetchOptions): Promise<Response>;
9
+ }
10
+ //# sourceMappingURL=fetch-http-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-http-client.d.ts","sourceRoot":"","sources":["../src/fetch-http-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhF;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,cAAc;IAChC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,kBAAkB,GAAG,OAAO,CAAC,QAAQ,CAAC;CAGxG"}
@@ -0,0 +1,12 @@
1
+ import { BaseHttpClient } from './base-http-client.js';
2
+ /**
3
+ * A HTTP client implementation using the native `fetch` API.
4
+ *
5
+ * This implementation does not support proxying.
6
+ */
7
+ export class FetchHttpClient extends BaseHttpClient {
8
+ async fetch(request, options) {
9
+ return fetch(request, options);
10
+ }
11
+ }
12
+ //# sourceMappingURL=fetch-http-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-http-client.js","sourceRoot":"","sources":["../src/fetch-http-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA2B,MAAM,uBAAuB,CAAC;AAEhF;;;;GAIG;AACH,MAAM,OAAO,eAAgB,SAAQ,cAAc;IACtC,KAAK,CAAC,KAAK,CAAC,OAAgB,EAAE,OAA0C;QAC7E,OAAO,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;CACJ"}
package/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { BaseHttpClient, type CustomFetchOptions } from './base-http-client.js';
2
+ export { ResponseWithUrl, type IResponseWithUrl } from './response.js';
3
+ export { FetchHttpClient } from './fetch-http-client.js';
4
+ //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
package/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { BaseHttpClient } from './base-http-client.js';
2
+ export { ResponseWithUrl } from './response.js';
3
+ export { FetchHttpClient } from './fetch-http-client.js';
4
+ //# sourceMappingURL=index.js.map
package/index.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAA2B,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,eAAe,EAAyB,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@crawlee/http-client",
3
+ "version": "4.0.0-beta.23",
4
+ "description": "The scalable web crawling and scraping library for JavaScript/Node.js. Enables development of data extraction and web automation jobs (not only) with headless Chrome and Puppeteer.",
5
+ "engines": {
6
+ "node": ">=22.0.0"
7
+ },
8
+ "type": "module",
9
+ "exports": {
10
+ ".": "./index.js",
11
+ "./package.json": "./package.json"
12
+ },
13
+ "keywords": [
14
+ "apify",
15
+ "headless",
16
+ "chrome",
17
+ "puppeteer",
18
+ "crawler",
19
+ "scraper"
20
+ ],
21
+ "author": {
22
+ "name": "Apify",
23
+ "email": "support@apify.com",
24
+ "url": "https://apify.com"
25
+ },
26
+ "contributors": [
27
+ "Jan Curn <jan@apify.com>",
28
+ "Marek Trunkat <marek@apify.com>",
29
+ "Ondra Urban <ondra@apify.com>"
30
+ ],
31
+ "license": "Apache-2.0",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/apify/crawlee"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/apify/crawlee/issues"
38
+ },
39
+ "homepage": "https://crawlee.dev",
40
+ "scripts": {
41
+ "build": "yarn clean && yarn compile && yarn copy",
42
+ "clean": "rimraf ./dist",
43
+ "compile": "tsc -p tsconfig.build.json",
44
+ "copy": "tsx ../../scripts/copy.ts"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "dependencies": {
50
+ "@crawlee/types": "4.0.0-beta.23",
51
+ "tough-cookie": "^6.0.0"
52
+ },
53
+ "lerna": {
54
+ "command": {
55
+ "publish": {
56
+ "assets": []
57
+ }
58
+ }
59
+ },
60
+ "gitHead": "1d348c0c13605e8c4749727419f2c01d1162d642"
61
+ }
package/response.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export interface IResponseWithUrl extends Response {
2
+ url: string;
3
+ }
4
+ /**
5
+ * A Response class that includes the original request URL.
6
+ *
7
+ * This class extends `Response` from `fetch` API and is fully compatible with this.
8
+ */
9
+ export declare class ResponseWithUrl extends Response implements IResponseWithUrl {
10
+ url: string;
11
+ constructor(body: BodyInit | null, init: ResponseInit & {
12
+ url?: string;
13
+ });
14
+ }
15
+ //# sourceMappingURL=response.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../src/response.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAiB,SAAQ,QAAQ;IAC9C,GAAG,EAAE,MAAM,CAAC;CACf;AAKD;;;;GAIG;AACH,qBAAa,eAAgB,SAAQ,QAAS,YAAW,gBAAgB;IAC5D,GAAG,EAAE,MAAM,CAAC;gBACT,IAAI,EAAE,QAAQ,GAAG,IAAI,EAAE,IAAI,EAAE,YAAY,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE;CAM3E"}
package/response.js ADDED
@@ -0,0 +1,16 @@
1
+ // See https://github.com/nodejs/undici/blob/d7707ee8fd5da2d0cc64b5fae421b965faf803c8/lib/web/fetch/constants.js#L6
2
+ const nullBodyStatus = [101, 204, 205, 304];
3
+ /**
4
+ * A Response class that includes the original request URL.
5
+ *
6
+ * This class extends `Response` from `fetch` API and is fully compatible with this.
7
+ */
8
+ export class ResponseWithUrl extends Response {
9
+ url;
10
+ constructor(body, init) {
11
+ const bodyParsed = nullBodyStatus.includes(init.status ?? 200) ? null : body;
12
+ super(bodyParsed, init);
13
+ this.url = init.url ?? '';
14
+ }
15
+ }
16
+ //# sourceMappingURL=response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../src/response.ts"],"names":[],"mappings":"AAIA,mHAAmH;AACnH,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAE5C;;;;GAIG;AACH,MAAM,OAAO,eAAgB,SAAQ,QAAQ;IAChC,GAAG,CAAS;IACrB,YAAY,IAAqB,EAAE,IAAqC;QACpE,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;QAE7E,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;IAC9B,CAAC;CACJ"}