"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CdpConnection = void 0; const log_js_1 = require("../utils/log.js"); const cdpClient_js_1 = require("./cdpClient.js"); /** * Represents a high-level CDP connection to the browser backend. * Manages a CdpClient instance for each active CDP session. */ class CdpConnection { #transport; /** The CdpClient object attached to the root browser session. */ #browserCdpClient; /** Map from session ID to CdpClient. */ #sessionCdpClients = new Map(); #commandCallbacks = new Map(); #logger; #nextId = 0; constructor(transport, logger) { this.#transport = transport; this.#logger = logger; this.#transport.setOnMessage(this.#onMessage); this.#browserCdpClient = new cdpClient_js_1.CdpClient(this, undefined); } /** Closes the connection to the browser. */ close() { this.#transport.close(); for (const [, { reject, error }] of this.#commandCallbacks) { reject(error); } this.#commandCallbacks.clear(); this.#sessionCdpClients.clear(); } /** The CdpClient object attached to the root browser session. */ browserClient() { return this.#browserCdpClient; } /** * Gets a CdpClient instance attached to the given session ID, * or null if the session is not attached. */ getCdpClient(sessionId) { const cdpClient = this.#sessionCdpClients.get(sessionId); if (!cdpClient) { throw new Error('Unknown CDP session ID'); } return cdpClient; } sendCommand(method, params, sessionId) { return new Promise((resolve, reject) => { const id = this.#nextId++; this.#commandCallbacks.set(id, { resolve, reject, error: new cdpClient_js_1.CloseError(`${method} ${JSON.stringify(params)} ${sessionId ?? ''} call rejected because the connection has been closed.`), }); const cdpMessage = { id, method, params }; if (sessionId) { cdpMessage.sessionId = sessionId; } const cdpMessageStr = JSON.stringify(cdpMessage); void this.#transport.sendMessage(cdpMessageStr)?.catch((error) => { this.#logger?.(`${log_js_1.LogType.cdp}:ERROR`, error); this.#transport.close(); }); this.#logger?.(`${log_js_1.LogType.cdp}:SEND ▸`, JSON.stringify(cdpMessage, null, 2)); }); } #onMessage = (message) => { const messageParsed = JSON.parse(message); const messagePretty = JSON.stringify(messageParsed, null, 2); this.#logger?.(`${log_js_1.LogType.cdp}:RECV ◂`, messagePretty); // Update client map if a session is attached or detached. // Listen for these events on every session. if (messageParsed.method === 'Target.attachedToTarget') { const { sessionId } = messageParsed.params; this.#sessionCdpClients.set(sessionId, new cdpClient_js_1.CdpClient(this, sessionId)); } else if (messageParsed.method === 'Target.detachedFromTarget') { const { sessionId } = messageParsed.params; const client = this.#sessionCdpClients.get(sessionId); if (client) { this.#sessionCdpClients.delete(sessionId); } } if (messageParsed.id !== undefined) { // Handle command response. const callbacks = this.#commandCallbacks.get(messageParsed.id); this.#commandCallbacks.delete(messageParsed.id); if (callbacks) { if (messageParsed.result) { callbacks.resolve(messageParsed.result); } else if (messageParsed.error) { callbacks.reject(messageParsed.error); } } } else if (messageParsed.method) { const client = messageParsed.sessionId ? this.#sessionCdpClients.get(messageParsed.sessionId) : this.#browserCdpClient; client?.emit(messageParsed.method, messageParsed.params || {}); } }; } exports.CdpConnection = CdpConnection; //# sourceMappingURL=cdpConnection.js.map