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

@trupermax/print-agent

v1.0.0

Published

Librería JavaScript para comunicarse con Print Agent desde aplicaciones web.

Readme

@trupermax/print-agent

Librería JavaScript/TypeScript para comunicarse con el servicio local Print Agent desde aplicaciones web.

Instalación

npm install @trupermax/print-agent

Uso básico

import { PrintAgent, EscPos } from '@trupermax/print-agent'

const agent = new PrintAgent()

const data = new EscPos()
  .init()
  .align('center')
  .bold(true)
  .textLine('Hola Mundo')
  .cut()
  .build()

await agent.printEscPos(data, { useDefaultPrinter: true })

PrintAgent

Constructor

const agent = new PrintAgent(options?)

| Opción | Tipo | Defecto | Descripción | |---|---|---|---| | baseUrl | string | http://127.0.0.1:9876 | URL del servicio Print Agent |

Métodos

status()

Retorna el estado del servicio.

const res = await agent.status()
// { status: 'running', message: 'Print Agent funcionando correctamente' }

printers()

Retorna la lista de impresoras disponibles.

const printers = await agent.printers()
// [{ name: 'EPSON TM-T20', driver: '...', port: '...', is_default: true }]

printPDF(pdfBase64, options?)

Imprime un PDF a partir de un string en Base64.

await agent.printPDF(base64String, {
  printerName: 'HP LaserJet',
  useDefaultPrinter: true,
  copies: 2,
})

printZPL(raw, options?)

Imprime una etiqueta ZPL en una impresora Zebra.

await agent.printZPL('^XA^FO50,50^ADN,36,20^FDHola^FS^XZ', {
  printerName: 'ZDesigner GK420d',
  copies: 1,
})

printEscPos(data, options?)

Imprime bytes ESC/POS en una impresora térmica.

const bytes = new EscPos().init().textLine('Hola').cut().build()

await agent.printEscPos(bytes, {
  printerName: 'EPSON TM-T20',
  useDefaultPrinter: false,
  copies: 1,
})

escpos()

Método de fábrica que retorna una nueva instancia del builder EscPos.

const builder = agent.escpos()
const bytes = builder.init().textLine('Hola').cut().build()

Referencia de comandos EscPos

Todos los métodos retornan this para encadenarse. Llama .build() al final para obtener el Uint8Array.

| Método | Descripción | |---|---| | init() | Inicializa la impresora (resetea configuración) | | align(value) | Alineación: 'left', 'center', 'right' | | bold(enabled) | Negrita: true / false | | underline(enabled) | Subrayado: true / false | | fontSize(size) | Tamaño de fuente: 1 (normal) al 4 (cuádruple) | | text(value) | Agrega texto sin salto de línea | | textLine(value) | Agrega texto con salto de línea | | line(char?, length?) | Línea separadora (defecto: 42 guiones) | | feed(lines?) | Avanza el papel N líneas (defecto: 1) | | row(left, right, width?) | Dos textos en la misma línea: izquierda y derecha | | columns(cells, defs) | Tabla con N columnas de ancho y alineación individual | | qr(data, options?) | Código QR generado por la impresora | | barcode(data, type?, options?) | Código de barras generado por la impresora | | cut(partial?) | Corta el papel: parcial (defecto) o completo | | raw(bytes) | Agrega bytes ESC/POS crudos directamente | | build() | Retorna el Uint8Array final para enviar al endpoint |


Detalle de cada comando

init()

Inicializa la impresora y resetea todos los ajustes. Siempre llámalo primero.

new EscPos().init()

align(value)

.align('left')    // izquierda (defecto)
.align('center')  // centro
.align('right')   // derecha

bold(enabled)

.bold(true)
.bold(false)

underline(enabled)

.underline(true)
.underline(false)

fontSize(size)

.fontSize(1)  // normal
.fontSize(2)  // doble
.fontSize(3)  // triple
.fontSize(4)  // cuádruple

text(value)

Agrega texto sin salto de línea al final.

.text('Subtotal: ').bold(true).text('Q.150.00').bold(false)

textLine(value)

Agrega texto seguido de un salto de línea.

.textLine('Hola Mundo')

line(char?, length?)

.line()           // 42 guiones
.line('=', 42)    // 42 signos igual
.line('*', 20)    // 20 asteriscos

feed(lines?)

.feed()    // avanza 1 línea
.feed(3)   // avanza 3 líneas

row(left, right, width?)

Imprime dos textos en la misma línea rellenando el espacio entre ellos. Útil para pares clave-valor.

.row('Subtotal', 'Q.150.00')       // ancho 42 por defecto
.row('IVA 12%', 'Q.18.00', 42)
.row('TOTAL', 'Q.168.00')

columns(cells, defs)

Imprime N columnas con ancho y alineación individual. Ideal para tablas de productos.

.columns(
  ['Cant.', 'Descripción', 'Precio', 'Total'],
  [
    { width: 6,  align: 'left' },
    { width: 16, align: 'left' },
    { width: 10, align: 'right' },
    { width: 10, align: 'right' },
  ]
)

Cada ColumnDef:

| Campo | Tipo | Defecto | Descripción | |---|---|---|---| | width | number | requerido | Ancho en caracteres | | align | Align | 'left' | Alineación dentro de la columna |

La suma de todos los anchos debe coincidir con el ancho de la impresora (normalmente 42 para papel de 80mm).

qr(data, options?)

Genera un código QR usando el hardware de la impresora.

.qr('https://miempresa.com')

.qr('https://miempresa.com', {
  size: 4,          // tamaño del módulo: 1–8 (defecto: 4)
  errorLevel: 'M',  // corrección de error: 'L', 'M', 'Q', 'H' (defecto: 'M')
})

| errorLevel | Corrección | |---|---| | 'L' | 7% — más compacto | | 'M' | 15% — uso general (defecto) | | 'Q' | 25% — ambientes con suciedad | | 'H' | 30% — máxima corrección |

barcode(data, type?, options?)

Genera un código de barras usando el hardware de la impresora.

.barcode('1234567890128')

.barcode('1234567890128', 'EAN13', {
  height: 60,            // alto en puntos (defecto: 60)
  width: 2,              // ancho de módulo: 1–6 (defecto: 2)
  textPosition: 'below', // posición del texto: 'none', 'above', 'below', 'both' (defecto: 'below')
})

Tipos de código de barras soportados:

| Tipo | Uso típico | |---|---| | 'CODE128' | Uso general, alfanumérico (defecto) | | 'CODE39' | Inventario, industria | | 'CODE93' | Variante compacta de CODE39 | | 'EAN13' | Productos retail (13 dígitos) | | 'EAN8' | Productos pequeños (8 dígitos) | | 'UPC-A' | Retail USA (12 dígitos) | | 'UPC-E' | Versión comprimida de UPC-A | | 'ITF' | Cajas y logística | | 'CODABAR' | Bibliotecas, sangre, courier |

cut(partial?)

.cut()        // corte parcial (defecto)
.cut(false)   // corte completo

raw(bytes)

Agrega bytes ESC/POS crudos. Útil para comandos avanzados no cubiertos por el builder.

.raw([0x1b, 0x21, 0x00])

build()

Retorna el Uint8Array final con todos los bytes acumulados para enviar al endpoint.

const data = new EscPos().init().textLine('Hola').cut().build()

Ejemplo completo — ticket con tabla y QR

import { PrintAgent, EscPos } from '@trupermax/print-agent'

const agent = new PrintAgent()

const items = [
  { code: 'A00310', desc: 'TOR HEX GR5 NC 3/8 X 1',  qty: 2, price: 2.00 },
  { code: 'A03672', desc: 'FAJA A-40 LISA SUPERBELT', qty: 1, price: 37.00 },
]

const colDefs = [
  { width: 6,  align: 'left' },
  { width: 10, align: 'right' },
  { width: 10, align: 'right' },
  { width: 16, align: 'right' },
]

const escpos = new EscPos()
  .init()
  .align('center')
  .bold(true)
  .textLine('MI EMPRESA S.A.')
  .bold(false)
  .textLine('NIT: 123456-7')
  .feed(1)
  .align('left')
  .line('-', 42)
  .columns(['Cant.', 'Precio', 'Desc.%', 'Total'], colDefs)
  .line('-', 42)

items.forEach(item => {
  const total = item.qty * item.price
  escpos
    .textLine(`${item.code} - ${item.desc}`)
    .columns(
      [String(item.qty), `Q.${item.price.toFixed(2)}`, '', `Q.${total.toFixed(2)}`],
      colDefs
    )
    .feed(1)
})

escpos
  .line('-', 42)
  .align('right')
  .bold(true)
  .textLine(`TOTAL: Q.${items.reduce((s, i) => s + i.qty * i.price, 0).toFixed(2)}`)
  .bold(false)
  .feed(1)
  .align('center')
  .qr('https://miempresa.com', { size: 4 })
  .feed(3)
  .cut()

const bytes = escpos.build()

const printers = await agent.printers()
const printer = printers.find(p => p.is_default)?.name ?? ''

await agent.printEscPos(bytes, { printerName: printer })

Types

type Align = 'left' | 'center' | 'right'

type FontSize = 1 | 2 | 3 | 4

type BarcodeType =
  | 'UPC-A' | 'UPC-E' | 'EAN13' | 'EAN8'
  | 'CODE39' | 'ITF' | 'CODABAR' | 'CODE93' | 'CODE128'

interface ColumnDef {
  width: number
  align?: Align
}

interface QROptions {
  size?: number
  errorLevel?: 'L' | 'M' | 'Q' | 'H'
}

interface BarcodeOptions {
  height?: number
  width?: number
  textPosition?: 'none' | 'above' | 'below' | 'both'
}

interface Printer {
  name: string
  driver: string
  port: string
  is_default: boolean
}

interface PrintAgentOptions {
  baseUrl?: string
}

interface PrintPDFOptions {
  printerName?: string
  useDefaultPrinter?: boolean
  copies?: number
}

interface PrintZPLOptions {
  printerName?: string
  useDefaultPrinter?: boolean
  copies?: number
}

interface PrintEscPosOptions {
  printerName?: string
  useDefaultPrinter?: boolean
  copies?: number
}

Desarrollo local y pruebas

# Compilar la librería
npm run build

# Ejecutar la demo manual (requiere Print Agent corriendo en localhost:9876)
node test/manual.mjs

Para probar la impresión física, descomenta la llamada a printEscPos al final de test/manual.mjs.