system-testing 1.0.33 → 1.0.34

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.
@@ -0,0 +1 @@
1
+ export const stub: "Hello world";
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ const stub = "Hello world";
2
+ export { stub };
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAAA,MAAM,IAAI,GAAG,aAAa,CAAA;AAE1B,OAAO,EAAC,IAAI,EAAC,CAAA"}
@@ -0,0 +1,106 @@
1
+ export default class SystemTestBrowserHelper {
2
+ static current(): SystemTestBrowserHelper;
3
+ communicator: SystemTestCommunicator;
4
+ _enabled: boolean;
5
+ events: EventEmitter<any>;
6
+ startScoundrel(): Promise<void>;
7
+ scoundrelWs: WebSocket;
8
+ scoundrelClientWebSocket: any;
9
+ scoundrelClient: any;
10
+ waitForScoundrelStarted(): Promise<any>;
11
+ getScoundrel(): any;
12
+ connectOnError(): void;
13
+ connectUnhandledRejection(): void;
14
+ /**
15
+ * @param {object} data
16
+ * @param {string} [data.backtrace]
17
+ * @param {Error} [data.error]
18
+ * @param {string} [data.errorClass]
19
+ * @param {string} [data.file]
20
+ * @param {number} [data.line]
21
+ * @param {string} [data.message]
22
+ * @param {string} [data.type]
23
+ * @param {string} [data.url]
24
+ * @returns {void}
25
+ */
26
+ handleError(data: {
27
+ backtrace?: string;
28
+ error?: Error;
29
+ errorClass?: string;
30
+ file?: string;
31
+ line?: number;
32
+ message?: string;
33
+ type?: string;
34
+ url?: string;
35
+ }): void;
36
+ /**
37
+ * @returns {void}
38
+ */
39
+ connectWebSocket(): void;
40
+ ws: WebSocket;
41
+ /**
42
+ * @returns {void}
43
+ */
44
+ enableOnBrowser(): void;
45
+ /**
46
+ * @returns {boolean}
47
+ */
48
+ getEnabled(): boolean;
49
+ /**
50
+ * @returns {EventEmitter}
51
+ */
52
+ getEvents(): EventEmitter;
53
+ /**
54
+ * @param {any[]} args
55
+ * @returns {void}
56
+ */
57
+ fakeConsoleError: (...args: any[]) => void;
58
+ /**
59
+ * @param {any[]} args
60
+ * @returns {void}
61
+ */
62
+ fakeConsoleLog: (...args: any[]) => void;
63
+ /**
64
+ * @param {any} arg
65
+ * @param {any[]} [scannedObjects]
66
+ * @returns {any}
67
+ */
68
+ consoleLogMessage(arg: any, scannedObjects?: any[]): any;
69
+ /**
70
+ * @param {{data: {path: string, type: string}}} args
71
+ * @returns {Promise<{result: string} | void>}
72
+ */
73
+ onCommand: ({ data }: {
74
+ data: {
75
+ path: string;
76
+ type: string;
77
+ };
78
+ }) => Promise<{
79
+ result: string;
80
+ } | void>;
81
+ /**
82
+ * @param {function() : void} callback
83
+ * @returns {void}
84
+ */
85
+ onInitialize(callback: () => void): void;
86
+ _onInitializeCallback: () => void;
87
+ /**
88
+ * @returns {void}
89
+ */
90
+ overrideConsoleLog(): void;
91
+ originalConsoleError: {
92
+ (...data: any[]): void;
93
+ (message?: any, ...optionalParams: any[]): void;
94
+ };
95
+ originalConsoleLog: {
96
+ (...data: any[]): void;
97
+ (message?: any, ...optionalParams: any[]): void;
98
+ };
99
+ /**
100
+ * @param {string} sql
101
+ * @returns {Promise<Array<Record<string, any>>>}
102
+ */
103
+ sendQuery(sql: string): Promise<Array<Record<string, any>>>;
104
+ }
105
+ import SystemTestCommunicator from "./system-test-communicator.js";
106
+ import EventEmitter from "events";
@@ -0,0 +1,237 @@
1
+ // @ts-check
2
+ import Client from "scoundrel-remote-eval/src/client/index.js";
3
+ import ClientWebSocket from "scoundrel-remote-eval/src/client/connections/web-socket/index.js";
4
+ import { digg } from "diggerize";
5
+ import EventEmitter from "events";
6
+ import SystemTestCommunicator from "./system-test-communicator.js";
7
+ /** @type {{systemTestBrowserHelper: SystemTestBrowserHelper | null}} */
8
+ const shared = {
9
+ systemTestBrowserHelper: null
10
+ };
11
+ export default class SystemTestBrowserHelper {
12
+ static current() {
13
+ if (!shared.systemTestBrowserHelper) {
14
+ throw new Error("No current SystemTestBrowserHelper set");
15
+ }
16
+ return shared.systemTestBrowserHelper;
17
+ }
18
+ constructor() {
19
+ /**
20
+ * @param {any[]} args
21
+ * @returns {void}
22
+ */
23
+ this.fakeConsoleError = (...args) => {
24
+ this.communicator.sendCommand({ type: "console.error", value: this.consoleLogMessage(args) });
25
+ if (this.originalConsoleError) {
26
+ return this.originalConsoleError(...args);
27
+ }
28
+ };
29
+ /**
30
+ * @param {any[]} args
31
+ * @returns {void}
32
+ */
33
+ this.fakeConsoleLog = (...args) => {
34
+ this.communicator.sendCommand({ type: "console.log", value: this.consoleLogMessage(args) });
35
+ if (this.originalConsoleLog) {
36
+ return this.originalConsoleLog(...args);
37
+ }
38
+ };
39
+ /**
40
+ * @param {{data: {path: string, type: string}}} args
41
+ * @returns {Promise<{result: string} | void>}
42
+ */
43
+ this.onCommand = async ({ data }) => {
44
+ if (data.type == "initialize") {
45
+ this.events.emit("initialize");
46
+ if (this._onInitializeCallback) {
47
+ await this._onInitializeCallback();
48
+ }
49
+ return { result: "initialized" };
50
+ }
51
+ else if (data.type == "visit") {
52
+ this.events.emit("navigate", { path: data.path });
53
+ }
54
+ else if (data.type == "dismissTo") {
55
+ this.events.emit("dismissTo", { path: data.path });
56
+ }
57
+ else {
58
+ throw new Error(`Unknown command type for SystemTestBrowserHelper: ${data.type}`);
59
+ }
60
+ };
61
+ this.communicator = new SystemTestCommunicator({ parent: this, onCommand: this.onCommand });
62
+ this._enabled = false;
63
+ this.events = new EventEmitter();
64
+ shared.systemTestBrowserHelper = this;
65
+ this.startScoundrel();
66
+ }
67
+ async startScoundrel() {
68
+ this.scoundrelWs = new WebSocket("http://localhost:8090");
69
+ this.scoundrelClientWebSocket = new ClientWebSocket(this.scoundrelWs);
70
+ await this.scoundrelClientWebSocket.waitForOpened();
71
+ this.scoundrelClient = new Client(this.scoundrelClientWebSocket);
72
+ this.events.emit("scoundrelStarted");
73
+ }
74
+ waitForScoundrelStarted() {
75
+ return new Promise((resolve) => {
76
+ if (this.scoundrelClient) {
77
+ resolve(undefined);
78
+ }
79
+ else {
80
+ this.events.once("scoundrelStarted", () => {
81
+ resolve(undefined);
82
+ });
83
+ }
84
+ });
85
+ }
86
+ getScoundrel() {
87
+ if (!this.scoundrelClient) {
88
+ throw new Error("Scoundrel client is not started yet");
89
+ }
90
+ return this.scoundrelClient;
91
+ }
92
+ connectOnError() {
93
+ window.addEventListener("error", (event) => {
94
+ this.handleError({
95
+ type: "error",
96
+ error: event.error,
97
+ errorClass: event.error?.name,
98
+ file: event.filename,
99
+ line: event.lineno,
100
+ message: event.message || "Unknown error",
101
+ url: window.location.href
102
+ });
103
+ });
104
+ }
105
+ connectUnhandledRejection() {
106
+ window.addEventListener("unhandledrejection", (event) => {
107
+ this.handleError({
108
+ type: "unhandledrejection",
109
+ error: event.reason,
110
+ errorClass: "UnhandledRejection",
111
+ message: event.reason.message || event.reason || "Unhandled promise rejection without a message",
112
+ url: window.location.href
113
+ });
114
+ });
115
+ }
116
+ /**
117
+ * @param {object} data
118
+ * @param {string} [data.backtrace]
119
+ * @param {Error} [data.error]
120
+ * @param {string} [data.errorClass]
121
+ * @param {string} [data.file]
122
+ * @param {number} [data.line]
123
+ * @param {string} [data.message]
124
+ * @param {string} [data.type]
125
+ * @param {string} [data.url]
126
+ * @returns {void}
127
+ */
128
+ handleError(data) {
129
+ let backtrace;
130
+ if (data.error && data.error.stack) {
131
+ backtrace = data.error.stack.split("\n");
132
+ backtrace.shift();
133
+ backtrace = backtrace.join("\n");
134
+ }
135
+ else if (data.file) {
136
+ backtrace = `${data.file}:${data.line}`;
137
+ }
138
+ data.backtrace = backtrace;
139
+ this.communicator.sendCommand(data);
140
+ }
141
+ /**
142
+ * @returns {void}
143
+ */
144
+ connectWebSocket() {
145
+ this.ws = new WebSocket("ws://localhost:1985");
146
+ this.communicator.ws = this.ws;
147
+ this.ws.addEventListener("error", digg(this, "communicator", "onError"));
148
+ this.ws.addEventListener("open", digg(this, "communicator", "onOpen"));
149
+ this.ws.addEventListener("message", (event) => this.communicator.onMessage(event.data));
150
+ }
151
+ /**
152
+ * @returns {void}
153
+ */
154
+ enableOnBrowser() {
155
+ this._enabled = true;
156
+ this.connectWebSocket();
157
+ this.connectOnError();
158
+ this.connectUnhandledRejection();
159
+ this.overrideConsoleLog();
160
+ }
161
+ /**
162
+ * @returns {boolean}
163
+ */
164
+ getEnabled() { return this._enabled; }
165
+ /**
166
+ * @returns {EventEmitter}
167
+ */
168
+ getEvents() { return this.events; }
169
+ /**
170
+ * @param {any} arg
171
+ * @param {any[]} [scannedObjects]
172
+ * @returns {any}
173
+ */
174
+ consoleLogMessage(arg, scannedObjects = []) {
175
+ if (Array.isArray(arg)) {
176
+ if (scannedObjects.includes(arg)) {
177
+ return "[recursive]";
178
+ }
179
+ else {
180
+ scannedObjects.push(arg);
181
+ }
182
+ const result = [];
183
+ for (const value of arg) {
184
+ result.push(this.consoleLogMessage(value, scannedObjects));
185
+ }
186
+ return result;
187
+ }
188
+ else if (Object.prototype.toString.call(arg) === '[object Object]') {
189
+ if (scannedObjects.includes(arg)) {
190
+ return "[recursive]";
191
+ }
192
+ else {
193
+ scannedObjects.push(arg);
194
+ }
195
+ /** @type {Record<string, any>} */
196
+ const result = {};
197
+ for (const key in arg) {
198
+ result[key] = this.consoleLogMessage(arg[key], scannedObjects);
199
+ }
200
+ return result;
201
+ }
202
+ else if (typeof arg == "object") {
203
+ return `[object ${arg?.constructor?.name}]`;
204
+ }
205
+ else {
206
+ return arg;
207
+ }
208
+ }
209
+ /**
210
+ * @param {function() : void} callback
211
+ * @returns {void}
212
+ */
213
+ onInitialize(callback) {
214
+ this._onInitializeCallback = callback;
215
+ }
216
+ /**
217
+ * @returns {void}
218
+ */
219
+ overrideConsoleLog() {
220
+ if (this.originalConsoleError || this.originalConsoleLog) {
221
+ throw new Error("Console methods has already been overridden!");
222
+ }
223
+ this.originalConsoleError = console.error;
224
+ this.originalConsoleLog = console.log;
225
+ console.error = this.fakeConsoleError;
226
+ console.log = this.fakeConsoleLog;
227
+ }
228
+ /**
229
+ * @param {string} sql
230
+ * @returns {Promise<Array<Record<string, any>>>}
231
+ */
232
+ async sendQuery(sql) {
233
+ // @ts-expect-error
234
+ return await this.communicator.sendCommand({ type: "query", sql });
235
+ }
236
+ }
237
+ //# sourceMappingURL=system-test-browser-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-test-browser-helper.js","sourceRoot":"","sources":["../src/system-test-browser-helper.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ export default class SystemTestCommunicator {
2
+ /**
3
+ * @param {object} args
4
+ * @param {(args: Record<string, any>) => Promise<{result: string} | void>} args.onCommand
5
+ * @param {object} [args.parent]
6
+ */
7
+ constructor({ onCommand, parent }: {
8
+ onCommand: (args: Record<string, any>) => Promise<{
9
+ result: string;
10
+ } | void>;
11
+ parent?: object;
12
+ });
13
+ /** @type {Record<string, {resolve: (data: any) => void, reject: (data: any) => void}>} */
14
+ _responses: Record<string, {
15
+ resolve: (data: any) => void;
16
+ reject: (data: any) => void;
17
+ }>;
18
+ /** @type {Record<string, any>} */
19
+ _sendQueue: Record<string, any>;
20
+ _sendQueueCount: number;
21
+ /** @type {WebSocket | null} */
22
+ ws: WebSocket | null;
23
+ onCommand: (args: Record<string, any>) => Promise<{
24
+ result: string;
25
+ } | void>;
26
+ parent: any;
27
+ flushSendQueue(): void;
28
+ /** @param {Error} error */
29
+ onError: (error: Error) => void;
30
+ /** @param {string} rawData */
31
+ onMessage: (rawData: string) => Promise<void>;
32
+ onOpen: () => void;
33
+ /**
34
+ * @param {Record<string, any>} data
35
+ * @returns {void}
36
+ */
37
+ send(data: Record<string, any>): void;
38
+ /**
39
+ * Sends a command and returns a promise that resolves with the response.
40
+ * @param {Record<string, any>} data - The command data to send.
41
+ * @returns {Promise<void>} A promise that resolves with the response data.
42
+ */
43
+ sendCommand(data: Record<string, any>): Promise<void>;
44
+ /**
45
+ * @param {number} id
46
+ * @param {Record<string, any>} data
47
+ * @returns {void}
48
+ */
49
+ respond(id: number, data: Record<string, any>): void;
50
+ }
@@ -0,0 +1,105 @@
1
+ // @ts-check
2
+ export default class SystemTestCommunicator {
3
+ /**
4
+ * @param {object} args
5
+ * @param {(args: Record<string, any>) => Promise<{result: string} | void>} args.onCommand
6
+ * @param {object} [args.parent]
7
+ */
8
+ constructor({ onCommand, parent }) {
9
+ /** @type {Record<string, {resolve: (data: any) => void, reject: (data: any) => void}>} */
10
+ this._responses = {};
11
+ /** @type {Record<string, any>} */
12
+ this._sendQueue = [];
13
+ this._sendQueueCount = 0;
14
+ /** @type {WebSocket | null} */
15
+ this.ws = null;
16
+ /** @param {Error} error */
17
+ this.onError = (error) => {
18
+ console.error("onWebSocketClientError", error);
19
+ };
20
+ /** @param {string} rawData */
21
+ this.onMessage = async (rawData) => {
22
+ /** @type {{data: any, id: number, type: string, isTrusted?: boolean}} */
23
+ const data = JSON.parse(rawData);
24
+ if (data.isTrusted) {
25
+ // Ignore
26
+ }
27
+ else if (data.type == "command") {
28
+ try {
29
+ const result = await this.onCommand({ data: data.data });
30
+ this.respond(data.id, { result });
31
+ }
32
+ catch (error) {
33
+ if (error instanceof Error) {
34
+ this.respond(data.id, { error: error.message });
35
+ }
36
+ else {
37
+ this.respond(data.id, { error: error });
38
+ }
39
+ }
40
+ }
41
+ else if (data.type == "response") {
42
+ const response = this._responses[data.id];
43
+ if (!response) {
44
+ throw new Error(`No such response: ${data.id}`);
45
+ }
46
+ delete this._responses[data.id];
47
+ if (data.data.error) {
48
+ response.reject(data.data.error);
49
+ }
50
+ else {
51
+ response.resolve(data.data.result);
52
+ }
53
+ }
54
+ else {
55
+ throw new Error(`Unknown type for SystemTestCommunicator: ${data.type}: ${JSON.stringify(data)}`);
56
+ }
57
+ };
58
+ this.onOpen = () => {
59
+ this.flushSendQueue();
60
+ };
61
+ this.onCommand = onCommand;
62
+ this.parent = parent;
63
+ }
64
+ flushSendQueue() {
65
+ while (this._sendQueue.length !== 0) {
66
+ const data = this._sendQueue.shift();
67
+ if (!this.ws || this.ws.readyState !== 1) {
68
+ throw new Error("WebSocket is not open");
69
+ }
70
+ this.ws.send(JSON.stringify(data));
71
+ }
72
+ }
73
+ /**
74
+ * @param {Record<string, any>} data
75
+ * @returns {void}
76
+ */
77
+ send(data) {
78
+ this._sendQueue.push(data);
79
+ if (this.ws.readyState == 1) {
80
+ this.flushSendQueue();
81
+ }
82
+ }
83
+ /**
84
+ * Sends a command and returns a promise that resolves with the response.
85
+ * @param {Record<string, any>} data - The command data to send.
86
+ * @returns {Promise<void>} A promise that resolves with the response data.
87
+ */
88
+ sendCommand(data) {
89
+ return new Promise((resolve, reject) => {
90
+ const id = this._sendQueueCount;
91
+ this._sendQueueCount += 1;
92
+ this._responses[id] = { resolve, reject };
93
+ this.send({ type: "command", id, data });
94
+ });
95
+ }
96
+ /**
97
+ * @param {number} id
98
+ * @param {Record<string, any>} data
99
+ * @returns {void}
100
+ */
101
+ respond(id, data) {
102
+ this.send({ type: "response", id, data });
103
+ }
104
+ }
105
+ //# sourceMappingURL=system-test-communicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-test-communicator.js","sourceRoot":"","sources":["../src/system-test-communicator.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export default class SystemTestHttpServer {
2
+ /** @returns {void} */
3
+ close(): void;
4
+ /**
5
+ * @param {http.IncomingMessage} request
6
+ * @param {http.ServerResponse} response
7
+ * @returns {Promise<void>}
8
+ */
9
+ onHttpServerRequest: (request: http.IncomingMessage, response: http.ServerResponse) => Promise<void>;
10
+ /** @returns {Promise<void>} */
11
+ start(): Promise<void>;
12
+ basePath: string;
13
+ /** @returns {Promise<void>} */
14
+ startHttpServer(): Promise<void>;
15
+ httpServer: http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>;
16
+ }
17
+ import http from "node:http";
@@ -0,0 +1,66 @@
1
+ // @ts-check
2
+ import fs from "node:fs/promises";
3
+ import http from "node:http";
4
+ import mime from "mime";
5
+ import url from "url";
6
+ export default class SystemTestHttpServer {
7
+ constructor() {
8
+ /**
9
+ * @param {http.IncomingMessage} request
10
+ * @param {http.ServerResponse} response
11
+ * @returns {Promise<void>}
12
+ */
13
+ this.onHttpServerRequest = async (request, response) => {
14
+ if (!request.url) {
15
+ response.statusCode = 400;
16
+ response.end("Bad Request");
17
+ return;
18
+ }
19
+ const parsedUrl = url.parse(request.url);
20
+ let filePath = `${process.cwd()}/dist${parsedUrl.pathname}`;
21
+ if (filePath.endsWith("/")) {
22
+ filePath += "index.html";
23
+ }
24
+ let fileExists;
25
+ try {
26
+ await fs.stat(filePath);
27
+ fileExists = true;
28
+ }
29
+ catch (_error) { // eslint-disable-line no-unused-vars
30
+ fileExists = false;
31
+ }
32
+ if (!fileExists) {
33
+ filePath = `${process.cwd()}/dist/index.html`;
34
+ }
35
+ const fileContent = await fs.readFile(filePath);
36
+ const mimeType = mime.getType(filePath);
37
+ response.statusCode = 200;
38
+ if (mimeType) {
39
+ response.setHeader("Content-Type", mimeType);
40
+ }
41
+ response.end(fileContent);
42
+ };
43
+ }
44
+ /** @returns {void} */
45
+ close() {
46
+ if (!this.httpServer) {
47
+ throw new Error("HTTP server is not initialized");
48
+ }
49
+ this.httpServer.close();
50
+ }
51
+ /** @returns {Promise<void>} */
52
+ async start() {
53
+ this.basePath = await fs.realpath(`${__dirname}/../..`);
54
+ await this.startHttpServer();
55
+ }
56
+ /** @returns {Promise<void>} */
57
+ startHttpServer() {
58
+ return new Promise((resolve) => {
59
+ this.httpServer = http.createServer(this.onHttpServerRequest);
60
+ this.httpServer.listen(1984, "localhost", () => {
61
+ resolve();
62
+ });
63
+ });
64
+ }
65
+ }
66
+ //# sourceMappingURL=system-test-http-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-test-http-server.js","sourceRoot":"","sources":["../src/system-test-http-server.js"],"names":[],"mappings":"AAAA,YAAY;AAEZ,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjC,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,GAAG,MAAM,KAAK,CAAA;AAErB,MAAM,CAAC,OAAO,OAAO,oBAAoB;IAAzC;QAUE;;;;WAIG;QACH,wBAAmB,GAAG,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;YAChD,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;gBACjB,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAA;gBACzB,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;gBAC3B,OAAM;YACR,CAAC;YAED,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YACxC,IAAI,QAAQ,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,QAAQ,SAAS,CAAC,QAAQ,EAAE,CAAA;YAE3D,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,QAAQ,IAAI,YAAY,CAAA;YAC1B,CAAC;YAED,IAAI,UAAU,CAAA;YAEd,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;gBACvB,UAAU,GAAG,IAAI,CAAA;YACnB,CAAC;YAAC,OAAO,MAAM,EAAE,CAAC,CAAC,qCAAqC;gBACtD,UAAU,GAAG,KAAK,CAAA;YACpB,CAAC;YAED,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,QAAQ,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,kBAAkB,CAAA;YAC/C,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;YAEvC,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAA;YAEzB,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAA;YAC9C,CAAC;YAED,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC3B,CAAC,CAAA;IAiBH,CAAC;IApEC,sBAAsB;IACtB,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;QACnD,CAAC;QAED,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;IACzB,CAAC;IA8CD,+BAA+B;IAC/B,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,SAAS,QAAQ,CAAC,CAAA;QACvD,MAAM,IAAI,CAAC,eAAe,EAAE,CAAA;IAC9B,CAAC;IAED,+BAA+B;IAC/B,eAAe;QACb,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;YAC7D,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE;gBAC7C,OAAO,EAAE,CAAA;YACX,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;CACF"}