Tons of Solutions Engineering work done today for the rest of the CS team! Headway, Howard Hanna, Engels, Brighton, etc. Also completed Datasnippers auth flow and worked on Anthology's script. Cloned Anthology's courses (900..) and will clone Full Story on Monday.

This commit is contained in:
Norm Rasmussen
2024-01-05 17:07:59 -05:00
parent ce261975ca
commit a5fe4bd2c8
3157 changed files with 554269 additions and 16 deletions

View File

@ -0,0 +1,125 @@
"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 all CdpClients (each backed by a Session ID) instance for each active
* CDP session.
*/
class CdpConnection {
static LOGGER_PREFIX_RECV = `${log_js_1.LogType.cdp}:RECV ◂`;
static LOGGER_PREFIX_SEND = `${log_js_1.LogType.cdp}:SEND ▸`;
#mainBrowserCdpClient;
#transport;
/** Map from session ID to CdpClient.
* `undefined` points to the main browser session. */
#sessionCdpClients = new Map();
#commandCallbacks = new Map();
#logger;
#nextId = 0;
constructor(transport, logger) {
this.#transport = transport;
this.#logger = logger;
this.#transport.setOnMessage(this.#onMessage);
// Create default Browser CDP Session.
this.#mainBrowserCdpClient = this.#createCdpClient(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();
}
async createBrowserSession() {
const { sessionId } = await this.#mainBrowserCdpClient.sendCommand('Target.attachToBrowserTarget');
return this.#createCdpClient(sessionId);
}
/**
* 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: ${sessionId}`);
}
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;
}
void this.#transport
.sendMessage(JSON.stringify(cdpMessage))
?.catch((error) => {
this.#logger?.(log_js_1.LogType.debugError, error);
this.#transport.close();
});
this.#logger?.(CdpConnection.LOGGER_PREFIX_SEND, cdpMessage);
});
}
#onMessage = (json) => {
const message = JSON.parse(json);
this.#logger?.(CdpConnection.LOGGER_PREFIX_RECV, message);
// Update client map if a session is attached
// Listen for these events on every session.
if (message.method === 'Target.attachedToTarget') {
const { sessionId } = message.params;
this.#createCdpClient(sessionId);
}
if (message.id !== undefined) {
// Handle command response.
const callbacks = this.#commandCallbacks.get(message.id);
this.#commandCallbacks.delete(message.id);
if (callbacks) {
if (message.result) {
callbacks.resolve(message.result);
}
else if (message.error) {
callbacks.reject(message.error);
}
}
}
else if (message.method) {
const client = this.#sessionCdpClients.get(message.sessionId ?? undefined);
client?.emit(message.method, message.params || {});
// Update client map if a session is detached
// But emit on that session
if (message.method === 'Target.detachedFromTarget') {
const { sessionId } = message.params;
const client = this.#sessionCdpClients.get(sessionId);
if (client) {
this.#sessionCdpClients.delete(sessionId);
client.removeAllListeners();
}
}
}
};
/**
* Creates a new CdpClient instance for the given session ID.
* @param sessionId either a string, or undefined for the main browser session.
* The main browser session is used only to create new browser sessions.
* @private
*/
#createCdpClient(sessionId) {
const cdpClient = new CdpClient_js_1.CdpClient(this, sessionId);
this.#sessionCdpClients.set(sessionId, cdpClient);
return cdpClient;
}
}
exports.CdpConnection = CdpConnection;
//# sourceMappingURL=CdpConnection.js.map