npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@plevands/epson-thermal-printer

v0.2.0

Published

Library for Epson thermal printer integration with PDF support and React hooks

Downloads

180

Readme

@plevands/epson-thermal-printer

npm version License: MIT TypeScript

Library for Epson thermal printer integration with PDF support and React hooks.

Requirements

  • Node.js 18.x or higher
  • React 18.x or higher (optional, for hooks API)
  • pdfjs-dist 4.x or higher (optional, for PDF processing)
  • Epson thermal printer with network connectivity

Features

  • Official Epson ePOS SDK integration with TypeScript support
  • 🔄 Lazy loading - SDK loads automatically on first use
  • 📄 PDF Processing - Intelligent margin trimming and scaling for thermal printers
  • ⚛️ React Hooks - Modern hooks-based API (useEpsonPrinter, usePrinterConfig, usePdfProcessor)
  • 🔧 Fully Configurable - Control PDF processing, print quality, paper width, and more
  • 📦 TypeScript First - Complete type definitions included
  • 🎯 Zero Config - Works out of the box with sensible defaults
  • Self-contained - Epson SDK is embedded, no external dependencies to configure

Installation

Development with npm link

# In the library directory
npm install
npm run build
npm link

# In your project
npm link @plevands/epson-thermal-printer

Usage in Your Projects

npm install @plevands/epson-thermal-printer

Note: The Epson ePOS SDK v2.27.0 is embedded in the library. No additional setup required!

PDF Processing (Optional)

If you want to use PDF processing features (processPdfFile, usePdfProcessor), install pdfjs-dist:

npm install pdfjs-dist

If you don't use PDF features, you don't need to install it. The library uses dynamic imports so pdfjs-dist is only loaded when you call PDF processing functions.

Setup (Optional)

Custom PDF.js Worker

The PDF.js worker is auto-configured to use a CDN. Only configure it if you want to use your own worker:

import { configurePdfWorker } from '@plevands/epson-thermal-printer';

// Use your own worker instead of CDN
configurePdfWorker('/assets/pdf.worker.min.mjs');

Quick Start

Basic Usage (Hooks API)

import { useEpsonPrinter, usePrinterConfig } from '@plevands/epson-thermal-printer';

function MyPrintComponent() {
  const { config, isConfigured } = usePrinterConfig();
  const { print, isLoading, error } = useEpsonPrinter(config);

  const handlePrint = async () => {
    const canvas = document.querySelector('canvas') as HTMLCanvasElement;
    const result = await print(canvas);
    
    if (result.success) {
      alert('Print successful!');
    } else {
      alert(`Print failed: ${result.message}`);
    }
  };

  return (
    <div>
      {!isConfigured && <p>Please configure the printer first</p>}
      <button onClick={handlePrint} disabled={isLoading || !isConfigured}>
        {isLoading ? 'Printing...' : 'Print'}
      </button>
      {error && <p>Error: {error}</p>}
    </div>
  );
}

Text-Only Printing with Builder (Hooks API)

import { useEpsonPrinter, usePrinterConfig } from '@plevands/epson-thermal-printer';

function TextReceipt() {
  const { config, isConfigured } = usePrinterConfig({
    initialConfig: { printerIP: '192.168.1.100' },
  });
  const { printWithBuilder, isLoading, error } = useEpsonPrinter(config, { align: 'left' });

  const handlePrintText = async () => {
    const result = await printWithBuilder((builder) => {
      builder.addTextAlign('left');
      builder.addText('TICKET #123\n');
      builder.addText('Producto A x1     10.00\n');
      builder.addText('TOTAL             10.00\n');
      builder.addFeedLine(2);
      builder.addCut('feed');
    });

    if (!result.success) {
      console.error(result.message);
    }
  };

  return (
    <button onClick={handlePrintText} disabled={isLoading || !isConfigured}>
      Imprimir texto
      {error ? ` (${error})` : ''}
    </button>
  );
}

Service API (No React)

import { EposPrintService } from '@plevands/epson-thermal-printer';

const service = new EposPrintService({
  printerIP: '192.168.1.100',
  printerPort: 80,
  deviceId: 'local_printer',
});

// SDK loads automatically from configured path (default: /epos-2.27.0.js)
const result = await service.printCanvas(canvas);

// With HTTPS (e.g., for printers with TLS enabled)
const secureService = new EposPrintService({
  printerIP: '192.168.1.100',
  useHttps: true,  // Uses port 443 by default when true
  deviceId: 'local_printer',
});

Check Printer Connection

You can verify if the printer is online before showing print options. This is useful to conditionally display UI elements or handle offline printers gracefully.

Using Hooks (React):

import { useEpsonPrinter, usePrinterConfig } from '@plevands/epson-thermal-printer';
import { useEffect, useState } from 'react';

function PrinterPanel() {
  const { config, isConfigured } = usePrinterConfig();
  const { checkConnection, print, isLoading, error } = useEpsonPrinter(config);
  const [isOnline, setIsOnline] = useState<boolean | null>(null);

  // Check connection when component mounts or config changes
  useEffect(() => {
    if (!isConfigured) return;
    checkConnection().then(result => {
      setIsOnline(result.success);
    });
  }, [checkConnection, isConfigured]);

  if (!isConfigured) {
    return <span>⚙️ Please configure the printer</span>;
  }

  if (isOnline === null) {
    return <span>Checking printer connection...</span>;
  }

  if (!isOnline) {
    return <span>⚠️ Printer offline: {error}</span>;
  }

  return (
    <div>
      <span>✅ Printer connected</span>
      <button onClick={() => print(canvas)} disabled={isLoading}>
        Print
      </button>
    </div>
  );
}

Using Service API (No React):

import { EposPrintService } from '@plevands/epson-thermal-printer';

const service = new EposPrintService({
  printerIP: '192.168.1.100',
  printerPort: 80,
});

// Check connection without printing anything
const result = await service.checkConnection();

if (result.success) {
  console.log('Printer is online and ready!');
} else {
  console.log('Printer offline:', result.message);
  // result.message includes helpful details like:
  // - "Printer offline"
  // - "Cover open"  
  // - "Out of paper"
  // - "Paper running low"
}

| Method | Prints? | Use Case | |--------|---------|----------| | checkConnection() | ❌ No | Verify printer is online | | testConnection() | ✅ Yes | Print a small test receipt |

With PDF Processing

import { 
  useEpsonPrinter, 
  usePdfProcessor,
  usePrinterConfig 
} from '@plevands/epson-thermal-printer';

function PdfPrinter() {
  const { config, isConfigured } = usePrinterConfig();
  const { processFile } = usePdfProcessor({
    enabled: true,
    trimMargins: { top: 10, bottom: 10, left: 5, right: 5 },
    targetWidth: 576, // 80mm paper
    monochromeThreshold: 160,
  });
  const { printPages } = useEpsonPrinter(config);

  const handlePrint = async (file: File) => {
    // Process PDF with margin trimming and scaling
    const pages = await processFile(file);
    
    // Print all processed pages
    const result = await printPages(
      pages.map(p => p.canvas),
      { pageSelection: 'all' }
    );
  };

  return <div>{/* Your UI */}</div>;
}

Configuration

PDF Processing Options

interface PdfProcessingConfig {
  enabled: boolean;              // Enable/disable processing
  trimMargins?: {
    top?: number;                // Default: 8px
    bottom?: number;             // Default: 8px
    left?: number;               // Default: 8px
    right?: number;              // Default: 8px
  };
  targetWidth?: number;          // Default: 576 (80mm paper)
  scale?: number;                // Render scale, default: 3
  monochromeThreshold?: number;  // 0-255, default: 160
}

Paper Width Reference

| Paper Size | Width (pixels) | targetWidth value | |------------|----------------|---------------------| | 80mm | 576px | 576 (default) | | 58mm | 384px | 384 |

Print Options

interface PrintOptions {
  halftone?: 0 | 1 | 2;  // 0=DITHER, 1=ERROR_DIFFUSION, 2=THRESHOLD
  brightness?: number;    // 0.1 to 10.0, default 1.0
  mode?: 'mono' | 'gray16';
  cut?: boolean;
  align?: 'left' | 'center' | 'right';
}

Printer Configuration

interface EpsonPrinterConfig {
  printerIP: string;     // Required
  printerPort?: number;  // Default: 80 (or 443 if useHttps is true)
  deviceId?: string;     // Default: 'local_printer'
  timeout?: number;      // Default: 60000ms
  useHttps?: boolean;    // Use HTTPS instead of HTTP (default: false)
}

API Reference

Hooks

useEpsonPrinter(config, options?)

Main hook for printer operations with automatic SDK loading.

Parameters:

  • config - EpsonPrinterConfig | null — printer configuration (pass null or unconfigured hook value; operations will return NOT_CONFIGURED error)
  • options? - PrintOptions — default print options

Returns:

  • print(canvas) - Print a single canvas
  • printPages(canvases, options?) - Print multiple pages
  • printWithBuilder(builder => ...) - Print custom ePOSBuilder commands (ideal for text receipts)
  • checkConnection() - Check printer connection without printing
  • testConnection() - Test printer connection
  • isLoading - Loading state
  • error - Error message if any
  • sdkStatus - SDK loading status

usePrinterConfig(options?)

Manages printer configuration with localStorage persistence.

Without arguments, config starts as null until the user calls updateConfig. Pass initialConfig to provide defaults for new users. Pass storageKey to use a custom localStorage key — useful when managing multiple printer configurations (e.g. one per network).

Options (UsePrinterConfigOptions): | Option | Type | Default | Description | |--------|------|---------|-------------| | initialConfig | EpsonPrinterConfig | undefined | Defaults for new users. localStorage values take priority for returning users. | | storageKey | string | 'epson-printer-config' | localStorage key for this configuration instance. |

// No defaults — config is null until user configures
const { config, isConfigured } = usePrinterConfig();

// With defaults — config starts pre-filled
const { config, isConfigured } = usePrinterConfig({
  initialConfig: { printerIP: '10.0.0.50' },
});

// Multiple configs for different networks
const office    = usePrinterConfig({ storageKey: 'printer-office' });
const warehouse = usePrinterConfig({ storageKey: 'printer-warehouse' });

Returns:

  • config - Current configuration (EpsonPrinterConfig | null)
  • updateConfig(partial) - Update configuration (persists to localStorage)
  • resetConfig() - Reset to initial value (initialConfig if provided, otherwise null) and clear localStorage
  • isConfigured - true when config is not null and has a valid printer IP

usePdfProcessor(config?)

Process PDF files with configurable options.

Returns:

  • processFile(file) - Process PDF file
  • isProcessing - Processing state
  • error - Error message if any

Services

EposPrintService

Core service class for printing operations.

const service = new EposPrintService(config, options);

// Methods
await service.printCanvas(canvas);
await service.printWithBuilder((builder) => {
  builder.addTextAlign('center');
  builder.addText('Hello World!\n');
  builder.addFeedLine(3);
  builder.addCut('feed');
});
await service.printPages(canvases, { header: 'Header Text' });
await service.testConnection();  // Prints a test receipt
await service.printTestPage();   // Prints a detailed test page

SDK Loader Functions

import { 
  loadEpsonSDK,
  isEpsonSDKLoaded,
  initializeEpsonSDK,
  getEpsonSDK,
  checkEpsonSDKStatus,
} from '@plevands/epson-thermal-printer';

// Check if loaded
const loaded = isEpsonSDKLoaded();

// Check detailed SDK status
const status = checkEpsonSDKStatus();
// Returns: { loaded: boolean, loading: boolean, error: string | null, classes: string[] }

// Get SDK instance (after loading)
const sdk = getEpsonSDK();

// Manual initialization (optional)
const result = await initializeEpsonSDK();

// Note: SDK loads automatically on first print - no manual call needed!

PDF Processing Functions

import {
  configurePdfWorker,
  isPdfWorkerConfigured,
  PDFJS_CDN_WORKER_URL,
  processPdfFile,
  processPdfPage,
} from '@plevands/epson-thermal-printer';

// Configure PDF.js worker (optional but recommended)
configurePdfWorker(PDFJS_CDN_WORKER_URL);

// Check if worker is configured
const configured = isPdfWorkerConfigured();

// Process a PDF file
const pages = await processPdfFile(file, {
  targetWidth: 576,
  trimMargins: { top: 10, bottom: 10 },
});

Logging Configuration

By default, only errors are logged to the console. You can enable debug logs or intercept all logs with a custom handler:

import { configureLogger } from '@plevands/epson-thermal-printer';

// Enable all logs (debug, warn, error) in console
configureLogger({ enabled: true });

// Intercept all logs with custom handler
configureLogger({
  enabled: false, // Don't show debug/warn in console (errors always shown)
  onLog: (entry) => {
    // entry: { level: 'debug' | 'warn' | 'error', message: string, args?: unknown[] }
    myLoggingService.log(entry.level, entry.message, entry.args);
  },
});

// Combine both: show in console AND send to custom handler
configureLogger({
  enabled: true,
  onLog: (entry) => sendToAnalytics(entry),
});

Running the Demo App

This repository includes a demo application to test the library:

# Clone the repository
git clone https://github.com/plevands/epson-printer.git
cd epson-printer

# Install dependencies
npm install

# Start the development server
npm run dev

# Open in browser: http://localhost:5123

The demo app demonstrates:

  • 🖨️ Printer configuration
  • 📄 PDF file upload and preview
  • 🎨 Real-time PDF processing visualization
  • ⚙️ Print controls with customizable options

Development Workflow with npm link

In the Library

# Make changes to the library
npm run build        # Build once
# OR
npm run dev:lib      # Watch mode - rebuilds on changes

In Your Project

# Link the library (once)
npm link @plevands/epson-thermal-printer

# Your project will use the local version
# Changes to the library reflect immediately after rebuild

Unlinking

# In your project
npm unlink @plevands/epson-thermal-printer

# In the library
npm unlink

Network Requirements

CORS Configuration

The printer must allow CORS requests from your application domain. Configure your printer's web interface:

  1. Access printer at http://[PRINTER_IP]
  2. Navigate to Network > CORS settings
  3. Add your application origin (e.g., http://localhost:5173)

Firewall

Ensure port 80 (or custom port) is accessible on the printer's IP address.

Technical Notes

SDK Inheritance Pattern

The Epson ePOS SDK uses JavaScript prototypal inheritance where ePOSPrint extends ePOSBuilder via ePOSPrint.prototype = new ePOSBuilder(). This pattern has an important implication:

Problem: When calling builder methods directly on ePOSPrint instance (e.g., printer.addText()), the commands accumulate in a shared prototype message property, not an instance property. When send() is called internally, it creates a new empty ePOSBuilder instead of using the accumulated commands.

Solution: This library handles this by using separate ePOSBuilder instances:

// ✅ Correct pattern (used internally by this library)
const builder = new epson.ePOSBuilder();
builder.addText('Hello');
builder.addCut(builder.CUT_FEED);
const xml = builder.toString();

const printer = new epson.ePOSPrint(printerUrl);
printer.send(xml);  // Pass XML explicitly

If you're extending this library or using the raw SDK, always follow this pattern to avoid empty print requests.

Troubleshooting

SDK Not Loading

The SDK loads automatically on first print. If you see errors:

  1. Check console for loading errors
  2. Verify public/epos-2.27.0.js exists in your build
  3. Try manual initialization:
    import { initializeEpsonSDK } from '@plevands/epson-thermal-printer';
    await initializeEpsonSDK();

Connection Failed

  • Verify printer IP address is correct
  • Check CORS configuration on printer
  • Ensure printer is on same network
  • Test connection:
    const { testConnection } = useEpsonPrinter(config);
    await testConnection();

Print Quality Issues

Adjust print options:

const { print } = useEpsonPrinter(config, {
  halftone: 1,        // Try different values (0, 1, 2)
  brightness: 1.2,    // Increase for lighter prints
  mode: 'mono',       // Or 'gray16' for grayscale
});

PDF Processing Issues

Fine-tune processing config:

const { processFile } = usePdfProcessor({
  enabled: true,
  trimMargins: { top: 0, bottom: 0, left: 0, right: 0 }, // Disable trimming
  monochromeThreshold: 180, // Higher = more white
});

Examples

See the included demo app in this repository for complete examples of all features.

npm run dev    # Start demo app
npm run build  # Build library for production
npm run lint   # Run ESLint

Browser Support

| Browser | Supported | |---------|-----------| | Chrome | ✅ 90+ | | Firefox | ✅ 88+ | | Safari | ✅ 14+ | | Edge | ✅ 90+ |

Note: Requires modern browser with ES2020+ and Canvas API support.

License

MIT © Colegio Plevand's

Contributing

Contributions welcome! Please feel free to submit issues and pull requests.