CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-parcel--plugin

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

1.06x
Overview
Eval results
Files

reporting.mddocs/

Build Reporting

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.

Capabilities

Reporter Class

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>;
}

Reporter Events

/**
 * 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

/**
 * 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--plugin

docs

bundling.md

compression.md

index.md

naming.md

optimization.md

packaging.md

reporting.md

resolution.md

runtime.md

transformation.md

validation.md

tile.json