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

@kosadchiy/plugin-esc-pos

v0.2.0

Published

Tauri plugin for ESC/POS receipt printers over USB and TCP.

Readme

Tauri Plugin ESC/POS

ESC/POS printer plugin for Tauri applications.

The plugin supports:

  • USB printing on desktop and Android
  • TCP printing on desktop, Android, and iOS
  • Cash drawer opening over USB or TCP
  • USB printer discovery on desktop and Android
  • Receipt text formatting, barcodes, and QR codes with platform-specific support

Platform Support

| Platform | USB Print | TCP Print | Open Drawer | List Printers | | --- | --- | --- | --- | --- | | Desktop | ✅ | ✅ | ✅ | USB only | | Android | ✅ | ✅ | ✅ | USB only | | iOS | ❌ | ✅ | ✅ | ❌ |

Notes:

  • USB printing is not supported on iOS due to platform limitations.

Demo App

The repository includes a Tauri demo app in examples/tauri-app for testing the plugin against real USB and TCP printers.

It lets you:

  • switch between USB and TCP targets
  • discover USB printers
  • edit receipt markup live
  • send print, printAndOpenDrawer, and openDrawer requests
  • try the bundled retail and kitchen receipt samples

Run it with:

cd examples/tauri-app
npm install
npm run tauri dev

Screenshot:

Demo app UI

Installation

Rust

Add the plugin to your Tauri app:

[dependencies]
tauri-plugin-esc-pos = "0.2.0"

Register it in your Tauri app setup:

fn main() {
    tauri::Builder::default()
        .plugin(tauri_plugin_esc_pos::init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

JavaScript

Install the JavaScript bindings:

npm install @kosadchiy/plugin-esc-pos
import {
  listPrinters,
  openDrawer,
  print,
  printAndOpenDrawer,
} from "@kosadchiy/plugin-esc-pos"

Permissions

The plugin ships with these permissions:

  • esc-pos:allow-print
  • esc-pos:allow-print-and-open-drawer
  • esc-pos:allow-list-printers
  • esc-pos:allow-open-drawer

API Reference

Types

type PrinterTarget =
  | { type: "usb"; printerId: string }
  | { type: "tcp"; address: string; port?: number }

interface PrintRequest {
  target: PrinterTarget
  receipt: string
  paperWidth?: 58 | 80
  encoding?: PrintEncoding
}

type PrintEncoding =
  | "utf8"
  | "pc437"
  | "pc737"
  | "pc850"
  | "pc852"
  | "pc855"
  | "pc857"
  | "pc858"
  | "pc860"
  | "pc861"
  | "pc862"
  | "pc863"
  | "pc865"
  | "pc866"
  | "pc869"
  | "wpc775"
  | "iso8859_2"
  | "iso8859_7"
  | "iso8859_15"
  | "wpc1250"
  | "wpc1251"
  | "wpc1252"
  | "wpc1253"
  | "wpc1254"
  | "wpc1257"

interface OpenDrawerRequest {
  target: PrinterTarget
}

interface PrinterInfo {
  id: string
  connection: "usb"
  manufacturerName?: string
  productName?: string
  vendorId?: string
  productId?: string
}

listPrinters(): Promise<PrinterInfo[]>

Returns detected USB printers.

Behavior:

  • Desktop: scans USB printers via nusb
  • Android: scans USB printers via native Android USB APIs
  • iOS: returns an empty list

Example:

const printers = await listPrinters()

for (const printer of printers) {
  console.log(printer.id, printer.productName)
}

print(request: PrintRequest): Promise<void>

Prints a receipt to the selected target.

Fields:

  • target: printer connection target
  • receipt: receipt markup string
  • paperWidth: optional paper width in millimeters, 58 or 80
  • encoding: optional text encoding/code page, see PrintEncoding

Defaults:

  • If paperWidth is omitted, the plugin uses 58
  • If encoding is omitted, the plugin uses "utf8"

Encoding notes:

  • Many ESC/POS printers do not support UTF-8 text mode.
  • For Russian/Cyrillic receipt text, try "pc866" first, then "pc855" or "wpc1251" depending on the printer's supported code pages.
  • For Western Europe try "pc850", "pc858", "wpc1252", or "iso8859_15".
  • For Central/Eastern Europe try "pc852", "wpc1250", or "iso8859_2".
  • For Greek try "pc737", "pc869", "wpc1253", or "iso8859_7".
  • For Turkish try "pc857" or "wpc1254".
  • For Hebrew try "pc862".
  • For Baltic text try "wpc775" or "wpc1257".
  • The selected encoding must match a code page supported by the printer firmware.

Example:

await print({
  target: { type: "usb", printerId: "1155:22336" },
  paperWidth: 80,
  encoding: "pc866",
  receipt: "[C]<b>Hello</b>\n[L]Coffee[R]3.50",
})

printAndOpenDrawer(request: PrintRequest): Promise<void>

Prints a receipt and opens the cash drawer as part of the same operation.

Use this when the drawer opening should be coupled to the print job.

Example:

await printAndOpenDrawer({
  target: { type: "tcp", address: "192.168.1.50", port: 9100 },
  paperWidth: 80,
  receipt: "[C]Paid\n[R]Total:[R]12.49",
})

openDrawer(request: OpenDrawerRequest): Promise<void>

Opens the cash drawer without printing a receipt.

Example:

await openDrawer({
  target: { type: "tcp", address: "192.168.1.50", port: 9100 },
})

Targets

USB Target

const target: PrinterTarget = { type: "usb", printerId: "1155:22336" }

Notes:

  • printerId is the USB identifier returned by listPrinters()
  • USB is supported on desktop and Android only

TCP Target

const target: PrinterTarget = {
  type: "tcp",
  address: "192.168.1.50",
  port: 9100,
}

Notes:

  • port defaults to 9100
  • TCP is supported on desktop, Android, and iOS

Receipt Format

The receipt field is a plain string with line-based markup.

Each line is printed in order. Use \n to create a new line.

Basic example:

[C]Northline Coffee
[L]Americano[R]3.50
[L]Croissant[R]2.80
[R]Total:[R]6.30

Special elements such as barcodes, QR codes, and images should be placed on their own line.

Alignment Tags

Use these tags at the beginning of a segment:

  • [L] left aligned
  • [C] centered
  • [R] right aligned

Example:

[L]Item[R]Qty[R]Total
[L]Flat White[R]2[R]7.00
[R]Total:[R]7.00

You can combine multiple aligned segments in the same line:

[L]Order:[R]A-1024
[L]Date:[R]2026-04-26 12:40

Universal API

If you want one receipt template that works across desktop, Android, and iOS, treat this subset as the portable API.

Portable commands:

  • print()
  • printAndOpenDrawer()
  • openDrawer()

Portable target:

  • TCP: { type: "tcp", address: string, port?: number }

Portable receipt markup:

  • alignment tags: [L], [C], [R]
  • inline tags: <b>...</b>, <u>...</u>, <font size="big">...</font>
  • QR code: <qrcode>...</qrcode>

Portable text encoding:

  • encoding: "utf8" is the default
  • Common ESC/POS presets include pc437, pc850, pc852, pc858, pc866, wpc1252, and regional DOS/Windows/ISO code pages listed in PrintEncoding

Portable receipt example:

[C]<b>Northline Coffee</b>
[C]<u><font size="big">RECEIPT</font></u>
[L]Order:[R]A-1024
[L]Date:[R]2026-04-26 12:40
[L]<b>Item</b>[R]<b>Qty</b>[R]<b>Total</b>
[L]Flat White[R]2[R]7.00
[L]Brownie[R]1[R]3.50
[R]<b>Total:</b>[R]<b>12.49</b>
[C]<qrcode>https://example.com/order/A-1024</qrcode>

Demo app receipt example:

This is the larger default receipt used in examples/tauri-app/src/App.svelte.

[C]Northline Coffee
[C]23 Makarious III Ave
[C]Limassol 4000
[C]--------------------------------
[C]<u><font size="big">RECEIPT</font></u>
[C]--------------------------------
[L]Order:[R]A-1024
[L]Date:[R]2026-04-26 12:40
[C]--------------------------------
[L]<b>Item</b>[R]<b>Qty</b>[R]<b>Total</b>
[L]Flat White[R]2[R]7.00
[L]Brownie[R]1[R]3.50
[C]--------------------------------
[R]Subtotal:[R]10.50
[R]Tax:[R]1.99
[R]<b>Total:</b>[R]<b>12.49</b>
[C]--------------------------------
[C]Thank you
[L]
[C]<qrcode>https://example.com/order/A-1024</qrcode>
[C]<barcode type="ean13">831254784551</barcode>
[L]
[L]
[L]

Platform Differences

Android:

  • Android still uses the ESCPOS-ThermalPrinter-Android connection helpers for USB discovery and transport.

iOS:

  • Due to iOS platform limitations, printing is available only over TCP.

Error Behavior

Typical validation and runtime errors include:

  • Missing printerId for USB target
  • Missing TCP address for TCP target
  • Invalid target: expected USB target
  • Invalid target: expected TCP target
  • Printer not found
  • Connection failed: ...

Examples

Print to first discovered USB printer

const printers = await listPrinters()

if (!printers.length) {
  throw new Error("No USB printers found")
}

await print({
  target: { type: "usb", printerId: printers[0].id },
  paperWidth: 80,
  receipt: `
[C]<b>Northline Coffee</b>
[L]Americano[R]3.50
[R]Total:[R]3.50
`.trim(),
})

Print over TCP

await print({
  target: { type: "tcp", address: "192.168.1.50", port: 9100 },
  paperWidth: 58,
  receipt: `
[C]KITCHEN TICKET
[L]2x Burger
[L]1x Fries
`.trim(),
})

Open the drawer over TCP

await openDrawer({
  target: { type: "tcp", address: "192.168.1.50" },
})

TODO

  • Add image printing support