Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@printers/printers) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@printers/printers
Cross-runtime printer library for Deno, Bun, and Node.js.
Features
- 🔄 Cross-runtime compatibility - works in Deno, Bun, and Node.js
- 🖨️ Cross-platform printing - Windows, macOS, and Linux
- 🦀 Native performance - Rust backend using the
printerscrate - 🏗️ Multi-architecture support - AMD64 and ARM64 binaries
- 🔒 Safe testing - simulation mode prevents accidental printing
- 📊 Async job tracking - non-blocking print jobs with status monitoring
- 🔍 Rich printer metadata - access all printer properties
- ⚡ Flexible completion control - choose immediate return or wait for job completion
- 🔧 Full CUPS options support - comprehensive printing configuration on Unix systems
- 📄 Structured print options - simple, CUPS, and raw option interfaces
Installation
Node.js
npm install @printers/printers
# or
yarn add @printers/printers
# or
pnpm add @printers/printersDeno
deno add npm:@printers/printersImportant: Deno requires special configuration for N-API modules:
- Add
"nodeModulesDir": "auto"to yourdeno.json:
{
"nodeModulesDir": "auto"
}- Run with the
--allow-ffiand--allow-envflags:
deno run --allow-ffi --allow-env your-script.tsBun
bun add @printers/printersQuick Start
import { getAllPrinters, Printer } from "@printers/printers";
// List all available printers
const printers = getAllPrinters();
console.log(
"Available printers:",
printers.map(p => p.name)
);
// Print a file (returns a Promise with job ID)
const printer = printers[0];
try {
const jobId = await printer.printFile("/path/to/document.pdf", {
simple: { copies: 2, duplex: true },
waitForCompletion: true, // Wait for job completion (default)
});
console.log(`Print job ${jobId} completed!`);
} catch (error) {
console.error("Print failed:", error.message);
}API Reference
Functions
getAllPrinters(): Printer[]
Returns an array of all available system printers.
getAllPrinterNames(): string[]
Returns an array of printer names.
getPrinterByName(name: string): Printer | null
Find a printer by its exact name.
printerExists(name: string): boolean
Check if a printer exists on the system.
getJobStatus(jobId: number): JobStatus | null
Get the status of a print job by ID.
cleanupOldJobs(maxAgeMs: number = 30000): number
Remove old completed/failed jobs and return the count removed. The maxAgeMs parameter is in milliseconds (default: 30000ms = 30 seconds).
shutdown(): void
Shutdown the library and cleanup all background threads. Called automatically on process exit.
Additional Exports
Legacy/Convenience Functions
findPrinter(name: string): Printer | null- Alias forgetPrinterByNamegetDefaultPrinter(): Printer | null- Returns the default system printercreatePrintJob(printerName: string, filePath: string, options?: Record<string, string>): Promise<void>- Create and execute a print job
Constants
isSimulationMode: boolean- Whether simulation mode is activeruntimeInfo: RuntimeInfo- Information about the current runtimePrinterConstructor: PrinterClass- Class with static factory method for creating printer instances
Classes
Printer
Represents a system printer with metadata and printing capabilities.
Properties:
name: string- Printer display namesystemName?: string- System-level printer namedriverName?: string- Printer driver nameuri?: string- Printer URI (if available)portName?: string- Port name (e.g., "USB001", "LPT1:")processor?: string- Print processor (e.g., "winprint")dataType?: string- Default data type (e.g., "RAW")description?: string- Printer descriptionlocation?: string- Physical location descriptionisDefault?: boolean- Whether this is the default printerisShared?: boolean- Whether the printer is shared on networkstate?: PrinterState- Current printer statestateReasons?: string[]- Array of state reason strings
Methods:
exists(): boolean- Check if printer is availabletoString(): string- Get string representation with all fieldsequals(other: Printer): boolean- Compare with another printer by namedispose?(): void- Manually release printer resources (automatic cleanup available)getName(): string- Get the printer nameprintFile(filePath: string, options?: PrintJobOptions): Promise<number>- Print a file and return job IDprintBytes(data: Uint8Array, options?: PrintJobOptions): Promise<number>- Print raw bytes and return job IDgetActiveJobs(): PrinterJob[]- Get currently active/pending jobsgetJobHistory(limit?: number): PrinterJob[]- Get completed job historygetJob(jobId: number): PrinterJob | null- Get specific job detailsgetAllJobs(): PrinterJob[]- Get all jobs (active + history)cleanupOldJobs(maxAgeSeconds: number): number- Remove old jobs
Static Methods (via PrinterConstructor):
PrinterConstructor.fromName(name: string): Printer | null- Create printer instance from name
Print Options
The library supports multiple ways to specify print options, with automatic conversion and precedence handling.
PrintJobOptions Interface
interface PrintJobOptions {
/** Top-level job name (highest precedence) */
jobName?: string;
/** Control whether to wait for job completion (default: true) */
waitForCompletion?: boolean;
/** Raw CUPS-style options (lowest precedence) */
raw?: Record<string, string>;
/** Simple, user-friendly options (medium precedence) */
simple?: SimplePrintOptions;
/** Full CUPS options (high precedence) */
cups?: CUPSOptions;
}SimplePrintOptions
Easy-to-use options that get converted to CUPS format:
interface SimplePrintOptions {
copies?: number;
duplex?: boolean;
paperSize?: "A4" | "Letter" | "Legal" | "A3" | "A5" | "Tabloid";
quality?: "draft" | "normal" | "high";
color?: boolean;
pageRange?: string; // e.g., "1-5,8,10-12"
jobName?: string;
pagesPerSheet?: 1 | 2 | 4 | 6 | 9 | 16;
landscape?: boolean;
}CUPSOptions
Direct CUPS option control for advanced configurations:
interface CUPSOptions {
"job-name"?: string;
"job-priority"?: number;
copies?: number | string;
collate?: boolean;
"media-size"?: string;
"print-quality"?: number;
"fit-to-page"?: boolean;
// ... and many more CUPS options
[key: string]: string | number | boolean | undefined;
}waitForCompletion Parameter
Controls the async behavior of print operations:
true(default): Wait for print job completion with intelligent delaysfalse: Return immediately after job submission
// Wait for completion (default behavior)
const jobId = await printer.printFile("document.pdf", {
simple: { copies: 2 },
waitForCompletion: true,
});
// Quick return - fire and forget
const jobId = await printer.printFile("document.pdf", {
simple: { copies: 2 },
waitForCompletion: false,
});Option Precedence
Options are merged with the following precedence (highest to lowest):
- Top-level
jobName- Always takes precedence - CUPS options - Direct CUPS control
- Simple options - Converted to CUPS format
- Raw options - Base level options
await printer.printFile("document.pdf", {
jobName: "Final Job Name", // Will override everything
raw: { "job-name": "Raw Name", copies: "1" },
simple: { copies: 2 }, // Will override raw copies
cups: { "job-priority": 75 }, // Adds to final options
});
// Result: job-name="Final Job Name", copies="2", job-priority="75"Types and Interfaces
PrinterJob
interface PrinterJob {
id: number;
name: string;
state:
| "pending"
| "paused"
| "processing"
| "cancelled"
| "completed"
| "unknown";
mediaType: string;
createdAt: number; // Unix timestamp
printerName: string;
ageSeconds: number;
processedAt?: number; // Unix timestamp
completedAt?: number; // Unix timestamp
errorMessage?: string;
}JobStatus (Legacy)
interface JobStatus {
id: number;
printer_name: string;
file_path: string;
status: "queued" | "printing" | "completed" | "failed";
error_message?: string;
age_seconds: number;
}PrinterState
type PrinterState = "idle" | "processing" | "stopped" | "unknown";PrintError
enum PrintError {
InvalidParams = 1,
InvalidPrinterName = 2,
InvalidFilePath = 3,
InvalidJson = 4,
InvalidJsonEncoding = 5,
PrinterNotFound = 6,
FileNotFound = 7,
SimulatedFailure = 8,
}RuntimeInfo
interface RuntimeInfo {
name: "deno" | "node" | "bun" | "unknown";
isDeno: boolean;
isNode: boolean;
isBun: boolean;
version: string;
}Runtime Permissions
Deno Permissions
deno run --allow-ffi --allow-env your-script.ts--allow-ffi- Required for loading the N-API native module--allow-env- Required for readingPRINTERS_JS_SIMULATEenvironment variable and runtime detection
Node.js / Bun Permissions
No special permissions required.
Testing & Safety
Simulation Mode
Set PRINTERS_JS_SIMULATE=true to enable simulation mode, which prevents actual
printing while testing all functionality:
Unix/Linux/macOS:
PRINTERS_JS_SIMULATE=true deno run --allow-ffi --allow-env your-script.tsWindows Command Prompt:
set PRINTERS_JS_SIMULATE=true
deno run --allow-ffi --allow-env your-script.tsWindows PowerShell:
$env:PRINTERS_JS_SIMULATE="true"
deno run --allow-ffi --allow-env your-script.tsExamples
Basic Printing
import { getAllPrinters } from "@printers/printers";
const printers = getAllPrinters();
if (printers.length > 0) {
const printer = printers[0];
// Access printer information
console.log(`Using printer: ${printer.name}`);
console.log(`Driver: ${printer.driverName}`);
console.log(`State: ${printer.state}`);
console.log(`Default: ${printer.isDefault}`);
try {
// Simple printing with job ID return
const jobId = await printer.printFile("document.pdf");
console.log(`Print job ${jobId} completed successfully`);
} catch (error) {
console.log("Print failed:", error.message);
}
}Advanced Print Options
import { getAllPrinters } from "@printers/printers";
const printer = getAllPrinters()[0];
// Using simple options
const jobId1 = await printer.printFile("document.pdf", {
simple: {
copies: 3,
duplex: true,
paperSize: "A4",
quality: "high",
color: false,
},
waitForCompletion: true, // Wait for completion (default)
});
// Using CUPS options for advanced control
const jobId2 = await printer.printFile("document.pdf", {
cups: {
"job-name": "Important Document",
"job-priority": 75,
"print-quality": 5,
"media-size": "A4",
sides: "two-sided-long-edge",
},
});
// Quick fire-and-forget printing
const jobId3 = await printer.printFile("document.pdf", {
simple: { copies: 1 },
waitForCompletion: false, // Return immediately
});
console.log(`Submitted jobs: ${jobId1}, ${jobId2}, ${jobId3}`);Job Tracking and Management
import { getAllPrinters } from "@printers/printers";
const printer = getAllPrinters()[0];
// Submit a print job
const jobId = await printer.printFile("large-document.pdf", {
simple: { copies: 5, duplex: true },
waitForCompletion: false, // Don't wait, track manually
});
// Check job status
const job = printer.getJob(jobId);
if (job) {
console.log(`Job ${job.id}: ${job.name}`);
console.log(`State: ${job.state}`);
console.log(`Media: ${job.mediaType}`);
console.log(`Age: ${job.ageSeconds}s`);
}
// Monitor active jobs
const activeJobs = printer.getActiveJobs();
console.log(`${activeJobs.length} jobs currently active`);
// View job history
const history = printer.getJobHistory(10); // Last 10 jobs
for (const historicalJob of history) {
console.log(`${historicalJob.name}: ${historicalJob.state}`);
}
// Cleanup old completed jobs
const cleaned = printer.cleanupOldJobs(3600); // Remove jobs older than 1 hour
console.log(`Cleaned up ${cleaned} old jobs`);Printer Information & Management
import {
cleanupOldJobs,
getAllPrinterNames,
getAllPrinters,
getPrinterByName,
printerExists,
} from "@printers/printers";
// List all printers with detailed information
const printers = getAllPrinters();
for (const printer of printers) {
console.log(`\n${printer.name}:`);
console.log(` Driver: ${printer.driverName}`);
console.log(` State: ${printer.state}`);
console.log(` Port: ${printer.portName}`);
console.log(` Default: ${printer.isDefault ? "Yes" : "No"}`);
console.log(` Shared: ${printer.isShared ? "Yes" : "No"}`);
if (printer.location) {
console.log(` Location: ${printer.location}`);
}
if (printer.stateReasons.length > 0 && printer.stateReasons[0] !== "none") {
console.log(` Issues: ${printer.stateReasons.join(", ")}`);
}
}
// Check if specific printer exists
if (printerExists("My Printer")) {
const printer = getPrinterByName("My Printer");
console.log("Found printer:", printer?.name);
}
// Clean up old print jobs (older than 1 hour)
const cleaned = cleanupOldJobs(3600000); // 3600000ms = 1 hour
console.log(`Cleaned up ${cleaned} old print jobs`);Working with Printer Properties
import { getAllPrinters } from "@printers/printers";
const printers = getAllPrinters();
// Find default printer
const defaultPrinter = printers.find(p => p.isDefault);
console.log(`Default printer: ${defaultPrinter?.name || "None"}`);
// Find printers by state
const readyPrinters = printers.filter(
p => p.state === "idle" || p.state === "processing"
);
console.log(`Ready printers: ${readyPrinters.map(p => p.name).join(", ")}`);
// Find network printers
const networkPrinters = printers.filter(p => p.isShared);
console.log(`Network printers: ${networkPrinters.map(p => p.name).join(", ")}`);Platform Support
| OS | Architecture | Deno | Bun | Node.js |
|---|---|---|---|---|
| Windows | x64 | ✅ | ✅ | ✅ |
| Windows | ARM64 | ❌ | ❌ | ✅ |
| macOS | x64 | ✅ | ✅ | ✅ |
| macOS | ARM64 | ✅ | ✅ | ✅ |
| Linux | x64 | ✅ | ✅ | ✅ |
| Linux | ARM64 | ✅ | ✅ | ✅ |
Development & Contributing
For technical information about architecture, build systems, development workflow, and contribution guidelines, see CONTRIBUTING.md.
License
MIT License - see LICENSE file for details.