// Daemon diagnostic traces (WA_CLI_TRACE=1 or "trace": true in config.json). // Logs: CDP/evaluate calls still pending after >15 s, exceptions inside functions exposed // to the page (puppeteer swallows them), navigations and client events. // Useful to see where whatsapp-web.js hangs when it never reaches `ready`. import { createRequire } from 'node:module'; const require = createRequire(import.meta.url); const QUIET = new Set(['loading_screen', 'message', 'message_create', 'message_ack', 'unread_count', 'media_uploaded']); export function enableTrace(log) { const { CdpPage } = require('puppeteer-core/lib/cjs/puppeteer/cdp/Page.js'); const { CdpCDPSession } = require('puppeteer-core/lib/cjs/puppeteer/cdp/CdpSession.js'); const wweb = require('whatsapp-web.js'); const t = (...a) => log('trace:', ...a); const pending = new Map(); let seq = 0; const track = (desc, p) => { const id = ++seq; pending.set(id, { desc, start: Date.now() }); const done = () => pending.delete(id); p.then(done, (e) => { done(); t('error', desc, String(e?.message ?? e).slice(0, 200)); }); return p; }; setInterval(() => { for (const p of pending.values()) { const s = Math.round((Date.now() - p.start) / 1000); if (s >= 15 && s % 15 === 0) t(`pendiente ${s}s:`, p.desc); } }, 1000).unref(); const send = CdpCDPSession.prototype.send; CdpCDPSession.prototype.send = function (method, ...args) { return track(`cdp ${method}`, send.call(this, method, ...args)); }; const expose = CdpPage.prototype.exposeFunction; CdpPage.prototype.exposeFunction = function (name, fn) { const wrapped = async (...args) => { try { return await fn(...args); } catch (e) { t(`exception in ${name}:`, String(e?.stack ?? e).split('\n').slice(0, 4).join(' | ')); throw e; } }; return track(`exposeFunction(${name})`, expose.call(this, name, wrapped)); }; const emit = wweb.Client.prototype.emit; wweb.Client.prototype.emit = function (event, ...args) { if (!QUIET.has(event)) t('evento', event, event === 'disconnected' || event === 'change_state' ? args[0] : ''); return emit.call(this, event, ...args); }; const init = wweb.Client.prototype.initialize; wweb.Client.prototype.initialize = function (...args) { const iv = setInterval(() => { if (!this.pupPage) return; clearInterval(iv); const page = this.pupPage; page.on('framenavigated', (f) => t('framenavigated', f === page.mainFrame() ? 'main' : 'iframe', f.url().slice(0, 60))); page.on('load', () => t('load')); page.on('pageerror', (e) => t('pageerror', String(e?.message ?? e).slice(0, 150))); }, 20); return init.apply(this, args); }; const inject = wweb.Client.prototype.inject; wweb.Client.prototype.inject = function (...args) { t('inject()'); return track('inject()', inject.apply(this, args)); }; if (inject.waCompat) wweb.Client.prototype.inject.waCompat = true; }