CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-playwright-extra

A modular plugin framework for Playwright to enable enhanced browser automation through plugins.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

plugin-management.mddocs/

Plugin Management

Comprehensive plugin management system that handles plugin registration, dependency resolution, lifecycle management, and error handling. The PluginList class manages all aspects of plugin orchestration within Playwright Extra.

Capabilities

Plugin List Class

The core plugin management class that handles plugin registration, ordering, dependency resolution, and lifecycle event dispatch.

class PluginList {
  readonly list: Plugin[];
  readonly names: string[];
  
  add(plugin: Plugin): boolean;
  setDependencyDefaults(dependencyPath: string, opts: any): this;
  setDependencyResolution(dependencyPath: string, pluginModule: CompatiblePluginModule): this;
  onPluginError(plugin: Plugin, method: PluginMethodName, err: Error): void;
}

Plugin Registration

Add a new plugin to the list after validating its structure and requirements.

/**
 * Add a new plugin to the list (after checking if it's well-formed).
 * @param plugin - Plugin instance to add
 * @returns true if plugin was added successfully, false otherwise
 */
add(plugin: Plugin): boolean;

Usage Examples:

import { chromium } from "playwright-extra";
import StealthPlugin from "puppeteer-extra-plugin-stealth";

const plugin = StealthPlugin();

// Plugin is automatically added when using .use()
chromium.use(plugin);

// Direct access to plugin manager
const wasAdded = chromium.plugins.add(plugin);
console.log(`Plugin added: ${wasAdded}`);

Plugin Inspection

Access registered plugins and their names.

/**
 * Get a list of all registered plugins.
 */
readonly list: Plugin[];

/**
 * Get the names of all registered plugins.
 */
readonly names: string[];

Usage Examples:

import { chromium } from "playwright-extra";

// Check registered plugins
console.log(chromium.plugins.names); // ['stealth', 'recaptcha']

// Inspect plugin instances
chromium.plugins.list.forEach(plugin => {
  console.log(`Plugin: ${plugin.name}`);
  console.log(`Requirements: ${Array.from(plugin.requirements || [])}`);
});

Dependency Configuration

Configure default options for plugins that are implicitly required through the dependencies system.

/**
 * Define default values for plugins implicitly required through the dependencies plugin stanza.
 * @param dependencyPath - The string by which the dependency is listed (not the plugin name)
 * @param opts - Default options to apply to the dependency
 * @returns The PluginList instance for chaining
 */
setDependencyDefaults(dependencyPath: string, opts: any): this;

Usage Examples:

import { chromium } from "playwright-extra";
import StealthPlugin from "puppeteer-extra-plugin-stealth";

chromium.use(StealthPlugin());

// Configure stealth sub-plugin defaults
chromium.plugins.setDependencyDefaults('stealth/evasions/webgl.vendor', {
  vendor: 'Custom Vendor Name',
  renderer: 'Custom Renderer Name'
});

// Configure user agent evasion defaults  
chromium.plugins.setDependencyDefaults('stealth/evasions/user-agent-override', {
  userAgent: 'Mozilla/5.0 (Custom Browser)'
});

Dependency Resolution

Define custom plugin modules for dependencies to avoid dynamic imports, which is useful for bundlers that have issues with dynamic imports.

/**
 * Define custom plugin modules for plugins implicitly required through the dependencies plugin stanza.
 * Using this will prevent dynamic imports from being used, which JS bundlers often have issues with.
 * @param dependencyPath - The dependency path identifier
 * @param pluginModule - The plugin module to use for this dependency
 * @returns The PluginList instance for chaining
 */
setDependencyResolution(dependencyPath: string, pluginModule: CompatiblePluginModule): this;

Usage Examples:

import { chromium } from "playwright-extra";
import StealthPlugin from "puppeteer-extra-plugin-stealth";
import WebGLVendorPlugin from "puppeteer-extra-plugin-stealth/evasions/webgl.vendor";

chromium.use(StealthPlugin());

// Provide explicit plugin modules to avoid dynamic imports
chromium.plugins.setDependencyResolution(
  'stealth/evasions/webgl.vendor',
  WebGLVendorPlugin
);

Error Handling

Handle errors that occur during plugin method execution. This method can be overwritten to customize error handling behavior.

/**
 * Error callback in case calling a plugin method throws an error. Can be overwritten.
 * @param plugin - The plugin that caused the error
 * @param method - The method name that was being executed
 * @param err - The error that occurred
 */
onPluginError(plugin: Plugin, method: PluginMethodName, err: Error): void;

Usage Examples:

import { chromium } from "playwright-extra";

// Customize error handling
chromium.plugins.onPluginError = (plugin, method, error) => {
  console.error(`Plugin ${plugin.name} failed during ${method}:`, error);
  
  // Could implement retry logic, disable plugin, etc.
  if (error.message.includes('timeout')) {
    console.log('Timeout error, continuing execution...');
  } else {
    throw error; // Re-throw critical errors
  }
};

Plugin Lifecycle Dispatch

The plugin manager handles dispatching lifecycle events to registered plugins.

Non-blocking dispatch (fires events without waiting):

dispatch<TMethod extends PluginMethodName>(
  method: TMethod,
  ...args: Parameters<PluginMethodFn<TMethod>>
): void;

Blocking dispatch (waits for all plugins, supports waterfall pattern):

async dispatchBlocking<TMethod extends PluginMethodName>(
  method: TMethod,
  ...args: Parameters<PluginMethodFn<TMethod>>
): Promise<ReturnType<PluginMethodFn<TMethod>>>;

Usage Examples:

// These methods are used internally by PlaywrightExtra
// but can be called directly for custom scenarios

const plugins = chromium.plugins;

// Dispatch non-blocking event
plugins.dispatch('onPageCreated', page);

// Dispatch blocking event with modification support
const modifiedOptions = await plugins.dispatchBlocking('beforeLaunch', options);

Plugin Ordering and Dependencies

The plugin manager automatically handles plugin ordering based on requirements and resolves plugin dependencies.

Plugin ordering - Plugins with runLast requirement are moved to the end:

// Plugin with runLast requirement will be executed last
const plugin = {
  name: 'cleanup-plugin',
  requirements: new Set(['runLast']),
  // ... other plugin properties
};

Dependency resolution - Plugins can declare dependencies that are automatically loaded:

// Plugin declaring dependencies
const plugin = {
  name: 'parent-plugin',
  dependencies: new Set(['stealth/evasions/webgl.vendor']),
  // ... other plugin properties
};

Core Types

interface Plugin extends PuppeteerExtraPlugin {
  _isPuppeteerExtraPlugin: boolean;
  name: string;
  noPuppeteerShim?: boolean;
  requirements?: PluginRequirements;
  dependencies?: PluginDependencies;
  data?: PluginData[];
  getDataFromPlugins?(name?: string): void;
  plugins?: CompatiblePlugin[];
}

type PluginMethodName = keyof PluginLifecycleMethods;

type PluginMethodFn<TMethod extends PluginMethodName> = 
  TMethod extends keyof PluginLifecycleMethods 
    ? PluginLifecycleMethods[TMethod] 
    : never;

type PluginRequirements = Set<'launch' | 'headful' | 'dataFromPlugins' | 'runLast'>;

type PluginDependencies = Set<string> | Map<string, any> | string[];

type CompatiblePluginModule = (...args: any[]) => CompatiblePlugin;

interface PluginData {
  name: string | { [key: string]: any };
  value: { [key: string]: any };
}

Install with Tessl CLI

npx tessl i tessl/npm-playwright-extra

docs

browser-launchers.md

custom-integration.md

index.md

plugin-development.md

plugin-management.md

puppeteer-compatibility.md

tile.json