Plugin API for Parcel bundler - provides base classes for creating Parcel plugins including transformers, resolvers, bundlers, namers, runtimes, packagers, optimizers, compressors, reporters, and validators
67
The Reporter plugin reports build progress, errors, and other events to users and external tools. Reporters provide feedback about the build process and can integrate with development tools and CI/CD systems.
Base class for creating build reporting plugins.
/**
* Base class for build reporting plugins
*/
export declare class Reporter {
constructor(opts: ReporterOpts);
}
/**
* Reporter plugin configuration interface
*/
interface ReporterOpts {
/** Report build events (required) */
report(args: {
event: ReporterEvent;
options: PluginOptions;
logger: PluginLogger;
tracer: PluginTracer;
}): Promise<void>;
}/**
* Events that can be reported during builds
*/
type ReporterEvent =
| BuildStartEvent
| BuildProgressEvent
| BuildSuccessEvent
| BuildFailureEvent
| WatchEvent
| LogEvent;
/**
* Build started event
*/
interface BuildStartEvent {
type: 'buildStart';
options: PluginOptions;
}
/**
* Build progress event
*/
interface BuildProgressEvent {
type: 'buildProgress';
phase: string;
message: string;
}
/**
* Build completed successfully
*/
interface BuildSuccessEvent {
type: 'buildSuccess';
bundleGraph: BundleGraph<NamedBundle>;
buildTime: number;
changedAssets: Map<string, Asset>;
}
/**
* Build failed event
*/
interface BuildFailureEvent {
type: 'buildFailure';
diagnostics: Array<Diagnostic>;
}
/**
* File watch event
*/
interface WatchEvent {
type: 'watchStart' | 'watchEnd';
subscription?: AsyncSubscription;
}
/**
* Log event
*/
interface LogEvent {
type: 'log';
level: 'error' | 'warn' | 'info' | 'verbose' | 'progress' | 'success';
diagnostics?: Array<Diagnostic>;
message?: string;
}Usage Example:
import { Reporter } from "@parcel/plugin";
import chalk from "chalk";
export default new Reporter({
// Report build events (required)
async report({event, options, logger}) {
switch (event.type) {
case 'buildStart':
console.log(chalk.blue('🚀 Build started...'));
this.startTime = Date.now();
break;
case 'buildProgress':
const progressBar = this.getProgressBar(event.phase);
console.log(chalk.yellow(`${progressBar} ${event.message}`));
break;
case 'buildSuccess':
const duration = Date.now() - this.startTime;
const bundles = event.bundleGraph.getBundles();
console.log(chalk.green('✅ Build completed successfully!'));
console.log(chalk.gray(` Built ${bundles.length} bundles in ${duration}ms`));
// Log bundle information
this.reportBundles(bundles);
break;
case 'buildFailure':
console.log(chalk.red('❌ Build failed!'));
// Report errors
for (const diagnostic of event.diagnostics) {
this.reportDiagnostic(diagnostic);
}
break;
case 'watchStart':
console.log(chalk.cyan('👀 Watching for changes...'));
break;
case 'log':
this.reportLog(event);
break;
}
},
getProgressBar(phase) {
const phases = {
'resolving': '📦',
'transforming': '🔄',
'bundling': '📦',
'packaging': '📦',
'optimizing': '⚡'
};
return phases[phase] || '⏳';
},
reportBundles(bundles) {
console.log(chalk.gray('\nBundle Summary:'));
for (const bundle of bundles) {
const size = this.formatSize(bundle.stats.size);
const type = bundle.type.toUpperCase();
const name = bundle.displayName || bundle.name || 'unnamed';
console.log(chalk.gray(` ${type} ${name} (${size})`));
}
},
reportDiagnostic(diagnostic) {
const level = diagnostic.level || 'error';
const color = level === 'error' ? chalk.red : chalk.yellow;
console.log(color(`\n${level.toUpperCase()}: ${diagnostic.message}`));
if (diagnostic.codeFrame) {
console.log(diagnostic.codeFrame);
}
if (diagnostic.filePath) {
console.log(chalk.gray(` at ${diagnostic.filePath}:${diagnostic.start?.line || 0}`));
}
},
reportLog(event) {
const colors = {
error: chalk.red,
warn: chalk.yellow,
info: chalk.blue,
success: chalk.green,
verbose: chalk.gray,
progress: chalk.cyan
};
const color = colors[event.level] || chalk.white;
if (event.message) {
console.log(color(event.message));
}
if (event.diagnostics) {
for (const diagnostic of event.diagnostics) {
this.reportDiagnostic(diagnostic);
}
}
},
formatSize(bytes) {
if (bytes < 1024) return `${bytes}B`;
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
}
});/**
* Diagnostic information for errors and warnings
*/
interface Diagnostic {
/** Diagnostic level */
level?: 'error' | 'warning' | 'info';
/** Main diagnostic message */
message: string;
/** Source file path */
filePath?: FilePath;
/** Source code location */
start?: SourceLocation;
end?: SourceLocation;
/** Code frame showing the error location */
codeFrame?: string;
/** Hints for fixing the issue */
hints?: Array<string>;
/** Documentation URL */
documentationURL?: string;
}Install with Tessl CLI
npx tessl i tessl/npm-parcel--plugindocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10