https://github.com/esimkowitz/printers-js
Cross-runtime printer library for Node.js, Deno, and Bun
https://github.com/esimkowitz/printers-js
bun deno napi nodejs printer printing rust-lang typescript
Last synced: 25 days ago
JSON representation
Cross-runtime printer library for Node.js, Deno, and Bun
- Host: GitHub
- URL: https://github.com/esimkowitz/printers-js
- Owner: esimkowitz
- License: mit
- Created: 2025-09-05T16:43:55.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-10-07T19:06:18.000Z (8 months ago)
- Last Synced: 2025-10-07T21:06:43.406Z (8 months ago)
- Topics: bun, deno, napi, nodejs, printer, printing, rust-lang, typescript
- Language: TypeScript
- Homepage: https://www.npmjs.com/@printers/printers
- Size: 5.8 MB
- Stars: 3
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# @printers/printers
[](https://www.npmjs.com/package/@printers/printers)
[](https://github.com/esimkowitz/printers-js/blob/main/LICENSE)
[](https://github.com/esimkowitz/printers-js/actions/workflows/ci.yml)
Cross-runtime printer library for Node.js, Deno, and Bun with native performance and comprehensive printing capabilities.
## Features
- 🔄 **Cross-runtime compatibility** - Node.js, Deno, and Bun support
- 🖨️ **Cross-platform printing** - Windows, macOS, and Linux
- 🦀 **Native performance** - Rust backend with Node-API bindings
- 🔒 **Safe testing** - Simulation mode prevents accidental printing
- 📊 **Real-time monitoring** - Printer state changes and job tracking
- 🔧 **Flexible options** - Simple, CUPS, and raw printing configuration
- ⚡ **Async control** - Choose immediate return or wait for completion
## Platform Support
- **macOS**: x64, arm64
- **Windows**: x64, arm64
- **Linux** (glibc only): x64, arm64
## Installation
### Node.js
```bash
npm install @printers/printers
```
### Deno
> [!NOTE]
> This package exposes a Node-API addon for running the Rust backend natively. To use Node-API addons in Deno, you must enable `nodeModulesDir` in your `deno.json` configuration file and pass the `--allow-ffi` flag when running your program. To learn more, see the [Node and npm compatibility](https://docs.deno.com/runtime/fundamentals/node/#node-api-addons) and [Security and permissions]() documentation.
Add to `deno.json`:
```json
{
"nodeModulesDir": "auto"
}
```
```bash
deno add npm:@printers/printers
```
Run with required permissions:
```bash
deno run --allow-ffi --allow-env your-script.ts
```
### Bun
```bash
bun add @printers/printers
```
## Documentation
📚 **[Complete Documentation](./docs/README.md)** - Comprehensive guides and examples
### Feature Guides
- **[Cross-Runtime Support](./docs/CrossRuntimeSupport.md)** - Node.js, Deno, and Bun compatibility
- **[Printing Options](./docs/PrintingOptions.md)** - Simple, CUPS, and raw printing configuration
- **[Job Tracking](./docs/JobTracking.md)** - Monitor and manage print jobs
- **[Printer State Monitoring](./docs/PrinterStateMonitoring.md)** - Real-time printer state change events
## Quick Start
```typescript
import { getAllPrinters, getPrinterByName } from "@printers/printers";
// List all available printers
const printers = await getAllPrinters();
console.log(
"Available printers:",
printers.map(p => p.name)
);
// Print a document
const printer = await getPrinterByName("My Printer");
if (printer) {
const jobId = await printer.printFile("document.pdf", {
simple: {
copies: 2,
duplex: true,
quality: "high",
},
});
console.log("Print job submitted:", jobId);
}
```
## API Reference
### Core Functions
All core functions are async and return Promises. This enables lazy loading of the native module,
avoiding top-level await issues in CommonJS interop and bundlers.
#### `getAllPrinters(): Promise`
Returns an array of all available system printers.
#### `getPrinterByName(name: string): Promise`
Find a printer by its exact name.
#### `getAllPrinterNames(): Promise`
Returns an array of printer names.
#### `printerExists(name: string): Promise`
Check if a printer exists on the system.
#### `getDefaultPrinter(): Promise`
Get the default system printer.
#### `setNativeModulePath(path: string): void`
Override the path used to load the native N-API binary. Useful when shipping
the library inside a bundler (Electron, pkg, esbuild single-file builds) or in
sandboxed environments where the platform-specific npm package
(`@printers/printers-`) is not present.
```ts
import { setNativeModulePath, getAllPrinters } from "@printers/printers";
// MUST be called before any other @printers/printers API.
setNativeModulePath("/absolute/path/to/printers.darwin-arm64.node");
const printers = await getAllPrinters();
```
The same override is also available via the `PRINTERS_JS_NATIVE_MODULE_PATH`
environment variable, which is convenient for CI, Docker, and deployment
scenarios. An explicit `setNativeModulePath()` call takes precedence over the
environment variable.
Per-platform `.node` binaries are attached as assets to each GitHub release in
addition to being published via the platform npm packages, so they can be
downloaded and bundled directly.
### Printer Class
#### Properties
- `name: string` - Printer display name
- `state?: PrinterState` - Current printer state (`"idle"`, `"printing"`, `"paused"`, `"offline"`, `"unknown"`)
- `isDefault?: boolean` - Whether this is the default printer
- `location?: string` - Physical location description
- `driverName?: string` - Printer driver name
- `stateReasons?: string[]` - Array of state reason strings
#### Methods
- `printFile(filePath: string, options?: PrintJobOptions): Promise` - Print a file and return job ID
- `printBytes(data: Uint8Array, options?: PrintJobOptions): Promise` - Print raw bytes and return job ID
- `exists(): Promise` - Check if the printer exists on the system
- `getActiveJobs(): Promise` - Get currently active/pending jobs
- `getJobHistory(limit?: number): Promise` - Get completed job history
- `getJob(jobId: number): Promise` - Get specific job details
- `getAllJobs(): Promise` - Get all jobs (active and completed)
- `cleanupOldJobs(maxAgeSeconds: number): Promise` - Remove old jobs
### State Monitoring
#### `subscribeToPrinterStateChanges(callback): Promise`
Subscribe to real-time printer state change events.
```typescript
const subscription = await subscribeToPrinterStateChanges(event => {
console.log(`${event.eventType}: ${event.printerName}`);
});
// Later: unsubscribe
await subscription.unsubscribe();
```
#### `getPrinterStateSnapshots(): Promise>`
Get current state of all printers.
#### `startPrinterStateMonitoring(config?): Promise`
Start printer state monitoring with optional configuration.
### Print Options
#### `PrintJobOptions`
```typescript
interface PrintJobOptions {
jobName?: string; // Job name for identification
waitForCompletion?: boolean; // Wait for completion (default: true)
simple?: SimplePrintOptions; // Easy-to-use options
cups?: CUPSOptions; // Full CUPS options
raw?: Record; // Raw key-value options
}
```
#### `SimplePrintOptions`
```typescript
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"
landscape?: boolean;
}
```
## Examples
### Basic Printing
```typescript
const printer = await getPrinterByName("My Printer");
// Simple printing
await printer.printFile("document.pdf", {
simple: { copies: 2, duplex: true },
});
// With job tracking
const jobId = await printer.printFile("document.pdf", {
waitForCompletion: false,
});
const job = await printer.getJob(jobId);
console.log(`Job ${jobId}: ${job?.state}`);
```
### State Monitoring
```typescript
// Subscribe to printer events
const subscription = await subscribeToPrinterStateChanges(event => {
switch (event.eventType) {
case "connected":
console.log(`Printer ${event.printerName} connected`);
break;
case "disconnected":
console.log(`Printer ${event.printerName} disconnected`);
break;
case "state_changed":
console.log(
`${event.printerName}: ${event.oldState} → ${event.newState}`
);
break;
}
});
```
### Custom Page Sizes
```typescript
import { createCustomPageSize } from "@printers/printers";
const photoSize = createCustomPageSize(4, 6, "in"); // "Custom.4x6in"
await printer.printFile("photo.jpg", {
cups: {
media: photoSize,
"print-quality": 5,
},
});
```
## Testing & Safety
### Simulation Mode
Enable simulation mode to test without real printing:
```bash
# Unix/Linux/macOS
PRINTERS_JS_SIMULATE=true node your-script.js
# Windows Command Prompt
set PRINTERS_JS_SIMULATE=true && node your-script.js
# Windows PowerShell
$env:PRINTERS_JS_SIMULATE="true"; node your-script.js
```
Check simulation status:
```typescript
import { isSimulationMode } from "@printers/printers";
console.log("Simulation mode:", isSimulationMode);
```
## Platform Support
| OS | Architecture | Node.js | Deno | Bun |
| ------- | ------------ | ------- | ---- | --- |
| Windows | x64 | ✅ | ✅ | ✅ |
| Windows | ARM64 | ✅ | ✅ | ✅ |
| macOS | x64 | ✅ | ✅ | ✅ |
| macOS | ARM64 | ✅ | ✅ | ✅ |
| Linux | x64 | ✅ | ✅ | ✅ |
| Linux | ARM64 | ✅ | ✅ | ✅ |
## Development
For development setup, build instructions, and contribution guidelines, see [CONTRIBUTING.md](./CONTRIBUTING.md).
## License
MIT License - see [LICENSE](./LICENSE) file for details.