puppeteer-pro
Version:
A simple puppeteer wrapper to enable useful plugins with ease
159 lines • 6.12 kB
JavaScript
"use strict";
/* eslint-disable prefer-rest-params */
Object.defineProperty(exports, "__esModule", { value: true });
exports.Plugin = void 0;
const shared_1 = require("./shared");
class Plugin {
constructor() {
this.browser = null;
this.initialized = false;
this.startCounter = 0;
this.dependencies = [];
this.requiresInterception = false;
}
get isInitialized() { return this.initialized; }
get isStopped() { return this.startCounter === 0; }
async addDependency(plugin) {
this.dependencies.push(plugin);
}
async init(browser) {
if (this.initialized)
return;
this.browser = browser;
const offOnClose = [];
browser.browserEvents.once('close', async () => {
offOnClose.forEach(fn => fn());
this.browser = null;
this.initialized = false;
this.startCounter = 0;
await this.onClose();
});
this.startCounter++;
const thisOnTargetCreated = this.onTargetCreated.bind(this);
browser.on('targetcreated', thisOnTargetCreated);
offOnClose.push(() => browser.off('targetcreated', thisOnTargetCreated));
this.initialized = true;
this.dependencies.forEach(x => x.init(browser));
return this.afterLaunch(browser);
}
async afterLaunch(_browser) { null; }
async onClose() { null; }
async onTargetCreated(target) {
if (this.isStopped)
return;
if (target.type() !== 'page')
return;
const page = (0, shared_1.newPage)(await target.page());
if (page.isClosed())
return;
const offOnClose = [];
page.once('close', async () => {
offOnClose.forEach(fn => fn());
});
const requestHandlers = [];
page.on('request', request => {
const _respond = request.respond;
let responded = 0;
let respondArgs;
const _abort = request.abort;
let aborted = 0;
let abortArgs;
const _continue = request.continue;
let continued = 0;
let continueArgs;
const handleRequest = async function () {
const total = responded + aborted + continued;
if (!request._interceptionHandled) {
if (responded === 1)
await _respond.apply(request, respondArgs);
else if (responded === 0 && aborted >= 1 && total === requestHandlers.length)
await _abort.apply(request, abortArgs);
else if (continued === requestHandlers.length)
await _continue.apply(request, continueArgs);
}
};
request.respond = async function () { responded++; respondArgs = respondArgs || arguments; await handleRequest(); };
request.abort = async function () { aborted++; abortArgs = abortArgs || arguments; await handleRequest(); };
request.continue = async function () { continued++; continueArgs = continueArgs || arguments; await handleRequest(); };
requestHandlers.forEach(handler => handler(request));
});
const _pageOn = page.on;
page.on = function async(eventName, handler) {
if (eventName === 'request') {
requestHandlers.push(handler);
return page;
}
else {
return _pageOn.call(page, eventName, handler);
}
};
if (this.requiresInterception) {
await page.setRequestInterception(true);
const thisOnRequest = this.onRequest.bind(this);
page.on('request', thisOnRequest);
offOnClose.push(() => page.off('request', thisOnRequest));
}
const thisOnDialog = this.onDialog.bind(this);
page.on('dialog', thisOnDialog);
offOnClose.push(() => page.off('dialog', thisOnDialog));
await this.onPageCreated(page);
}
async onPageCreated(_page) { null; }
async onRequest(request) {
const interceptionHandled = request._interceptionHandled;
if (interceptionHandled)
return;
if (this.isStopped)
return request.continue();
await this.processRequest(request);
}
async processRequest(_request) { null; }
async onDialog(dialog) {
if (this.isStopped)
return;
const _dismiss = dialog.dismiss;
dialog.dismiss = async () => {
if (dialog.handled)
return;
await _dismiss.apply(dialog);
};
await this.processDialog(dialog);
}
async processDialog(_dialog) { null; }
async beforeRestart() { null; }
async restart() {
await this.beforeRestart();
this.startCounter++;
if (this.requiresInterception && this.browser)
this.browser.interceptions++;
this.dependencies.forEach(x => x.restart());
await this.afterRestart();
}
async afterRestart() { null; }
async beforeStop() { null; }
async stop() {
await this.beforeStop();
this.startCounter--;
if (this.requiresInterception && this.browser)
this.browser.interceptions--;
if (this.browser && this.browser.interceptions === 0) {
const pages = await this.browser.pages();
pages.filter(x => !x.isClosed()).forEach(async (page) => {
await page.setRequestInterception(false);
});
}
this.dependencies.forEach(x => x.stop());
await this.afterStop();
}
async afterStop() { null; }
async getFirstPage() {
if (!this.browser)
return null;
const pages = await this.browser.pages();
const openPages = pages.filter(x => !x.isClosed());
const activePages = pages.filter(x => x.url() !== 'about:blank');
return activePages[0] || openPages[0];
}
}
exports.Plugin = Plugin;
//# sourceMappingURL=index.js.map