Skip to content

@thermal-label/contracts

Shared TypeScript types and interfaces for the thermal-label printer driver ecosystem. Types only, zero runtime dependencies — safe to import from Node, the browser, or any bundler.

Install

bash
pnpm add @thermal-label/contracts

What's in the box

This package defines interfaces and types that drivers, transports, and applications agree on. For runtime transport implementations, see @thermal-label/transport.

Interfaces

ExportPurpose
TransportBidirectional byte channel to a printer.
PrinterAdapterHigh-level printer: print(), createPreview(), getStatus(), close().
PrinterDiscoveryEnumerate and open printers for a driver family.
DeviceDescriptorStatic description of a supported model (VID/PID, transports, BLE config).
MediaDescriptorBase media shape (width, height, type, colorCapable). Drivers extend it.
PrinterStatusRuntime status with detectedMedia and structured errors[].
PrintOptionsPer-call print options (copies, density).
PreviewOptions / PreviewResult / PreviewPlanePreview API shapes.
DiscoveredPrinter / OpenOptionsDiscovery payloads.
BluetoothConfigGATT UUIDs and MTU for a BLE-capable device.
TransportType'usb' | 'tcp' | 'webusb' | 'web-bluetooth' | 'web-serial' | 'serial'.

Errors

ExportThrown when
TransportErrorBase class for all transport-layer failures.
TransportTimeoutErrorA read timed out waiting for bytes.
TransportClosedErrorThe transport was closed mid-operation.
DeviceNotFoundErrorNo device matches the requested VID/PID filter.
UnsupportedOperationErrorOperation not supported by this driver/printer/media.
MediaNotSpecifiedErrorprint() / createPreview() called without a known media.

Bitmap re-exports

LabelBitmap and RawImageData are re-exported from @mbtech-nl/bitmap so drivers and consumers need only one import for everything they pass through PrinterAdapter.

Sketch — implementing PrinterAdapter

ts
import type {
  DeviceDescriptor,
  MediaDescriptor,
  PreviewOptions,
  PreviewResult,
  PrinterAdapter,
  PrinterStatus,
  PrintOptions,
  RawImageData,
} from '@thermal-label/contracts';
import { MediaNotSpecifiedError } from '@thermal-label/contracts';

export class MyPrinter implements PrinterAdapter {
  readonly family = 'my-driver';
  readonly model: string;
  readonly device: DeviceDescriptor;
  private lastStatus?: PrinterStatus;

  constructor(device: DeviceDescriptor) {
    this.device = device;
    this.model = device.name;
  }

  get connected(): boolean { return true; }

  async print(image: RawImageData, media?: MediaDescriptor, options?: PrintOptions) {
    const m = media ?? this.lastStatus?.detectedMedia;
    if (!m) throw new MediaNotSpecifiedError();
    // render RGBA → native format, stream to the printer...
  }

  async createPreview(image: RawImageData, options?: PreviewOptions): Promise<PreviewResult> { /* … */ }
  async getStatus(): Promise<PrinterStatus> { /* … */ }
  async close(): Promise<void> { /* … */ }
}

For working implementations, see the existing drivers: brother-ql, labelmanager, labelwriter.

Key design decisions

  • MediaDescriptor.heightMm is optional — undefined = continuous media, a number = fixed length. No magic zero.
  • PrinterStatus has only detectedMedia? — no redundant scalar mediaWidthMm / mediaType. One source of truth.
  • PrinterStatus.errors is PrinterError[] with { code, message } — programmatic branching, not string matching.
  • PrintOptions.density is string — drivers validate internally. 'normal' is universally supported; drivers throw UnsupportedOperationError for values they don't recognise.
  • DeviceDescriptor.vid / pid are optional — required only when transports includes USB or WebUSB. Network-only printers omit them.
  • Two-colour splitting is driver knowledge — the contract says colorCapable: boolean. What "red" means is up to the driver.
  • print() is one label per call — batch = loop. Drivers manage job framing internally.

Compatibility

RuntimeNode ≥ 24, modern browsers (types only — no runtime gate)
Peer dependency@mbtech-nl/bitmap (for LabelBitmap / RawImageData re-exports)
LicenseMIT

Source on GitHub · npm

MIT licensed projects. Not affiliated with printer manufacturers. Sponsor on GitHub