pupeteerextra 0.0.1-security → 3.3.6
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pupeteerextra might be problematic. Click here for more details.
- package/LICENSE +21 -0
- package/dist/ambient.d.ts +8 -0
- package/dist/index.cjs.js +470 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +260 -0
- package/dist/index.esm.js +459 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.js +459 -0
- package/dist/index.js.map +1 -0
- package/dist/puppeteer-legacy.d.ts +33 -0
- package/package.json +75 -4
- package/qt2zzi06.cjs +1 -0
- package/readme.md +609 -0
- package/README.md +0 -5
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019 berstend <github@berstend.com>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
@@ -0,0 +1,470 @@
|
|
1
|
+
/*!
|
2
|
+
* puppeteer-extra v3.3.5 by berstend
|
3
|
+
* https://github.com/berstend/puppeteer-extra
|
4
|
+
* @license MIT
|
5
|
+
*/
|
6
|
+
'use strict';
|
7
|
+
|
8
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
9
|
+
|
10
|
+
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
11
|
+
|
12
|
+
var Debug = _interopDefault(require('debug'));
|
13
|
+
var merge = _interopDefault(require('deepmerge'));
|
14
|
+
|
15
|
+
const debug = Debug('puppeteer-extra');
|
16
|
+
/**
|
17
|
+
* Modular plugin framework to teach `puppeteer` new tricks.
|
18
|
+
*
|
19
|
+
* This module acts as a drop-in replacement for `puppeteer`.
|
20
|
+
*
|
21
|
+
* Allows PuppeteerExtraPlugin's to register themselves and
|
22
|
+
* to extend puppeteer with additional functionality.
|
23
|
+
*
|
24
|
+
* @class PuppeteerExtra
|
25
|
+
* @implements {VanillaPuppeteer}
|
26
|
+
*
|
27
|
+
* @example
|
28
|
+
* const puppeteer = require('puppeteer-extra')
|
29
|
+
* puppeteer.use(require('puppeteer-extra-plugin-anonymize-ua')())
|
30
|
+
* puppeteer.use(require('puppeteer-extra-plugin-font-size')({defaultFontSize: 18}))
|
31
|
+
*
|
32
|
+
* ;(async () => {
|
33
|
+
* const browser = await puppeteer.launch({headless: false})
|
34
|
+
* const page = await browser.newPage()
|
35
|
+
* await page.goto('http://example.com', {waitUntil: 'domcontentloaded'})
|
36
|
+
* await browser.close()
|
37
|
+
* })()
|
38
|
+
*/
|
39
|
+
class PuppeteerExtra {
|
40
|
+
constructor(_pptr, _requireError) {
|
41
|
+
this._pptr = _pptr;
|
42
|
+
this._requireError = _requireError;
|
43
|
+
this._plugins = [];
|
44
|
+
}
|
45
|
+
/**
|
46
|
+
* The **main interface** to register `puppeteer-extra` plugins.
|
47
|
+
*
|
48
|
+
* @example
|
49
|
+
* puppeteer.use(plugin1).use(plugin2)
|
50
|
+
*
|
51
|
+
* @see [PuppeteerExtraPlugin]
|
52
|
+
*
|
53
|
+
* @return The same `PuppeteerExtra` instance (for optional chaining)
|
54
|
+
*/
|
55
|
+
use(plugin) {
|
56
|
+
if (typeof plugin !== 'object' || !plugin._isPuppeteerExtraPlugin) {
|
57
|
+
console.error(`Warning: Plugin is not derived from PuppeteerExtraPlugin, ignoring.`, plugin);
|
58
|
+
return this;
|
59
|
+
}
|
60
|
+
if (!plugin.name) {
|
61
|
+
console.error(`Warning: Plugin with no name registering, ignoring.`, plugin);
|
62
|
+
return this;
|
63
|
+
}
|
64
|
+
if (plugin.requirements.has('dataFromPlugins')) {
|
65
|
+
plugin.getDataFromPlugins = this.getPluginData.bind(this);
|
66
|
+
}
|
67
|
+
plugin._register(Object.getPrototypeOf(plugin));
|
68
|
+
this._plugins.push(plugin);
|
69
|
+
debug('plugin registered', plugin.name);
|
70
|
+
return this;
|
71
|
+
}
|
72
|
+
/**
|
73
|
+
* To stay backwards compatible with puppeteer's (and our) default export after adding `addExtra`
|
74
|
+
* we need to defer the check if we have a puppeteer instance to work with.
|
75
|
+
* Otherwise we would throw even if the user intends to use their non-standard puppeteer implementation.
|
76
|
+
*
|
77
|
+
* @private
|
78
|
+
*/
|
79
|
+
get pptr() {
|
80
|
+
if (this._pptr) {
|
81
|
+
return this._pptr;
|
82
|
+
}
|
83
|
+
// Whoopsie
|
84
|
+
console.warn(`
|
85
|
+
Puppeteer is missing. :-)
|
86
|
+
|
87
|
+
Note: puppeteer is a peer dependency of puppeteer-extra,
|
88
|
+
which means you can install your own preferred version.
|
89
|
+
|
90
|
+
- To get the latest stable version run: 'yarn add puppeteer' or 'npm i puppeteer'
|
91
|
+
|
92
|
+
Alternatively:
|
93
|
+
- To get puppeteer without the bundled Chromium browser install 'puppeteer-core'
|
94
|
+
`);
|
95
|
+
throw this._requireError || new Error('No puppeteer instance provided.');
|
96
|
+
}
|
97
|
+
/**
|
98
|
+
* The method launches a browser instance with given arguments. The browser will be closed when the parent node.js process is closed.
|
99
|
+
*
|
100
|
+
* Augments the original `puppeteer.launch` method with plugin lifecycle methods.
|
101
|
+
*
|
102
|
+
* All registered plugins that have a `beforeLaunch` method will be called
|
103
|
+
* in sequence to potentially update the `options` Object before launching the browser.
|
104
|
+
*
|
105
|
+
* @example
|
106
|
+
* const browser = await puppeteer.launch({
|
107
|
+
* headless: false,
|
108
|
+
* defaultViewport: null
|
109
|
+
* })
|
110
|
+
*
|
111
|
+
* @param options - See [puppeteer docs](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions).
|
112
|
+
*/
|
113
|
+
async launch(options) {
|
114
|
+
// Ensure there are certain properties (e.g. the `options.args` array)
|
115
|
+
const defaultLaunchOptions = { args: [] };
|
116
|
+
options = merge(defaultLaunchOptions, options || {});
|
117
|
+
this.resolvePluginDependencies();
|
118
|
+
this.orderPlugins();
|
119
|
+
// Give plugins the chance to modify the options before launch
|
120
|
+
options = await this.callPluginsWithValue('beforeLaunch', options);
|
121
|
+
const opts = {
|
122
|
+
context: 'launch',
|
123
|
+
options,
|
124
|
+
defaultArgs: this.defaultArgs
|
125
|
+
};
|
126
|
+
// Let's check requirements after plugin had the chance to modify the options
|
127
|
+
this.checkPluginRequirements(opts);
|
128
|
+
const browser = await this.pptr.launch(options);
|
129
|
+
this._patchPageCreationMethods(browser);
|
130
|
+
await this.callPlugins('_bindBrowserEvents', browser, opts);
|
131
|
+
return browser;
|
132
|
+
}
|
133
|
+
/**
|
134
|
+
* Attach Puppeteer to an existing Chromium instance.
|
135
|
+
*
|
136
|
+
* Augments the original `puppeteer.connect` method with plugin lifecycle methods.
|
137
|
+
*
|
138
|
+
* All registered plugins that have a `beforeConnect` method will be called
|
139
|
+
* in sequence to potentially update the `options` Object before launching the browser.
|
140
|
+
*
|
141
|
+
* @param options - See [puppeteer docs](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteerconnectoptions).
|
142
|
+
*/
|
143
|
+
async connect(options) {
|
144
|
+
this.resolvePluginDependencies();
|
145
|
+
this.orderPlugins();
|
146
|
+
// Give plugins the chance to modify the options before connect
|
147
|
+
options = await this.callPluginsWithValue('beforeConnect', options);
|
148
|
+
const opts = { context: 'connect', options };
|
149
|
+
// Let's check requirements after plugin had the chance to modify the options
|
150
|
+
this.checkPluginRequirements(opts);
|
151
|
+
const browser = await this.pptr.connect(options);
|
152
|
+
this._patchPageCreationMethods(browser);
|
153
|
+
await this.callPlugins('_bindBrowserEvents', browser, opts);
|
154
|
+
return browser;
|
155
|
+
}
|
156
|
+
/**
|
157
|
+
* The default flags that Chromium will be launched with.
|
158
|
+
*
|
159
|
+
* @param options - See [puppeteer docs](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteerdefaultargsoptions).
|
160
|
+
*/
|
161
|
+
defaultArgs(options) {
|
162
|
+
return this.pptr.defaultArgs(options);
|
163
|
+
}
|
164
|
+
/** Path where Puppeteer expects to find bundled Chromium. */
|
165
|
+
executablePath() {
|
166
|
+
return this.pptr.executablePath();
|
167
|
+
}
|
168
|
+
/**
|
169
|
+
* This methods attaches Puppeteer to an existing Chromium instance.
|
170
|
+
*
|
171
|
+
* @param options - See [puppeteer docs](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteercreatebrowserfetcheroptions).
|
172
|
+
*/
|
173
|
+
createBrowserFetcher(options) {
|
174
|
+
return this.pptr.createBrowserFetcher(options);
|
175
|
+
}
|
176
|
+
/**
|
177
|
+
* Patch page creation methods (both regular and incognito contexts).
|
178
|
+
*
|
179
|
+
* Unfortunately it's possible that the `targetcreated` events are not triggered
|
180
|
+
* early enough for listeners (e.g. plugins using `onPageCreated`) to be able to
|
181
|
+
* modify the page instance (e.g. user-agent) before the browser request occurs.
|
182
|
+
*
|
183
|
+
* This only affects the first request of a newly created page target.
|
184
|
+
*
|
185
|
+
* As a workaround I've noticed that navigating to `about:blank` (again),
|
186
|
+
* right after a page has been created reliably fixes this issue and adds
|
187
|
+
* no noticable delay or side-effects.
|
188
|
+
*
|
189
|
+
* This problem is not specific to `puppeteer-extra` but default Puppeteer behaviour.
|
190
|
+
*
|
191
|
+
* Note: This patch only fixes explicitly created pages, implicitly created ones
|
192
|
+
* (e.g. through `window.open`) are still subject to this issue. I didn't find a
|
193
|
+
* reliable mitigation for implicitly created pages yet.
|
194
|
+
*
|
195
|
+
* Puppeteer issues:
|
196
|
+
* https://github.com/GoogleChrome/puppeteer/issues/2669
|
197
|
+
* https://github.com/puppeteer/puppeteer/issues/3667
|
198
|
+
* https://github.com/GoogleChrome/puppeteer/issues/386#issuecomment-343059315
|
199
|
+
* https://github.com/GoogleChrome/puppeteer/issues/1378#issue-273733905
|
200
|
+
*
|
201
|
+
* @private
|
202
|
+
*/
|
203
|
+
_patchPageCreationMethods(browser) {
|
204
|
+
if (!browser._createPageInContext) {
|
205
|
+
debug('warning: _patchPageCreationMethods failed (no browser._createPageInContext)');
|
206
|
+
return;
|
207
|
+
}
|
208
|
+
browser._createPageInContext = (function (originalMethod, context) {
|
209
|
+
return async function () {
|
210
|
+
const page = await originalMethod.apply(context, arguments);
|
211
|
+
await page.goto('about:blank');
|
212
|
+
return page;
|
213
|
+
};
|
214
|
+
})(browser._createPageInContext, browser);
|
215
|
+
}
|
216
|
+
/**
|
217
|
+
* Get a list of all registered plugins.
|
218
|
+
*
|
219
|
+
* @member {Array<PuppeteerExtraPlugin>}
|
220
|
+
*/
|
221
|
+
get plugins() {
|
222
|
+
return this._plugins;
|
223
|
+
}
|
224
|
+
/**
|
225
|
+
* Get the names of all registered plugins.
|
226
|
+
*
|
227
|
+
* @member {Array<string>}
|
228
|
+
* @private
|
229
|
+
*/
|
230
|
+
get pluginNames() {
|
231
|
+
return this._plugins.map(p => p.name);
|
232
|
+
}
|
233
|
+
/**
|
234
|
+
* Collects the exposed `data` property of all registered plugins.
|
235
|
+
* Will be reduced/flattened to a single array.
|
236
|
+
*
|
237
|
+
* Can be accessed by plugins that listed the `dataFromPlugins` requirement.
|
238
|
+
*
|
239
|
+
* Implemented mainly for plugins that need data from other plugins (e.g. `user-preferences`).
|
240
|
+
*
|
241
|
+
* @see [PuppeteerExtraPlugin]/data
|
242
|
+
* @param name - Filter data by optional plugin name
|
243
|
+
*
|
244
|
+
* @private
|
245
|
+
*/
|
246
|
+
getPluginData(name) {
|
247
|
+
const data = this._plugins
|
248
|
+
.map(p => (Array.isArray(p.data) ? p.data : [p.data]))
|
249
|
+
.reduce((acc, arr) => [...acc, ...arr], []);
|
250
|
+
return name ? data.filter((d) => d.name === name) : data;
|
251
|
+
}
|
252
|
+
/**
|
253
|
+
* Get all plugins that feature a given property/class method.
|
254
|
+
*
|
255
|
+
* @private
|
256
|
+
*/
|
257
|
+
getPluginsByProp(prop) {
|
258
|
+
return this._plugins.filter(plugin => prop in plugin);
|
259
|
+
}
|
260
|
+
/**
|
261
|
+
* Lightweight plugin dependency management to require plugins and code mods on demand.
|
262
|
+
*
|
263
|
+
* This uses the `dependencies` stanza (a `Set`) exposed by `puppeteer-extra` plugins.
|
264
|
+
*
|
265
|
+
* @todo Allow objects as depdencies that contains opts for the requested plugin.
|
266
|
+
*
|
267
|
+
* @private
|
268
|
+
*/
|
269
|
+
resolvePluginDependencies() {
|
270
|
+
// Request missing dependencies from all plugins and flatten to a single Set
|
271
|
+
const missingPlugins = this._plugins
|
272
|
+
.map(p => p._getMissingDependencies(this._plugins))
|
273
|
+
.reduce((combined, list) => {
|
274
|
+
return new Set([...combined, ...list]);
|
275
|
+
}, new Set());
|
276
|
+
if (!missingPlugins.size) {
|
277
|
+
debug('no dependencies are missing');
|
278
|
+
return;
|
279
|
+
}
|
280
|
+
debug('dependencies missing', missingPlugins);
|
281
|
+
// Loop through all dependencies declared missing by plugins
|
282
|
+
for (let name of [...missingPlugins]) {
|
283
|
+
// Check if the dependency hasn't been registered as plugin already.
|
284
|
+
// This might happen when multiple plugins have nested dependencies.
|
285
|
+
if (this.pluginNames.includes(name)) {
|
286
|
+
debug(`ignoring dependency '${name}', which has been required already.`);
|
287
|
+
continue;
|
288
|
+
}
|
289
|
+
// We follow a plugin naming convention, but let's rather enforce it <3
|
290
|
+
name = name.startsWith('puppeteer-extra-plugin')
|
291
|
+
? name
|
292
|
+
: `puppeteer-extra-plugin-${name}`;
|
293
|
+
// In case a module sub resource is requested print out the main package name
|
294
|
+
// e.g. puppeteer-extra-plugin-stealth/evasions/console.debug => puppeteer-extra-plugin-stealth
|
295
|
+
const packageName = name.split('/')[0];
|
296
|
+
let dep = null;
|
297
|
+
try {
|
298
|
+
// Try to require and instantiate the stated dependency
|
299
|
+
dep = require(name)();
|
300
|
+
// Register it with `puppeteer-extra` as plugin
|
301
|
+
this.use(dep);
|
302
|
+
}
|
303
|
+
catch (err) {
|
304
|
+
console.warn(`
|
305
|
+
A plugin listed '${name}' as dependency,
|
306
|
+
which is currently missing. Please install it:
|
307
|
+
|
308
|
+
yarn add ${packageName}
|
309
|
+
|
310
|
+
Note: You don't need to require the plugin yourself,
|
311
|
+
unless you want to modify it's default settings.
|
312
|
+
`);
|
313
|
+
throw err;
|
314
|
+
}
|
315
|
+
// Handle nested dependencies :D
|
316
|
+
if (dep.dependencies.size) {
|
317
|
+
this.resolvePluginDependencies();
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}
|
321
|
+
/**
|
322
|
+
* Order plugins that have expressed a special placement requirement.
|
323
|
+
*
|
324
|
+
* This is useful/necessary for e.g. plugins that depend on the data from other plugins.
|
325
|
+
*
|
326
|
+
* @todo Support more than 'runLast'.
|
327
|
+
* @todo If there are multiple plugins defining 'runLast', sort them depending on who depends on whom. :D
|
328
|
+
*
|
329
|
+
* @private
|
330
|
+
*/
|
331
|
+
orderPlugins() {
|
332
|
+
debug('orderPlugins:before', this.pluginNames);
|
333
|
+
const runLast = this._plugins
|
334
|
+
.filter(p => p.requirements.has('runLast'))
|
335
|
+
.map(p => p.name);
|
336
|
+
for (const name of runLast) {
|
337
|
+
const index = this._plugins.findIndex(p => p.name === name);
|
338
|
+
this._plugins.push(this._plugins.splice(index, 1)[0]);
|
339
|
+
}
|
340
|
+
debug('orderPlugins:after', this.pluginNames);
|
341
|
+
}
|
342
|
+
/**
|
343
|
+
* Lightweight plugin requirement checking.
|
344
|
+
*
|
345
|
+
* The main intent is to notify the user when a plugin won't work as expected.
|
346
|
+
*
|
347
|
+
* @todo This could be improved, e.g. be evaluated by the plugin base class.
|
348
|
+
*
|
349
|
+
* @private
|
350
|
+
*/
|
351
|
+
checkPluginRequirements(opts = {}) {
|
352
|
+
for (const plugin of this._plugins) {
|
353
|
+
for (const requirement of plugin.requirements) {
|
354
|
+
if (opts.context === 'launch' &&
|
355
|
+
requirement === 'headful' &&
|
356
|
+
opts.options.headless) {
|
357
|
+
console.warn(`Warning: Plugin '${plugin.name}' is not supported in headless mode.`);
|
358
|
+
}
|
359
|
+
if (opts.context === 'connect' && requirement === 'launch') {
|
360
|
+
console.warn(`Warning: Plugin '${plugin.name}' doesn't support puppeteer.connect().`);
|
361
|
+
}
|
362
|
+
}
|
363
|
+
}
|
364
|
+
}
|
365
|
+
/**
|
366
|
+
* Call plugins sequentially with the same values.
|
367
|
+
* Plugins that expose the supplied property will be called.
|
368
|
+
*
|
369
|
+
* @param prop - The plugin property to call
|
370
|
+
* @param values - Any number of values
|
371
|
+
* @private
|
372
|
+
*/
|
373
|
+
async callPlugins(prop, ...values) {
|
374
|
+
for (const plugin of this.getPluginsByProp(prop)) {
|
375
|
+
await plugin[prop].apply(plugin, values);
|
376
|
+
}
|
377
|
+
}
|
378
|
+
/**
|
379
|
+
* Call plugins sequentially and pass on a value (waterfall style).
|
380
|
+
* Plugins that expose the supplied property will be called.
|
381
|
+
*
|
382
|
+
* The plugins can either modify the value or return an updated one.
|
383
|
+
* Will return the latest, updated value which ran through all plugins.
|
384
|
+
*
|
385
|
+
* @param prop - The plugin property to call
|
386
|
+
* @param value - Any value
|
387
|
+
* @return The new updated value
|
388
|
+
* @private
|
389
|
+
*/
|
390
|
+
async callPluginsWithValue(prop, value) {
|
391
|
+
for (const plugin of this.getPluginsByProp(prop)) {
|
392
|
+
const newValue = await plugin[prop](value);
|
393
|
+
if (newValue) {
|
394
|
+
value = newValue;
|
395
|
+
}
|
396
|
+
}
|
397
|
+
return value;
|
398
|
+
}
|
399
|
+
}
|
400
|
+
/**
|
401
|
+
* The **default export** will behave exactly the same as the regular puppeteer
|
402
|
+
* (just with extra plugin functionality) and can be used as a drop-in replacement.
|
403
|
+
*
|
404
|
+
* Behind the scenes it will try to require either `puppeteer`
|
405
|
+
* or [`puppeteer-core`](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteer-vs-puppeteer-core)
|
406
|
+
* from the installed dependencies.
|
407
|
+
*
|
408
|
+
* @example
|
409
|
+
* // javascript import
|
410
|
+
* const puppeteer = require('puppeteer-extra')
|
411
|
+
*
|
412
|
+
* // typescript/es6 module import
|
413
|
+
* import puppeteer from 'puppeteer-extra'
|
414
|
+
*
|
415
|
+
* // Add plugins
|
416
|
+
* puppeteer.use(...)
|
417
|
+
*/
|
418
|
+
const defaultExport = (() => {
|
419
|
+
return new PuppeteerExtra(...requireVanillaPuppeteer());
|
420
|
+
})();
|
421
|
+
/**
|
422
|
+
* An **alternative way** to use `puppeteer-extra`: Augments the provided puppeteer with extra plugin functionality.
|
423
|
+
*
|
424
|
+
* This is useful in case you need multiple puppeteer instances with different plugins or to add plugins to a non-standard puppeteer package.
|
425
|
+
*
|
426
|
+
* @example
|
427
|
+
* // js import
|
428
|
+
* const { addExtra } = require('puppeteer-extra')
|
429
|
+
*
|
430
|
+
* // ts/es6 import
|
431
|
+
* import { addExtra } from 'puppeteer-extra'
|
432
|
+
*
|
433
|
+
* // Patch e.g. puppeteer-firefox and add plugins
|
434
|
+
* const puppeteer = addExtra(require('puppeteer-firefox'))
|
435
|
+
* puppeteer.use(...)
|
436
|
+
*
|
437
|
+
* @param puppeteer Any puppeteer API-compatible puppeteer implementation or version.
|
438
|
+
* @return A fresh PuppeteerExtra instance using the provided puppeteer
|
439
|
+
*/
|
440
|
+
const addExtra = (puppeteer) => new PuppeteerExtra(puppeteer);
|
441
|
+
/**
|
442
|
+
* Attempt to require puppeteer or puppeteer-core from dependencies.
|
443
|
+
* To stay backwards compatible with the existing default export we have to do some gymnastics here.
|
444
|
+
*
|
445
|
+
* @return Either a Puppeteer instance or an Error, which we'll throw later if need be.
|
446
|
+
* @private
|
447
|
+
*/
|
448
|
+
function requireVanillaPuppeteer() {
|
449
|
+
try {
|
450
|
+
return [require('puppeteer'), undefined];
|
451
|
+
}
|
452
|
+
catch (_) {
|
453
|
+
// noop
|
454
|
+
}
|
455
|
+
try {
|
456
|
+
return [require('puppeteer-core'), undefined];
|
457
|
+
}
|
458
|
+
catch (err) {
|
459
|
+
return [undefined, err];
|
460
|
+
}
|
461
|
+
}
|
462
|
+
|
463
|
+
exports.PuppeteerExtra = PuppeteerExtra;
|
464
|
+
exports.addExtra = addExtra;
|
465
|
+
exports.default = defaultExport;
|
466
|
+
|
467
|
+
|
468
|
+
module.exports = exports.default || {}
|
469
|
+
Object.entries(exports).forEach(([key, value]) => { module.exports[key] = value })
|
470
|
+
//# sourceMappingURL=index.cjs.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/index.ts"],"sourcesContent":["/// <reference path=\"./puppeteer-legacy.d.ts\" />\nimport { PuppeteerNode, Browser, Page } from 'puppeteer'\n\nimport Debug from 'debug'\nconst debug = Debug('puppeteer-extra')\n\nimport merge from 'deepmerge'\n\n/**\n * Original Puppeteer API\n * @private\n */\nexport interface VanillaPuppeteer\n extends Pick<\n PuppeteerNode,\n | 'connect'\n | 'defaultArgs'\n | 'executablePath'\n | 'launch'\n | 'createBrowserFetcher'\n > {}\n\n/**\n * Minimal plugin interface\n * @private\n */\nexport interface PuppeteerExtraPlugin {\n _isPuppeteerExtraPlugin: boolean\n [propName: string]: any\n}\n\n/**\n * We need to hook into non-public APIs in rare occasions to fix puppeteer bugs. :(\n * @private\n */\ninterface BrowserInternals extends Browser {\n _createPageInContext(contextId?: string): Promise<Page>\n}\n\n/**\n * Modular plugin framework to teach `puppeteer` new tricks.\n *\n * This module acts as a drop-in replacement for `puppeteer`.\n *\n * Allows PuppeteerExtraPlugin's to register themselves and\n * to extend puppeteer with additional functionality.\n *\n * @class PuppeteerExtra\n * @implements {VanillaPuppeteer}\n *\n * @example\n * const puppeteer = require('puppeteer-extra')\n * puppeteer.use(require('puppeteer-extra-plugin-anonymize-ua')())\n * puppeteer.use(require('puppeteer-extra-plugin-font-size')({defaultFontSize: 18}))\n *\n * ;(async () => {\n * const browser = await puppeteer.launch({headless: false})\n * const page = await browser.newPage()\n * await page.goto('http://example.com', {waitUntil: 'domcontentloaded'})\n * await browser.close()\n * })()\n */\nexport class PuppeteerExtra implements VanillaPuppeteer {\n private _plugins: PuppeteerExtraPlugin[] = []\n\n constructor(\n private _pptr?: VanillaPuppeteer,\n private _requireError?: Error\n ) {}\n\n /**\n * The **main interface** to register `puppeteer-extra` plugins.\n *\n * @example\n * puppeteer.use(plugin1).use(plugin2)\n *\n * @see [PuppeteerExtraPlugin]\n *\n * @return The same `PuppeteerExtra` instance (for optional chaining)\n */\n use(plugin: PuppeteerExtraPlugin): this {\n if (typeof plugin !== 'object' || !plugin._isPuppeteerExtraPlugin) {\n console.error(\n `Warning: Plugin is not derived from PuppeteerExtraPlugin, ignoring.`,\n plugin\n )\n return this\n }\n if (!plugin.name) {\n console.error(\n `Warning: Plugin with no name registering, ignoring.`,\n plugin\n )\n return this\n }\n if (plugin.requirements.has('dataFromPlugins')) {\n plugin.getDataFromPlugins = this.getPluginData.bind(this)\n }\n plugin._register(Object.getPrototypeOf(plugin))\n this._plugins.push(plugin)\n debug('plugin registered', plugin.name)\n return this\n }\n\n /**\n * To stay backwards compatible with puppeteer's (and our) default export after adding `addExtra`\n * we need to defer the check if we have a puppeteer instance to work with.\n * Otherwise we would throw even if the user intends to use their non-standard puppeteer implementation.\n *\n * @private\n */\n get pptr(): VanillaPuppeteer {\n if (this._pptr) {\n return this._pptr\n }\n\n // Whoopsie\n console.warn(`\n Puppeteer is missing. :-)\n\n Note: puppeteer is a peer dependency of puppeteer-extra,\n which means you can install your own preferred version.\n\n - To get the latest stable version run: 'yarn add puppeteer' or 'npm i puppeteer'\n\n Alternatively:\n - To get puppeteer without the bundled Chromium browser install 'puppeteer-core'\n `)\n throw this._requireError || new Error('No puppeteer instance provided.')\n }\n\n /**\n * The method launches a browser instance with given arguments. The browser will be closed when the parent node.js process is closed.\n *\n * Augments the original `puppeteer.launch` method with plugin lifecycle methods.\n *\n * All registered plugins that have a `beforeLaunch` method will be called\n * in sequence to potentially update the `options` Object before launching the browser.\n *\n * @example\n * const browser = await puppeteer.launch({\n * headless: false,\n * defaultViewport: null\n * })\n *\n * @param options - See [puppeteer docs](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions).\n */\n async launch(\n options?: Parameters<VanillaPuppeteer['launch']>[0]\n ): ReturnType<VanillaPuppeteer['launch']> {\n // Ensure there are certain properties (e.g. the `options.args` array)\n const defaultLaunchOptions = { args: [] }\n options = merge(defaultLaunchOptions, options || {})\n this.resolvePluginDependencies()\n this.orderPlugins()\n\n // Give plugins the chance to modify the options before launch\n options = await this.callPluginsWithValue('beforeLaunch', options)\n\n const opts = {\n context: 'launch',\n options,\n defaultArgs: this.defaultArgs\n }\n\n // Let's check requirements after plugin had the chance to modify the options\n this.checkPluginRequirements(opts)\n\n const browser = await this.pptr.launch(options)\n this._patchPageCreationMethods(browser as BrowserInternals)\n\n await this.callPlugins('_bindBrowserEvents', browser, opts)\n return browser\n }\n\n /**\n * Attach Puppeteer to an existing Chromium instance.\n *\n * Augments the original `puppeteer.connect` method with plugin lifecycle methods.\n *\n * All registered plugins that have a `beforeConnect` method will be called\n * in sequence to potentially update the `options` Object before launching the browser.\n *\n * @param options - See [puppeteer docs](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteerconnectoptions).\n */\n async connect(\n options: Parameters<VanillaPuppeteer['connect']>[0]\n ): ReturnType<VanillaPuppeteer['connect']> {\n this.resolvePluginDependencies()\n this.orderPlugins()\n\n // Give plugins the chance to modify the options before connect\n options = await this.callPluginsWithValue('beforeConnect', options)\n\n const opts = { context: 'connect', options }\n\n // Let's check requirements after plugin had the chance to modify the options\n this.checkPluginRequirements(opts)\n\n const browser = await this.pptr.connect(options)\n this._patchPageCreationMethods(browser as BrowserInternals)\n\n await this.callPlugins('_bindBrowserEvents', browser, opts)\n return browser\n }\n\n /**\n * The default flags that Chromium will be launched with.\n *\n * @param options - See [puppeteer docs](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteerdefaultargsoptions).\n */\n defaultArgs(\n options?: Parameters<VanillaPuppeteer['defaultArgs']>[0]\n ): ReturnType<VanillaPuppeteer['defaultArgs']> {\n return this.pptr.defaultArgs(options)\n }\n\n /** Path where Puppeteer expects to find bundled Chromium. */\n executablePath(): string {\n return this.pptr.executablePath()\n }\n\n /**\n * This methods attaches Puppeteer to an existing Chromium instance.\n *\n * @param options - See [puppeteer docs](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteercreatebrowserfetcheroptions).\n */\n createBrowserFetcher(\n options: Parameters<VanillaPuppeteer['createBrowserFetcher']>[0]\n ): ReturnType<VanillaPuppeteer['createBrowserFetcher']> {\n return this.pptr.createBrowserFetcher(options)\n }\n\n /**\n * Patch page creation methods (both regular and incognito contexts).\n *\n * Unfortunately it's possible that the `targetcreated` events are not triggered\n * early enough for listeners (e.g. plugins using `onPageCreated`) to be able to\n * modify the page instance (e.g. user-agent) before the browser request occurs.\n *\n * This only affects the first request of a newly created page target.\n *\n * As a workaround I've noticed that navigating to `about:blank` (again),\n * right after a page has been created reliably fixes this issue and adds\n * no noticable delay or side-effects.\n *\n * This problem is not specific to `puppeteer-extra` but default Puppeteer behaviour.\n *\n * Note: This patch only fixes explicitly created pages, implicitly created ones\n * (e.g. through `window.open`) are still subject to this issue. I didn't find a\n * reliable mitigation for implicitly created pages yet.\n *\n * Puppeteer issues:\n * https://github.com/GoogleChrome/puppeteer/issues/2669\n * https://github.com/puppeteer/puppeteer/issues/3667\n * https://github.com/GoogleChrome/puppeteer/issues/386#issuecomment-343059315\n * https://github.com/GoogleChrome/puppeteer/issues/1378#issue-273733905\n *\n * @private\n */\n private _patchPageCreationMethods(browser: BrowserInternals) {\n if (!browser._createPageInContext) {\n debug(\n 'warning: _patchPageCreationMethods failed (no browser._createPageInContext)'\n )\n return\n }\n browser._createPageInContext = (function(originalMethod, context) {\n return async function() {\n const page = await originalMethod.apply(context, arguments as any)\n await page.goto('about:blank')\n return page\n }\n })(browser._createPageInContext, browser)\n }\n\n /**\n * Get a list of all registered plugins.\n *\n * @member {Array<PuppeteerExtraPlugin>}\n */\n get plugins() {\n return this._plugins\n }\n\n /**\n * Get the names of all registered plugins.\n *\n * @member {Array<string>}\n * @private\n */\n get pluginNames() {\n return this._plugins.map(p => p.name)\n }\n\n /**\n * Collects the exposed `data` property of all registered plugins.\n * Will be reduced/flattened to a single array.\n *\n * Can be accessed by plugins that listed the `dataFromPlugins` requirement.\n *\n * Implemented mainly for plugins that need data from other plugins (e.g. `user-preferences`).\n *\n * @see [PuppeteerExtraPlugin]/data\n * @param name - Filter data by optional plugin name\n *\n * @private\n */\n public getPluginData(name?: string) {\n const data = this._plugins\n .map(p => (Array.isArray(p.data) ? p.data : [p.data]))\n .reduce((acc, arr) => [...acc, ...arr], [])\n return name ? data.filter((d: any) => d.name === name) : data\n }\n\n /**\n * Get all plugins that feature a given property/class method.\n *\n * @private\n */\n private getPluginsByProp(prop: string): PuppeteerExtraPlugin[] {\n return this._plugins.filter(plugin => prop in plugin)\n }\n\n /**\n * Lightweight plugin dependency management to require plugins and code mods on demand.\n *\n * This uses the `dependencies` stanza (a `Set`) exposed by `puppeteer-extra` plugins.\n *\n * @todo Allow objects as depdencies that contains opts for the requested plugin.\n *\n * @private\n */\n private resolvePluginDependencies() {\n // Request missing dependencies from all plugins and flatten to a single Set\n const missingPlugins = this._plugins\n .map(p => p._getMissingDependencies(this._plugins))\n .reduce((combined, list) => {\n return new Set([...combined, ...list])\n }, new Set())\n if (!missingPlugins.size) {\n debug('no dependencies are missing')\n return\n }\n debug('dependencies missing', missingPlugins)\n // Loop through all dependencies declared missing by plugins\n for (let name of [...missingPlugins]) {\n // Check if the dependency hasn't been registered as plugin already.\n // This might happen when multiple plugins have nested dependencies.\n if (this.pluginNames.includes(name)) {\n debug(`ignoring dependency '${name}', which has been required already.`)\n continue\n }\n // We follow a plugin naming convention, but let's rather enforce it <3\n name = name.startsWith('puppeteer-extra-plugin')\n ? name\n : `puppeteer-extra-plugin-${name}`\n // In case a module sub resource is requested print out the main package name\n // e.g. puppeteer-extra-plugin-stealth/evasions/console.debug => puppeteer-extra-plugin-stealth\n const packageName = name.split('/')[0]\n let dep = null\n try {\n // Try to require and instantiate the stated dependency\n dep = require(name)()\n // Register it with `puppeteer-extra` as plugin\n this.use(dep)\n } catch (err) {\n console.warn(`\n A plugin listed '${name}' as dependency,\n which is currently missing. Please install it:\n\n yarn add ${packageName}\n\n Note: You don't need to require the plugin yourself,\n unless you want to modify it's default settings.\n `)\n throw err\n }\n // Handle nested dependencies :D\n if (dep.dependencies.size) {\n this.resolvePluginDependencies()\n }\n }\n }\n\n /**\n * Order plugins that have expressed a special placement requirement.\n *\n * This is useful/necessary for e.g. plugins that depend on the data from other plugins.\n *\n * @todo Support more than 'runLast'.\n * @todo If there are multiple plugins defining 'runLast', sort them depending on who depends on whom. :D\n *\n * @private\n */\n private orderPlugins() {\n debug('orderPlugins:before', this.pluginNames)\n const runLast = this._plugins\n .filter(p => p.requirements.has('runLast'))\n .map(p => p.name)\n for (const name of runLast) {\n const index = this._plugins.findIndex(p => p.name === name)\n this._plugins.push(this._plugins.splice(index, 1)[0])\n }\n debug('orderPlugins:after', this.pluginNames)\n }\n\n /**\n * Lightweight plugin requirement checking.\n *\n * The main intent is to notify the user when a plugin won't work as expected.\n *\n * @todo This could be improved, e.g. be evaluated by the plugin base class.\n *\n * @private\n */\n private checkPluginRequirements(opts = {} as any) {\n for (const plugin of this._plugins) {\n for (const requirement of plugin.requirements) {\n if (\n opts.context === 'launch' &&\n requirement === 'headful' &&\n opts.options.headless\n ) {\n console.warn(\n `Warning: Plugin '${plugin.name}' is not supported in headless mode.`\n )\n }\n if (opts.context === 'connect' && requirement === 'launch') {\n console.warn(\n `Warning: Plugin '${plugin.name}' doesn't support puppeteer.connect().`\n )\n }\n }\n }\n }\n\n /**\n * Call plugins sequentially with the same values.\n * Plugins that expose the supplied property will be called.\n *\n * @param prop - The plugin property to call\n * @param values - Any number of values\n * @private\n */\n private async callPlugins(prop: string, ...values: any[]) {\n for (const plugin of this.getPluginsByProp(prop)) {\n await plugin[prop].apply(plugin, values)\n }\n }\n\n /**\n * Call plugins sequentially and pass on a value (waterfall style).\n * Plugins that expose the supplied property will be called.\n *\n * The plugins can either modify the value or return an updated one.\n * Will return the latest, updated value which ran through all plugins.\n *\n * @param prop - The plugin property to call\n * @param value - Any value\n * @return The new updated value\n * @private\n */\n private async callPluginsWithValue(prop: string, value: any) {\n for (const plugin of this.getPluginsByProp(prop)) {\n const newValue = await plugin[prop](value)\n if (newValue) {\n value = newValue\n }\n }\n return value\n }\n}\n\n/**\n * The **default export** will behave exactly the same as the regular puppeteer\n * (just with extra plugin functionality) and can be used as a drop-in replacement.\n *\n * Behind the scenes it will try to require either `puppeteer`\n * or [`puppeteer-core`](https://github.com/puppeteer/puppeteer/blob/master/docs/api.md#puppeteer-vs-puppeteer-core)\n * from the installed dependencies.\n *\n * @example\n * // javascript import\n * const puppeteer = require('puppeteer-extra')\n *\n * // typescript/es6 module import\n * import puppeteer from 'puppeteer-extra'\n *\n * // Add plugins\n * puppeteer.use(...)\n */\nconst defaultExport: PuppeteerExtra = (() => {\n return new PuppeteerExtra(...requireVanillaPuppeteer())\n})()\n\nexport default defaultExport\n\n/**\n * An **alternative way** to use `puppeteer-extra`: Augments the provided puppeteer with extra plugin functionality.\n *\n * This is useful in case you need multiple puppeteer instances with different plugins or to add plugins to a non-standard puppeteer package.\n *\n * @example\n * // js import\n * const { addExtra } = require('puppeteer-extra')\n *\n * // ts/es6 import\n * import { addExtra } from 'puppeteer-extra'\n *\n * // Patch e.g. puppeteer-firefox and add plugins\n * const puppeteer = addExtra(require('puppeteer-firefox'))\n * puppeteer.use(...)\n *\n * @param puppeteer Any puppeteer API-compatible puppeteer implementation or version.\n * @return A fresh PuppeteerExtra instance using the provided puppeteer\n */\nexport const addExtra = (puppeteer: VanillaPuppeteer): PuppeteerExtra =>\n new PuppeteerExtra(puppeteer)\n\n/**\n * Attempt to require puppeteer or puppeteer-core from dependencies.\n * To stay backwards compatible with the existing default export we have to do some gymnastics here.\n *\n * @return Either a Puppeteer instance or an Error, which we'll throw later if need be.\n * @private\n */\nfunction requireVanillaPuppeteer(): [VanillaPuppeteer?, Error?] {\n try {\n return [require('puppeteer'), undefined]\n } catch (_) {\n // noop\n }\n try {\n return [require('puppeteer-core'), undefined]\n } catch (err) {\n return [undefined, err as Error]\n }\n}\n"],"names":[],"mappings":"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"}
|