UNPKG

@monitoro/herd

Version:

Automate your browser, build AI web tools and MCP servers with Monitoro Herd

122 lines (121 loc) 3.85 kB
import { EventEmitter } from 'events'; import { Page } from './Page.js'; export class Device extends EventEmitter { constructor(client, info) { super(); this.pageMap = new Map(); // Changed to number key this.client = client; this.info = info; } get id() { return this.info.id; } get deviceId() { return this.info.deviceId; } get type() { return this.info.type; } get name() { return this.info.name; } get status() { return this.info.status; } get lastActive() { return this.info.lastActive ? new Date(this.info.lastActive) : null; } updateInfo(info) { this.info = info; this.emit('updated', info); } /** * Create a new page in the device */ async newPage() { const response = await this.client.sendCommand(this.deviceId, 'Tabs.createTab', { url: 'about:blank', active: false }); // Unwrap the NATS response which contains the tab info in the result property const tab = response?.result; if (!tab) { throw new Error('Failed to create new page: Invalid response format'); } const tabId = typeof tab.id === 'string' ? parseInt(tab.id, 10) : tab.id; if (isNaN(tabId)) { throw new Error('Invalid tab ID: must be convertible to integer'); } const page = new Page(this.client, this, tabId); this.pageMap.set(tabId, page); page.updateInfo(tab); return page; } /** * List all pages in the device */ async listPages() { const response = await this.client.sendCommand(this.deviceId, 'Tabs.getTabs'); // Unwrap the NATS response const tabs = response?.result; if (!Array.isArray(tabs)) { throw new Error('Failed to list pages: Invalid response format'); } return tabs.map(tabInfo => { const tabId = typeof tabInfo.id === 'string' ? parseInt(tabInfo.id, 10) : tabInfo.id; if (isNaN(tabId)) { throw new Error('Invalid tab ID: must be convertible to integer'); } let page = this.pageMap.get(tabId); if (!page) { page = new Page(this.client, this, tabId); this.pageMap.set(tabId, page); } page.updateInfo(tabInfo); return page; }); } /** * Get a specific page by ID */ async getPage(id) { const pages = await this.listPages(); const page = pages.find(p => p.id === id); if (!page) { throw new Error(`Page ${id} not found`); } return page; } /** * Subscribe to all events from this device */ onEvent(callback) { return this.client.subscribeToDeviceEvents(this.deviceId, callback); } /** * Subscribe to a specific event from this device */ on(eventName, callback) { const unsubscribe = this.client.subscribeToDeviceEvent(this.deviceId, eventName, (event) => { callback(event); }); // Store the unsubscribe function for cleanup const cleanups = this.listeners('cleanup'); cleanups.push(unsubscribe); return this; } /** * Close the device and cleanup resources */ async close() { // Cleanup all pages const pages = await this.listPages(); await Promise.all(pages.map(page => page.close())); this.pageMap.clear(); // Execute cleanup functions const cleanups = this.listeners('cleanup'); cleanups.forEach(cleanup => cleanup()); this.removeAllListeners(); await this.client.sendCommand(this.deviceId, 'Device.close'); } }