Skip to content

feat: network printers: --device, --media, --community, --no-confirm; --host walks drivers (0.6.0) - #1

Merged
mannes merged 13 commits into
mainfrom
feat/network-printers
Sep 16, 2026
Merged

mannes merged 13 commits into
mainfrom
feat/network-printers

Conversation

@mannes

@mannes mannes commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

CLI half of plan 17 (thermal-label/brother-ql#7): a network Brother QL shows up in list, print text "hi" --host <ip> prints on the detected roll with no model or media flags, and when auto-detection is impossible the CLI says why and --device / --media take over. Requires @thermal-label/contracts@0.6.2; brother-ql-node 0.6.2 is the first driver that uses the new paths.

What

  • --device <key> → OpenOptions.deviceKey; --media <id|name> resolved through the driver's listMedia(); --community <name> for SNMP-identified printers (applies to --host; the LAN scan uses the driver default); --no-confirm to send without out-of-band print confirmation. All on status, print text, print image.
  • --host without --printer walks the installed drivers in a fixed order and hands the printer to the first that opens it. Every failure declines, whatever its type, so an installed-but-unrelated driver (labelwriter-node's TCP path throws a plain Error without deviceKey) can never take down a Brother print. Only when all decline does the CLI fail, listing each driver's reason; a DeviceIdentificationRequiredError renders the candidate keys and the exact --printer … --device … line to copy (plus --media when status is unavailable too). One open site: selectPrinter returns the opened printer.
  • Discovered network printers are re-opened with { host, port, deviceKey } so identification does not run twice.
  • print no longer swallows getStatus() failures: it stops, unless --media is given, in which case it warns and sends blind (confirm: false). Rendering happens before the printer is opened.
  • list shows network rows (tcp 192.168.1.67:9100) and a Serial column; the no-printers hint explains the SNMP broadcast and --host.
  • Contracts errors are matched by name as well as instanceof, for nested-copy installs.
  • usb is now a direct dependency (the CLI is the USB-opening app; drivers stay usb-free).

Checks

  • ci.yml order from a clean dist against npm (contracts 0.6.2, brother-ql-node 0.6.2, labelwriter-node 0.6.4, labelmanager-node 0.6.0): typecheck, lint, prettier, 91 tests (95.6 % lines), build.
  • Bench, QL-820NWBc with the published driver stack: list 1.2 s with the tcp row; status --host 0.12 s (used to hang); DK-11201 → 271, DK-22251 → 259 + two-colour warning; print text --host cuts on the gap; DK-22251 without --media reports the rejected print with the --media 251 hint, --media 251 prints; all-decline rendering exercised with a wrong community.
  • Version 0.6.0. Docs: network section, flag table, decline sample taken from the real output.

The site already serves a /cli/ landing page — homepage was still
pointing at the source repo on github.com. The docs page is the right
target for the npmjs.com card.
The driver -node packages dropped their direct usb dep (it now lives behind
transport as an optional peer), so the cli no longer receives the usb native
addon transitively. The cli opens USB connections, so it must own the addon
directly. Serial/TCP-only consumers of the driver packages stay unburdened by
the native build; the cli, which drives USB, requires it.
--device forwards OpenOptions.deviceKey, --community OpenOptions.snmpCommunity,
on status / print text / print image. --media resolves against the driver's
listMedia() catalog by exact id or case-insensitive name and is passed to
print() instead of detected media; drivers without a catalog say so.
status renders the driver's details rows (the two-colour caveat lives there)
and shows --media as the media line. Shared print runner in commands/print.ts.
…rinters from list

--host without --printer no longer errors out. selectPrinter walks the
installed drivers in KNOWN_DRIVERS order and calls openPrinter inside one
try/catch; any failure, typed or not, is a decline and the walk moves on,
so a driver that cannot speak to the address (labelwriter-node throws a
plain Error on TCP without deviceKey) never takes down a print on another
driver. Only when every driver declines does the CLI fail, listing
family: message per driver; a DeviceIdentificationRequiredError renders
its candidates and a copy-pasteable --printer/--device invocation
(--media added when the driver says status is unavailable too).
Sequential on purpose: one 9100 socket at a time.

selectPrinter now returns the opened printer; commands stop opening
themselves. Discovered network printers re-open by host/port with the
discovered device key so identify does not run twice. --printer keeps
surfacing that one driver's error verbatim.
Discovered network printers render as host:port from DiscoveredPrinter
host/port (connectionId stays opaque) with a Serial column for every row.
The no-printers hint, shared with selection, now says what the scan is
(SNMP broadcast) and when to pass --host instead.
The pre-print status query used to be swallowed. Now a failure is fatal
unless --media was given (then it is a warning and the job goes out sized
by --media), and the status error rows plus warn/error details rows are
echoed as warnings before printing, so the two-colour caveat on a network
Brother is visible at print time, not only in status.
Sends blind on demand: the automatic confirm:false only fires when the
status query failed and --media is given, which leaves no way out when
status works but the driver's confirmation channel (SNMP page counter)
does not.
instanceof only holds when the CLI and the driver load one
@thermal-label/contracts module; a nested or hoisted second copy
downgraded DeviceIdentificationRequiredError to its bare message and
MediaNotSpecifiedError to the generic failure.
Network printers: --device / --media / --community, --host walks the
installed drivers, network rows in list, status failures surfaced at
print time. Docs and README updated. The contracts ^0.6.2 and
brother-ql-node ^0.6.2 pins follow once both are published.
….2, labelwriter-node >=0.6.4, labelmanager-node >=0.6.0
@codecov

codecov Bot commented Sep 16, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

@mannes
mannes merged commit 99defc0 into main Sep 16, 2026
4 checks passed
@mannes
mannes deleted the feat/network-printers branch September 16, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant