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

enhanced-printer

v1.0.9

Published

Advanced PDF printing library with job tracking, custom page sizes, and tray selection for Node.js and Electron

Readme

Enhanced Printer Library

A powerful Node.js/Electron library for advanced PDF printing with job tracking, custom page sizes, and tray selection. Compatible with Node.js 20+ and Electron 39+.

Features

PDF Printing - Print PDF files with full control
Job ID Tracking - Retrieve Windows print spooler job IDs
Custom Page Sizes - Support for standard and custom paper sizes
Tray Selection - Select specific printer trays/bins
Default Preferences - Automatically uses printer defaults when settings not specified
Job Monitoring - Query job status and manage print queue
Electron Compatible - Works seamlessly with Electron 39+

Installation

npm install enhanced-printer

Requirements

  • Node.js: 20.0.0 or higher
  • Electron: 39.0.0 or higher (optional)
  • OS: Windows (uses PowerShell for job tracking)

Quick Start

const { print, getPrinters } = require('enhanced-printer');

async function printPDF() {
  // Get available printers
  const printers = await getPrinters();
  console.log('Available printers:', printers);
  
  // Print with default settings
  const result = await print({
    printerName: 'Your Printer Name',
    filePath: 'C:\\path\\to\\document.pdf',
    jobName: 'MyJob_001'
  });
  
  console.log('Success:', result.success);
  console.log('Job ID:', result.jobId);
  console.log('Job Name:', result.jobName);
}

printPDF();

Available Methods

| Method | Description | |--------|-------------| | print() | Print a PDF with custom settings | | getPrinters() | Get list of available printers | | getDefaultPrinter() | Get default printer name | | getJobInfo() | Get info of a specific job by custom job name | | getJobs() | Get all print jobs for a printer | | cancelJob() | Cancel a print job by custom job name | | watchJob() | Poll a job until it completes, errors, or times out |

API Reference

print(options: PrintOptions): Promise<PrintResult>

Prints a PDF file with the specified options.

Parameters:

interface PrintOptions {
  printerName: string;     // Required: Name of the printer
  filePath: string;        // Required: Path to PDF file
  
  // Optional settings - defaults to printer preferences if not specified
  pageSize?: string;       // e.g., "A4", "A5", "A6", "Letter", "Legal"
  tray?: string | number;  // Tray name or number
  jobName?: string;        // Custom job name for tracking (auto-generated if not provided)
  copies?: number;         // Number of copies
  orientation?: 'portrait' | 'landscape';
  duplex?: 'simplex' | 'duplex';
  monochrome?: boolean;    // Black & white printing
  pages?: string;          // e.g., "1-3,5" to print specific pages
  subset?: 'odd' | 'even'; // Print only odd or even pages
}

Returns:

interface PrintResult {
  success: boolean;
  jobId?: number;        // Job ID from print spooler (if available)
  jobName: string;       // Custom job name used for tracking
  error?: string;        // Error message if print failed
}

Example:

const result = await print({
  printerName: 'HP LaserJet',
  filePath: './invoice.pdf',
  pageSize: 'A4',
  tray: 2,
  copies: 2,
  jobName: 'Invoice_12345'
});

getPrinters(): Promise<PrinterInfo[]>

Gets a list of available printers.

Returns:

interface PrinterInfo {
  name: string;
  isDefault: boolean;
  status: string;
}

Example:

const printers = await getPrinters();
printers.forEach(p => {
  console.log(`${p.name} - ${p.status} ${p.isDefault ? '(Default)' : ''}`);
});

getDefaultPrinter(): Promise<string | null>

Gets the name of the default printer.

Example:

const defaultPrinter = await getDefaultPrinter();
console.log('Default printer:', defaultPrinter);

getJobInfo(customJobName: string, printerName?: string): Promise<JobInfo | null>

Gets detailed information about a specific print job using the custom job name provided during printing.

Returns:

interface JobInfo {
  jobId: number;
  jobName: string;          // Document name from Windows
  customJobName: string;    // Custom job name provided during print
  printerName: string;
  status: string[];         // List of status flags, e.g. ["PRINTING", "RETAINED"]
  pages: number;
  size?: number;            // Size in bytes
  userName?: string;
  submittedTime?: string;
}

Possible status values: PAUSED, ERROR, DELETING, SPOOLING, PRINTING, OFFLINE, PAPER_OUT, PRINTED, DELETED, BLOCKED_DEVICE_QUEUE, USER_INTERVENTION, RESTART, COMPLETE, RETAINED, RENDERING_LOCALLY

Example:

const jobInfo = await getJobInfo('Invoice_12345');
console.log('Status:', jobInfo.status);   // ["PRINTING", "RETAINED"]
console.log('Pages:', jobInfo.pages);

getJobs(printerName: string): Promise<JobInfo[]>

Gets all print jobs for a specific printer.

Example:

const jobs = await getJobs('HP LaserJet');
jobs.forEach(job => {
  console.log(`Job ${job.jobId} (${job.customJobName}): ${job.status.join(', ')}`);
});

cancelJob(customJobName: string, printerName?: string): Promise<boolean>

Cancels a print job using the custom job name.

Example:

const cancelled = await cancelJob('Invoice_12345');
console.log('Cancelled:', cancelled);

watchJob(customJobName: string, printerName?: string, options?: WatchJobOptions): Promise<WatchJobResult>

Polls a print job at regular intervals until it completes, enters an error state, is aborted, or times out.

Why use this? Windows removes completed jobs from the print queue immediately. Without watchJob, polling getJobInfo after completion returns null, which is indistinguishable from an error. watchJob tracks the last known status and correctly resolves a vanished job as COMPLETED.

Options:

interface WatchJobOptions {
  pollInterval?: number;                       // ms between polls (default: 500)
  timeout?: number;                            // max wait ms — 0 or omit = no timeout (default: 0)
  onStatusChange?: (status: string[]) => void; // called on every status change
  signal?: AbortSignal;                        // AbortController signal for manual stop
}

Returns:

interface WatchJobResult {
  finalStatus: string[];   // e.g. ["COMPLETED"], ["ERROR"], ["ABORTED"]
  completed: boolean;      // true = success, false = error / timed out / aborted
}

Example — basic watch with timeout:

const { finalStatus, completed } = await watchJob('Invoice_12345', undefined, {
  timeout: 30000,           // stop after 30 seconds
  pollInterval: 500,
  onStatusChange: (status) => console.log('Status:', status)
});

console.log('Completed:', completed);      // true
console.log('Final status:', finalStatus); // ["COMPLETED"]

Example — watch indefinitely (no timeout):

// timeout: 0 (default) = never times out, watches until job finishes or errors
const { finalStatus, completed } = await watchJob('Invoice_12345');

Example — manual stop via AbortController:

const controller = new AbortController();

// Start watching (doesn't block — run via Promise if needed)
const watchPromise = watchJob('Invoice_12345', undefined, {
  signal: controller.signal,
  onStatusChange: (status) => console.log('Status:', status)
});

// Stop watching manually (e.g. user cancelled, component unmounted, etc.)
controller.abort();

const { finalStatus } = await watchPromise;
console.log(finalStatus); // ["ABORTED"]

Usage Examples

Using Printer Defaults

When you don't specify optional settings, the library automatically uses the printer's default configuration:

const result = await print({
  printerName: 'My Printer',
  filePath: './document.pdf'
});

Custom Page Size with Default Tray

const result = await print({
  printerName: 'Label Printer',
  filePath: './label.pdf',
  pageSize: 'A6'
  // tray not specified - uses default
});

Multiple Custom Settings

const result = await print({
  printerName: 'My Printer',
  filePath: './document.pdf',
  pageSize: 'Legal',
  tray: 1,
  copies: 3,
  orientation: 'landscape',
  duplex: 'duplex',
  monochrome: true,
  jobName: 'Important-Document'
});

Job Tracking

const result = await print({
  printerName: 'My Printer',
  filePath: './document.pdf',
  jobName: 'MyJob_001'
});

if (result.success) {
  // Get job info using custom job name
  const jobInfo = await getJobInfo('MyJob_001');
  console.log(`Job ${jobInfo.jobId}: ${jobInfo.status.join(', ')}`);
  
  // Get all jobs for the printer
  const allJobs = await getJobs('My Printer');
  console.log(`Total jobs in queue: ${allJobs.length}`);
  
  // Cancel if needed
  // await cancelJob('MyJob_001');
}

Electron Integration

Main Process:

const { ipcMain } = require('electron');
const { print, getPrinters, getJobs } = require('enhanced-printer');

ipcMain.handle('print-pdf', async (event, options) => {
  return await print(options);
});

ipcMain.handle('get-printers', async () => {
  return await getPrinters();
});

ipcMain.handle('get-jobs', async (event, printerName) => {
  return await getJobs(printerName);
});

Renderer Process:

const result = await window.printerAPI.print({
  printerName: 'My Printer',
  filePath: pdfPath,
  jobName: 'MyJob_001'
});

TypeScript Support

This library is written in TypeScript and includes full type definitions.

import { print, PrintOptions, PrintResult, JobInfo } from 'enhanced-printer';

const options: PrintOptions = {
  printerName: 'My Printer',
  filePath: './document.pdf',
  pageSize: 'A4',
  jobName: 'TypedJob_001'
};

const result: PrintResult = await print(options);

How It Works

  1. PDF Printing: Uses pdf-to-printer library which wraps SumatraPDF on Windows
  2. Job ID Retrieval: Queries Windows print spooler using PowerShell commands
  3. Custom Job Names: Maps user-provided job names to system job IDs for easy tracking
  4. Status Decoding: Converts numeric Windows job status bitmask into human-readable status flags
  5. Default Settings: When settings aren't specified, SumatraPDF uses the printer's DEVMODE defaults

Limitations

  • Windows Only: Job ID tracking requires PowerShell (Windows-specific)
  • PDF Files: Designed for PDF printing (for raw data, convert to PDF first)
  • Job ID Timing: Very fast printers may complete jobs before ID can be retrieved

Troubleshooting

Job ID is undefined

This can happen if:

  • The print job completes very quickly
  • The printer isn't accessible
  • PowerShell execution is blocked

The library will still print successfully; only job ID retrieval may fail.

Custom page size not working

Ensure the page size is either:

  1. A standard size name ("A4", "Letter", etc.)
  2. A custom size that's been pre-configured in Windows printer settings

Printer not found

Use getPrinters() to see available printers and verify the exact printer name (case-sensitive).

License

MIT

Contributing

Contributions welcome! Please open an issue or pull request.