@bobfrankston/brother-label 1.1.16 → 1.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli.js CHANGED
@@ -8,7 +8,7 @@ import * as os from "os";
8
8
  import * as path from "path";
9
9
  import * as dns from "dns/promises";
10
10
  import { preprocessSingleQuotes, parseArgs, } from "@bobfrankston/label-core";
11
- import { print, render, renderSegments, printSegments, getConfig, setConfig, getConfigPath, listPrinters, resolvePrinter, detectTape, brotherPrinter, } from "./api.js";
11
+ import { print, render, renderSegments, printSegments, getConfig, setConfig, getConfigPath, listPrinters, resolvePrinter, getDefaultPrinter, detectTape, brotherPrinter, } from "./api.js";
12
12
  const VERSION = "1.1.0";
13
13
  const VALID_TAPES = [6, 9, 12, 18, 24];
14
14
  function parseTape(value) {
@@ -29,6 +29,7 @@ const VALUED = [
29
29
  { names: ["-interval"], key: "interval" },
30
30
  { names: ["-ql"], key: "ql" },
31
31
  { names: ["-ql-media"], key: "qlMedia" },
32
+ { names: ["-port"], key: "port" },
32
33
  ];
33
34
  const BOOLEAN = [
34
35
  { names: ["-w", "-html"], key: "html" },
@@ -38,6 +39,8 @@ const BOOLEAN = [
38
39
  { names: ["-no-wait", "-nowait"], key: "nowait" },
39
40
  { names: ["-mdns"], key: "mdns" },
40
41
  { names: ["-vb", "-verbose"], key: "verbose" },
42
+ { names: ["-queue"], key: "queue" },
43
+ { names: ["-no-cut", "-nocut"], key: "nocut" },
41
44
  { names: ["-help", "-h", "-?"], key: "help" },
42
45
  { names: ["-version", "-v"], key: "version" },
43
46
  ];
@@ -81,6 +84,11 @@ Options:
81
84
  (bypasses Windows queue; e.g. -ql ql720 or -ql 1.2.3.4)
82
85
  -ql-media <id> QL media id (e.g. 271=DK-11201 29×90mm, 259=DK-22205 62mm)
83
86
  Required when the printer doesn't respond to status
87
+ -queue Print through the Windows spooler (XPS) instead of
88
+ writing raster bytes straight to the printer's port
89
+ -port <COMn> Serial/Bluetooth port for direct printing (overrides
90
+ the port looked up from the printer queue)
91
+ -no-cut Do not cut the tape after the label (direct path only)
84
92
  -vb, -verbose Print extra QL diagnostic messages (status, media source)
85
93
  -help Show this help
86
94
  -version Show version`);
@@ -482,6 +490,18 @@ async function cmdPrinterInfo(printerName, qlHost) {
482
490
  catch (e) {
483
491
  console.log(`Status: error: ${e.message}`);
484
492
  }
493
+ if (!qlHost) {
494
+ const { resolvePtModel } = await import("./ptdirect.js");
495
+ const model = resolvePtModel(printerName);
496
+ const direct = await resolvePtPort(printerName);
497
+ if (model && direct) {
498
+ console.log(`Direct: ${direct.port} via ${direct.source}`);
499
+ console.log(` profile ${model.name}${model.verified ? "" : " — geometry not from this model's own manual"}`);
500
+ }
501
+ else {
502
+ console.log(`Direct: unavailable (${!model ? "no raster profile for this model" : "no serial port found"}) — prints via the spooler`);
503
+ }
504
+ }
485
505
  if (qlHost) {
486
506
  console.log(`QL host: ${qlHost} (TCP/9100)`);
487
507
  const { detectQLMediaFromWindows } = await import("./ql.js");
@@ -577,6 +597,7 @@ async function cmdPrint(opts, segments, inputs) {
577
597
  textHeight: opts.height,
578
598
  space: opts.space,
579
599
  };
600
+ let segDirectPort;
580
601
  if (opts.output) {
581
602
  const buffer = await renderSegments(segments, tape, opts.height, opts.space);
582
603
  fs.writeFileSync(opts.output, buffer);
@@ -586,11 +607,14 @@ async function cmdPrint(opts, segments, inputs) {
586
607
  const buffer = await renderSegments(segments, tape, opts.height, opts.space);
587
608
  const { printPngToQL } = await import("./ql.js");
588
609
  await printPngToQL(qlHost, buffer, qlMediaId, opts.printer, !!opts.verbose);
589
- outln(`Printed ${segments.length} segment(s) to QL @ ${qlHost}`);
610
+ outln(`Printed ${segments.length} segment(s) on ${opts.printer || "QL"} @ ${qlHost}, ${tape}mm (direct TCP/9100)`);
611
+ }
612
+ else if (segDirectPort = await tryPrintDirect(await renderSegments(segments, tape, opts.height, opts.space), opts, tape)) {
613
+ reportPrinted(`${segments.length} segment(s) `, opts, tape, segDirectPort);
590
614
  }
591
615
  else {
592
616
  await printSegments(segments, segOpts);
593
- outln(`Printed ${segments.length} segment(s) on ${tape}mm tape`);
617
+ reportPrinted(`${segments.length} segment(s) `, opts, tape, null);
594
618
  }
595
619
  return;
596
620
  }
@@ -625,11 +649,229 @@ async function cmdPrint(opts, segments, inputs) {
625
649
  const buffer = await render(printOpts);
626
650
  const { printPngToQL } = await import("./ql.js");
627
651
  await printPngToQL(qlHost, buffer, qlMediaId, opts.printer, !!opts.verbose);
628
- outln(`Printed to QL @ ${qlHost}`);
652
+ outln(`Printed on ${opts.printer || "QL"} @ ${qlHost} (direct TCP/9100)`);
653
+ return;
654
+ }
655
+ const directPort = await tryPrintDirect(await render(printOpts), opts, tape);
656
+ if (directPort) {
657
+ reportPrinted("", opts, tape, directPort);
629
658
  return;
630
659
  }
631
660
  await print(printOpts);
632
- outln(`Printed on ${tape}mm tape`);
661
+ reportPrinted("", opts, tape, null);
662
+ }
663
+ /**
664
+ * Name the printer, the tape and the route a label actually took.
665
+ *
666
+ * "Printed on 24mm tape" is not something the user can check: it does not say
667
+ * which of four Brother printers took it, and it reads identically whether the
668
+ * bytes reached the printer or merely reached the Windows queue -- which is
669
+ * where labels disappear. Naming the target and the route makes the line
670
+ * verifiable, and still means something when read back in a log later.
671
+ */
672
+ function describeTarget(opts, tape, port) {
673
+ const printer = opts.printer || getDefaultPrinter();
674
+ return port
675
+ ? `${printer}, ${tape}mm tape (direct to ${port})`
676
+ : `${printer}, ${tape}mm tape`;
677
+ }
678
+ /**
679
+ * The verb has to be honest about what happened. A direct write reached the
680
+ * printer, so "Printed" is a claim we can stand behind. Handing a job to the
681
+ * Windows spooler is not printing -- the job can sit Retained in Error behind
682
+ * another dead job and never reach the tape, which is exactly how labels have
683
+ * been going missing. Say "Queued" for that, and name the printer either way.
684
+ */
685
+ function reportPrinted(what, opts, tape, port) {
686
+ const verb = port ? "Printed" : "Queued";
687
+ const tail = port ? "" : " -- the spooler has it; check the queue if nothing comes out";
688
+ outln(`${verb} ${what}on ${describeTarget(opts, tape, port)}${tail}`);
689
+ }
690
+ /**
691
+ * Write the rendered label straight to the printer's port, skipping the
692
+ * Windows spooler. Returns false when this printer has no direct path, so the
693
+ * caller can fall back to the XPS/queue route.
694
+ *
695
+ * The direct route is the default because the queue is where labels go to die:
696
+ * a job that fails is left Retained and blocks every later job until someone
697
+ * clears it by hand, and `WorkOffline` discards jobs without a word. Writing
698
+ * the bytes ourselves either succeeds or throws — there is no third state that
699
+ * looks like success and prints nothing. `-queue` opts back in.
700
+ */
701
+ async function tryPrintDirect(png, opts, tape) {
702
+ if (opts.queue) {
703
+ /* A queue can be pointed at a discard port so the spooler stops
704
+ * fighting us for the printer's serial port. Printing to it would
705
+ * report success and put nothing on the tape, which is the one
706
+ * outcome this whole module exists to prevent. */
707
+ await refuseDiscardQueue(opts.printer);
708
+ return null;
709
+ }
710
+ /* Fall back to the same default the spooler path uses, so omitting -p does
711
+ * not silently drop the label into the queue. */
712
+ const printerName = opts.printer || getDefaultPrinter();
713
+ if (!printerName)
714
+ return null;
715
+ const { resolvePtModel, printPtDirect } = await import("./ptdirect.js");
716
+ if (!resolvePtModel(printerName))
717
+ return null;
718
+ const port = opts.port || (await resolvePtPort(printerName))?.port;
719
+ if (!port)
720
+ return null;
721
+ const jobsBefore = await listJobIds(printerName);
722
+ try {
723
+ await printPtDirect(png, {
724
+ port,
725
+ printerName,
726
+ tape,
727
+ autoCut: !opts.nocut,
728
+ log: opts.verbose ? (m) => outln(m) : undefined,
729
+ });
730
+ }
731
+ finally {
732
+ /* Clear it even when the write failed -- a failed open still leaves the
733
+ * phantom behind, and that is precisely when a wedged queue is most
734
+ * confusing to look at. */
735
+ await clearPhantomJobs(printerName, jobsBefore);
736
+ }
737
+ return port;
738
+ }
739
+ /** Ports that swallow whatever the spooler sends them. */
740
+ const DISCARD_PORTS = /^(nul|null|nul:|null:)$/i;
741
+ /**
742
+ * List the spooler's current job ids for a printer. Best-effort: a failure
743
+ * here must never stop a label printing.
744
+ */
745
+ async function listJobIds(printerName) {
746
+ try {
747
+ const { runScriptOrThrow } = await import("@bobfrankston/label-core");
748
+ const out = await runScriptOrThrow(`@(Get-PrintJob -PrinterName '${printerName.replace(/'/g, "''")}' -ErrorAction SilentlyContinue).Id -join ','`);
749
+ return new Set(out.trim().split(",").map(Number).filter(n => !isNaN(n)));
750
+ }
751
+ catch {
752
+ return new Set();
753
+ }
754
+ }
755
+ /**
756
+ * Remove the empty job Windows invents when we open the printer's port.
757
+ *
758
+ * Writing directly to a serial port that a print queue is bound to makes the
759
+ * spooler materialise a zero-byte job -- proven with a script that only opens
760
+ * the port and writes an initialise sequence. That job then parks itself in
761
+ * Error and drags the queue down with it, which is what made the queue look
762
+ * broken after every successful direct print.
763
+ *
764
+ * The queue has to stay bound to the port: that binding is what establishes
765
+ * and holds the Bluetooth RFCOMM link. Open the port with the queue pointed
766
+ * elsewhere and the link will not come up at all. So the phantom cannot be
767
+ * prevented, only cleared.
768
+ *
769
+ * Scoped by identity, not by size: only jobs that did not exist before we
770
+ * opened the port are removed. Size is no use as a filter -- the spooler
771
+ * records a copy of the bytes we put on the wire, so these jobs are not empty
772
+ * (1205 and 4373 bytes were observed for two ordinary labels).
773
+ *
774
+ * The residual risk is a real job submitted by another program during the
775
+ * second or so a direct print takes. That window is narrow and the alternative
776
+ * -- leaving the queue permanently in Error after every label -- is worse.
777
+ */
778
+ async function clearPhantomJobs(printerName, before) {
779
+ try {
780
+ const { runScriptOrThrow } = await import("@bobfrankston/label-core");
781
+ const name = printerName.replace(/'/g, "''");
782
+ const skip = [...before].join(",") || "-1";
783
+ /* The spooler creates the job around the time the handle closes, so
784
+ * give it a moment to appear before looking, and a moment to act on
785
+ * the delete before returning -- a job caught mid-print lingers in
786
+ * "Deleting" otherwise. */
787
+ await runScriptOrThrow(`
788
+ $ErrorActionPreference = 'SilentlyContinue'
789
+ $before = @(${skip})
790
+ Start-Sleep -Milliseconds 900
791
+ Get-PrintJob -PrinterName '${name}' | Where-Object { $_.Id -notin $before } |
792
+ ForEach-Object { Remove-PrintJob -PrinterName '${name}' -ID $_.Id }
793
+ Start-Sleep -Milliseconds 600
794
+ `);
795
+ }
796
+ catch { /* cosmetic cleanup; never fail a print over it */ }
797
+ }
798
+ /**
799
+ * Refuse `-queue` when the printer's Windows queue points at a discard port.
800
+ *
801
+ * Repointing a queue away from the printer's real port is how we stop the
802
+ * spooler from creating a phantom job every time we open that port. The cost
803
+ * is that the queue no longer goes anywhere, so `-queue` must fail loudly
804
+ * rather than cheerfully reporting a label that was never printed.
805
+ */
806
+ async function refuseDiscardQueue(printerName) {
807
+ const name = printerName || getDefaultPrinter();
808
+ if (!name)
809
+ return;
810
+ const { listPrinters: coreListPrinters } = await import("@bobfrankston/label-core");
811
+ const info = (await coreListPrinters(/brother|^pt-|^ql-/i)).find(p => p.name === name);
812
+ const portName = (info?.portName ?? "").replace(/:$/, "");
813
+ if (!DISCARD_PORTS.test(portName))
814
+ return;
815
+ throw new UserError(`${name}'s Windows queue points at "${info.portName}", which discards everything sent to it — ` +
816
+ `-queue would report success and print nothing. Drop -queue to print directly, ` +
817
+ `or repoint the queue at the printer's port with: Set-Printer -Name "${name}" -PortName "COMn:"`);
818
+ }
819
+ /**
820
+ * Find the serial port to write a P-touch label to.
821
+ *
822
+ * The printer queue's PortName is the obvious source but it goes stale:
823
+ * Windows reassigns a Bluetooth printer's outgoing COM number when it
824
+ * re-pairs (the PT-D610BT here was installed on COM8 and came back on COM10),
825
+ * and the queue keeps pointing at the old one. Worse, the abandoned number is
826
+ * often still a valid *incoming* Bluetooth port with nothing behind it, so the
827
+ * stale queue looks openable and simply swallows the job.
828
+ *
829
+ * So: ask Bluetooth which port actually belongs to this printer, and fall back
830
+ * to the queue's port only when no Bluetooth match exists (a genuinely wired
831
+ * serial printer). Returns null when neither yields a COM port.
832
+ */
833
+ async function resolvePtPort(printerName) {
834
+ const { listPrinters: coreListPrinters, runScriptOrThrow } = await import("@bobfrankston/label-core");
835
+ /* Bluetooth SPP ports carry the remote device's address in their instance
836
+ * id; BTHPORT maps that address to the advertised device name, which
837
+ * contains the model (e.g. "PT-D610BT5465"). Match on the model token. */
838
+ const model = /PT-([A-Z0-9]+)/i.exec(printerName)?.[1];
839
+ if (model) {
840
+ const script = [
841
+ "$ErrorActionPreference = 'SilentlyContinue'",
842
+ "Get-PnpDevice -Class Ports -PresentOnly | Where-Object { $_.FriendlyName -match 'Bluetooth' } | ForEach-Object {",
843
+ " if ($_.InstanceId -match '&0&([0-9A-Fa-f]{12})_') {",
844
+ " $addr = $matches[1].ToLower()",
845
+ " $raw = (Get-ItemProperty \"HKLM:\\SYSTEM\\CurrentControlSet\\Services\\BTHPORT\\Parameters\\Devices\\$addr\").Name",
846
+ " if ($raw -and $_.FriendlyName -match '\\((COM\\d+)\\)') {",
847
+ " $com = $matches[1]",
848
+ " $name = [System.Text.Encoding]::ASCII.GetString($raw).Trim([char]0)",
849
+ " Write-Output \"$com=$name\"",
850
+ " }",
851
+ " }",
852
+ "}",
853
+ ].join("\n");
854
+ try {
855
+ const out = (await runScriptOrThrow(script)).trim();
856
+ for (const line of out.split(/\r?\n/)) {
857
+ const eq = line.indexOf("=");
858
+ if (eq < 0)
859
+ continue;
860
+ const com = line.slice(0, eq).trim();
861
+ const name = line.slice(eq + 1).trim();
862
+ const squashed = name.replace(/[^A-Za-z0-9]/g, "").toUpperCase();
863
+ if (com && squashed.includes(model.toUpperCase())) {
864
+ return { port: com, source: `Bluetooth device ${name}` };
865
+ }
866
+ }
867
+ }
868
+ catch { /* fall through to the queue's port */ }
869
+ }
870
+ const info = (await coreListPrinters(/brother|^pt-/i)).find(p => p.name === printerName);
871
+ const m = /^(COM\d+):?$/i.exec(info?.portName ?? "");
872
+ if (m)
873
+ return { port: m[1], source: `printer queue port ${info.portName}` };
874
+ return null;
633
875
  }
634
876
  function classifyInput(input, opts) {
635
877
  if (opts.text)
package/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * Brother Label Printer CLI\n * Thin wrapper around api.ts using shared CLI primitives from label-core.\n */\n\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport * as dns from \"dns/promises\";\nimport {\n preprocessSingleQuotes,\n parseArgs,\n} from \"@bobfrankston/label-core\";\nimport type {\n PrintOptions as CorePrintOptions,\n PrinterStatus,\n Segment,\n ValuedOptionSpec,\n BooleanFlagSpec,\n} from \"@bobfrankston/label-core\";\nimport {\n print,\n render,\n renderSegments,\n printSegments,\n getConfig,\n setConfig,\n getConfigPath,\n listPrinters,\n resolvePrinter,\n detectTape,\n brotherPrinter,\n} from \"./api.js\";\nimport type { TapeSize, PrintOptions, SegmentOptions } from \"./api.js\";\n\nconst VERSION = \"1.1.0\";\nconst VALID_TAPES: TapeSize[] = [6, 9, 12, 18, 24];\n\nfunction parseTape(value: string): TapeSize {\n const num = parseInt(value.replace(\"mm\", \"\"), 10) as TapeSize;\n if (!VALID_TAPES.includes(num)) {\n throw new UserError(`Invalid tape size: ${value}. Valid: ${VALID_TAPES.join(\", \")}`);\n }\n return num;\n}\n\nconst VALUED: ValuedOptionSpec[] = [\n { names: [\"-tape\"], key: \"tape\" },\n { names: [\"-p\", \"-printer\"], key: \"printer\" },\n { names: [\"-o\", \"-output\"], key: \"output\" },\n { names: [\"-a\", \"-aspect\"], key: \"aspect\" },\n { names: [\"-ht\", \"-height\"], key: \"height\" },\n { names: [\"-s\", \"-space\"], key: \"space\" },\n { names: [\"-timeout\"], key: \"timeout\" },\n { names: [\"-interval\"], key: \"interval\" },\n { names: [\"-ql\"], key: \"ql\" },\n { names: [\"-ql-media\"], key: \"qlMedia\" },\n];\n\nconst BOOLEAN: BooleanFlagSpec[] = [\n { names: [\"-w\", \"-html\"], key: \"html\" },\n { names: [\"-i\", \"-image\"], key: \"image\" },\n { names: [\"-t\"], key: \"text\" },\n { names: [\"-c\", \"-clip\"], key: \"clip\" },\n { names: [\"-no-wait\", \"-nowait\"], key: \"nowait\" },\n { names: [\"-mdns\"], key: \"mdns\" },\n { names: [\"-vb\", \"-verbose\"], key: \"verbose\" },\n { names: [\"-help\", \"-h\", \"-?\"], key: \"help\" },\n { names: [\"-version\", \"-v\"], key: \"version\" },\n];\n\nconst SUBCOMMANDS = [\"list\", \"status\", \"config\"];\n\nfunction showHelp(): void {\n console.log(`Brother Label Printer CLI v${VERSION}\n\nUsage:\n brother-print [options] <text> Print text\n brother-print [options] <file> Print html/txt/image file (auto-detected)\n brother-print -clip [options] Print clipboard contents (image or text)\n brother-print -text <v> -qr <v> ... Print ordered text/qr segments\n brother-print -list [-mdns] List Brother printers and status\n (-mdns also discovers network printers)\n brother-print -status [-p <name>] Show printer status\n brother-print -config Show / set defaults\n\nCommands take a leading dash so they can never be confused with label content:\na bare word is always something to print, a dashed word is always a command.\n\nTape size is auto-detected from the printer. Use -tape to override.\nSingle quotes can wrap arguments: '7\"' 'line1\\\\nline2'\n\nOptions:\n -tape <size> Tape size: 6, 9, 12, 18, 24 (mm) [auto-detected]\n -p, -printer <name> Printer queue name\n -o, -output <file> Save PNG to file instead of printing\n -a, -aspect <r> Aspect ratio width:height for HTML (e.g. 3.5:2)\n -ht, -height <size> Text height: 12mm, .5in, or 50% (of tape height)\n -s, -space <size> Space between segments: 12px, 1mm, .2in\n -t, -text Force input as literal text (-text <v> for segments)\n -qr <data> QR code segment\n -w, -html Force input as HTML file path\n -i, -image Force input as image file path\n -c, -clip Read content from clipboard (image preferred, then text)\n -no-wait Fail immediately if printer is offline (default: wait)\n -timeout <secs> Max wait time when printer is offline\n -interval <secs> Polling interval while waiting (default 2)\n -mdns With -list: also discover network printers via mDNS\n -ql <host> Print to a Brother QL series printer over TCP/9100\n (bypasses Windows queue; e.g. -ql ql720 or -ql 1.2.3.4)\n -ql-media <id> QL media id (e.g. 271=DK-11201 29×90mm, 259=DK-22205 62mm)\n Required when the printer doesn't respond to status\n -vb, -verbose Print extra QL diagnostic messages (status, media source)\n -help Show this help\n -version Show version`);\n}\n\n/** Expected user-facing error: prints one line, no log file, no stack. */\nclass UserError extends Error {\n readonly isUserError = true;\n}\n\n/**\n * Single-line status display: on a TTY the line is rewritten in place\n * (CR + erase-line) instead of scrolling; callers must clear() before any\n * normal output so it doesn't collide with the pending status line.\n */\nconst statusLine = {\n active: false,\n update(msg: string): void {\n if (process.stderr.isTTY) {\n process.stderr.write(`\\r\\x1b[2K${msg}`);\n this.active = true;\n } else {\n console.error(msg);\n }\n },\n clear(): void {\n if (this.active) {\n process.stderr.write(`\\r\\x1b[2K`);\n this.active = false;\n }\n },\n};\n\n/** console.log that first clears any in-place status line. */\nfunction outln(msg: string): void {\n statusLine.clear();\n console.log(msg);\n}\n\nasync function main(): Promise<void> {\n const argv = preprocessSingleQuotes(process.argv.slice(2));\n let parsed;\n try {\n parsed = parseArgs(argv, VALUED, BOOLEAN, SUBCOMMANDS);\n } catch (e: any) {\n console.error(`Error: ${e.message}`);\n process.exit(1);\n }\n\n if (parsed.unknown.length > 0) {\n console.error(`Unknown option(s): ${parsed.unknown.join(\", \")}`);\n console.error(`Run \"brother-print -help\" for usage.`);\n process.exit(1);\n }\n\n /* Bare `list` used to be the command syntax; it is now `-list`. Refusing\n * beats guessing: printing a label that says \"list\" and listing printers\n * are both plausible readings of the same word. */\n if (parsed.ambiguous.length > 0) {\n const w = parsed.ambiguous[0];\n console.error(`Ambiguous argument: \"${w}\" -- commands now take a dash.`);\n console.error(` brother-print -${w} run the ${w} command`);\n console.error(` brother-print -text ${w} print a label that says \"${w}\"`);\n process.exit(1);\n }\n\n if (parsed.opts.help) { showHelp(); return; }\n if (parsed.opts.version) { console.log(VERSION); return; }\n\n try {\n if (typeof parsed.opts.printer === \"string\") {\n parsed.opts.printer = await resolvePrinter(parsed.opts.printer);\n /* Auto-route QL series through the QL TCP path. The XPS / CustomMediaSize\n * pipeline is P-touch-only; sending it to a QL queue produces an XPS\n * error. If the user already passed -ql explicitly, leave it alone. */\n if (!parsed.opts.ql && isQLPrinter(parsed.opts.printer)) {\n const host = await resolveQLHost(parsed.opts.printer);\n if (host) parsed.opts.ql = host;\n }\n }\n switch (parsed.command) {\n case \"list\": await cmdList(parsed.opts); return;\n case \"status\": await cmdStatus(parsed.opts); return;\n case \"config\": await cmdConfig(parsed.opts); return;\n }\n await cmdPrint(parsed.opts, parsed.segments, parsed.inputs);\n } catch (e: any) {\n statusLine.clear();\n /* Timeout/offline are expected conditions, not crashes — one line,\n * no error-report file. */\n if (e?.isUserError || /^Timed out waiting for printer|is offline \\(/.test(e?.message ?? \"\")) {\n console.error(`Error: ${e.message}`);\n process.exit(1);\n }\n reportError(e);\n process.exit(1);\n }\n}\n\nfunction isQLPrinter(name: string): boolean {\n return /\\bQL-/i.test(name);\n}\n\n/**\n * Look up the TCP host for a QL printer's installed Windows queue. Pulls the\n * port name via label-core, then asks PowerShell for that port's\n * PrinterHostAddress. Returns undefined if the port isn't a TCP/IP port (e.g.\n * the QL-820NWB's BRWxxxx Bluetooth port has no host address).\n */\nasync function resolveQLHost(printerName: string): Promise<string | undefined> {\n const { listPrinters: coreListPrinters, runScriptOrThrow } =\n await import(\"@bobfrankston/label-core\");\n const all = await coreListPrinters(/brother|^pt-|^ql-/i);\n const info = all.find(p => p.name === printerName);\n if (!info?.portName) return undefined;\n const port = info.portName.replace(/'/g, \"''\");\n const script = `\n$ErrorActionPreference = 'SilentlyContinue'\n$p = Get-PrinterPort -Name '${port}'\nif ($p -and $p.PrinterHostAddress) { Write-Output $p.PrinterHostAddress }\n`;\n try {\n const out = (await runScriptOrThrow(script)).trim();\n if (!out) return undefined;\n return await resolvableHost(out);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Brother's installer often writes a bare NetBIOS-style hostname (BRWxxxx)\n * as the port's PrinterHostAddress, which won't resolve in environments where\n * the DNS suffix isn't auto-appended. Resolution tiers, in order:\n * 1. as-is via the OS resolver\n * 2. <host>.<suffix> for every DNS suffix the OS knows about (global search\n * list, per-connection suffix, computer domain) — covers the case where\n * the user pings as FQDN manually because Windows isn't auto-appending\n * 3. <host>.local via the OS resolver (Windows 10 1803+ native mDNS)\n * 4. multicast mDNS query directly (bypasses OS resolver — works even when\n * Windows .local resolution is disabled, common in AD/domain environments)\n */\nasync function resolvableHost(host: string): Promise<string> {\n if (/^\\d{1,3}(\\.\\d{1,3}){3}$/.test(host)) return host;\n try {\n await dns.lookup(host);\n return host;\n } catch {}\n if (!host.includes(\".\")) {\n const suffixes = await getDnsSuffixes();\n const { default_fqdn } = await import(\"@bobfrankston/miscinfo\");\n if (default_fqdn && !suffixes.includes(default_fqdn.toLowerCase())) {\n suffixes.push(default_fqdn.toLowerCase());\n }\n for (const suffix of suffixes) {\n const candidate = `${host}.${suffix}`;\n try {\n await dns.lookup(candidate);\n return candidate;\n } catch {}\n }\n }\n const mdnsName = host.includes(\".\") ? host : host + \".local\";\n try {\n await dns.lookup(mdnsName);\n return mdnsName;\n } catch {}\n try {\n const { discoverPdlPrinters } = await import(\"./mdns.js\");\n const printers = await discoverPdlPrinters(2500);\n const target = host.toLowerCase();\n const hit = printers.find(p => {\n const h = p.hostname.toLowerCase().replace(/\\.$/, \"\");\n return h === target || h === target + \".local\" || h.startsWith(target + \".\");\n });\n if (hit && hit.addresses.length > 0) return hit.addresses[0];\n } catch {}\n return host;\n}\n\nlet dnsSuffixCache: string[] | undefined;\n/**\n * Read every DNS suffix the system knows about: the global SuffixSearchList,\n * each adapter's ConnectionSpecificSuffix, and the computer's AD/workgroup\n * domain. Cached per-process. Returns lowercased, de-duplicated, in priority\n * order (search list first since that's what the user explicitly configured).\n */\nasync function getDnsSuffixes(): Promise<string[]> {\n if (dnsSuffixCache) return dnsSuffixCache;\n const { runScriptOrThrow } = await import(\"@bobfrankston/label-core\");\n const script = `\n$ErrorActionPreference = 'SilentlyContinue'\n$out = @()\n$out += (Get-DnsClientGlobalSetting).SuffixSearchList\n$out += Get-DnsClient | Select-Object -ExpandProperty ConnectionSpecificSuffix\n$out += (Get-CimInstance Win32_ComputerSystem).Domain\n$out | Where-Object { $_ -and $_ -ne 'WORKGROUP' } | ForEach-Object { $_.ToLower() } | Select-Object -Unique\n`;\n try {\n const out = await runScriptOrThrow(script);\n dnsSuffixCache = out.split(/\\r?\\n/).map(s => s.trim()).filter(Boolean);\n } catch {\n dnsSuffixCache = [];\n }\n return dnsSuffixCache;\n}\n\n\n/**\n * Print an error with full context: message, cause chain (Node's fetch and\n * other newer APIs put the actual cause in error.cause), and stack on -v.\n */\n/**\n * Report an error: print a one-line summary to stderr and write the full\n * cause-chain (with stacks, codes, paths) to a temp file. Avoids dumping\n * walls of error text into the user's terminal. Set BROTHER_PRINT_DEBUG=1\n * to also include the full chain inline.\n */\nfunction reportError(e: any): void {\n const lines: string[] = [];\n lines.push(`# brother-print error report`);\n lines.push(`# timestamp: ${new Date().toISOString()}`);\n lines.push(`# argv: ${process.argv.join(\" \")}`);\n lines.push(`# cwd: ${process.cwd()}`);\n lines.push(`# pid: ${process.pid}`);\n lines.push(\"\");\n\n let cur = e;\n let depth = 0;\n while (cur) {\n const prefix = depth === 0 ? \"Error\" : \"Caused by\";\n const name = cur.name && cur.name !== \"Error\" ? ` ${cur.name}` : \"\";\n const code = cur.code ? ` [${cur.code}]` : \"\";\n const msg = cur.message ?? String(cur);\n lines.push(`${prefix}${name}${code}: ${msg}`);\n if (cur.path) lines.push(` path: ${cur.path}`);\n if (cur.input) lines.push(` input: ${cur.input}`);\n if (cur.stack) lines.push(String(cur.stack));\n lines.push(\"\");\n cur = cur.cause;\n depth++;\n if (depth > 8) { lines.push(\"... (cause chain truncated at 8 levels)\"); break; }\n }\n\n const dump = lines.join(\"\\n\");\n const tempPath = path.join(os.tmpdir(), `brother-print-error-${Date.now()}-${process.pid}.log`);\n let wroteFile = false;\n try { fs.writeFileSync(tempPath, dump); wroteFile = true; } catch { /* fallback */ }\n\n if (wroteFile) {\n console.error(`Error: ${tempPath}`);\n } else {\n console.error(dump);\n }\n if (process.env.BROTHER_PRINT_DEBUG) {\n console.error(\"--- full report (BROTHER_PRINT_DEBUG enabled) ---\");\n console.error(dump);\n }\n}\n\nasync function cmdList(opts: Record<string, string | boolean>): Promise<void> {\n const printers = await listPrinters();\n /* Brother's listPrinters returns just { name } (legacy shape). To get\n * portName/driverName for the diagnostic line, query label-core's\n * coreListPrinters too. */\n const { listPrinters: coreListPrinters } = await import(\"@bobfrankston/label-core\");\n const all = await coreListPrinters(/brother|^pt-|^ql-/i);\n const byName = new Map(all.map(p => [p.name, p]));\n\n if (printers.length === 0) {\n console.log(\"No installed Brother printers.\");\n } else {\n const sorted = [...printers].sort((a, b) => a.name.localeCompare(b.name));\n console.log(`Brother printers (${sorted.length}):`);\n for (let i = 0; i < sorted.length; i++) {\n const p = sorted[i];\n const info = byName.get(p.name);\n let statusStr = \"?\";\n let queueWarning = \"\";\n try {\n const s = await brotherPrinter.getStatus(p.name);\n statusStr = s.online ? \"online\" : `offline (${s.statusText}${s.error ? \", \" + s.error : \"\"})`;\n queueWarning = s.queueWarning;\n } catch (e: any) {\n statusStr = `status error: ${e.message}`;\n }\n const port = info ? shortenPort(info.portName) : \"(unknown)\";\n const driver = info?.driverName ?? \"(unknown)\";\n console.log(` #${i + 1} ${p.name}`);\n if (info?.comment) console.log(` description: ${info.comment}`);\n if (info?.location) console.log(` location: ${info.location}`);\n console.log(` port: ${port}`);\n if (info?.portName && info.portName !== port) {\n console.log(` full port: ${info.portName}`);\n }\n console.log(` driver: ${driver}`);\n if (info?.shareName && info.shareName !== p.name) {\n console.log(` share name: ${info.shareName}`);\n }\n console.log(` status: ${statusStr}`);\n if (queueWarning) console.log(` warning: ${queueWarning}`);\n }\n }\n\n if (opts.mdns) {\n const { discoverPdlPrinters, isBrother, modelFromTxt, matchesInstalledPort } =\n await import(\"./mdns.js\");\n console.log(\"\");\n console.log(\"Browsing mDNS for _pdl-datastream._tcp (3s)...\");\n const found = (await discoverPdlPrinters()).filter(isBrother);\n if (found.length === 0) {\n console.log(\"No Brother printers responded via mDNS.\");\n return;\n }\n const installedPorts = all.map(p => p.portName);\n const networkOnly = found.filter(m => !installedPorts.some(pn => matchesInstalledPort(m, pn)));\n const matched = found.filter(m => installedPorts.some(pn => matchesInstalledPort(m, pn)));\n\n console.log(`mDNS responders (${found.length}; ${matched.length} matched, ${networkOnly.length} network-only):`);\n let n = 1;\n for (const m of [...matched, ...networkOnly]) {\n const isNetOnly = networkOnly.includes(m);\n const tag = isNetOnly ? \" [network only]\" : \" [installed]\";\n const model = modelFromTxt(m) ?? \"(unknown model)\";\n console.log(` #${n++} ${m.instanceName}${tag}`);\n console.log(` model: ${model}`);\n console.log(` hostname: ${m.hostname.replace(/\\.$/, \"\")}`);\n if (m.addresses.length > 0) {\n console.log(` address: ${m.addresses.join(\", \")}`);\n }\n console.log(` port: ${m.port}`);\n }\n }\n}\n\n/**\n * Pull a short identifier out of a Windows printer port: \"... on hostname\"\n * → hostname; raw IP/hostname kept as-is; USB ports kept as-is.\n */\nfunction shortenPort(portName: string): string {\n if (!portName) return \"(unknown)\";\n const onMatch = portName.match(/\\bon\\s+(\\S+)\\s*$/i);\n if (onMatch) return onMatch[1];\n const hostMatch = portName.match(/\\b(\\d{1,3}(?:\\.\\d{1,3}){3}|[\\w-]+\\.local|[\\w-]+\\.[\\w.-]+)\\b/);\n if (hostMatch) return hostMatch[1];\n return portName;\n}\n\n/**\n * Show details for a single resolved printer: name, port, driver, online\n * status, and the loaded media. For QL printers (auto-detected via the QL\n * TCP path) the media is read from the Windows driver's print ticket; for\n * PT printers detectTape queries the printer live (raw ESC i S status),\n * falling back to the driver ticket when the printer is unreachable.\n */\nasync function cmdPrinterInfo(printerName: string, qlHost: string | undefined): Promise<void> {\n const { listPrinters: coreListPrinters } = await import(\"@bobfrankston/label-core\");\n const all = await coreListPrinters(/brother|^pt-|^ql-/i);\n const info = all.find(p => p.name === printerName);\n\n console.log(`Printer: ${printerName}`);\n if (info?.portName) {\n console.log(`Port: ${info.portName}`);\n }\n if (info?.driverName) {\n console.log(`Driver: ${info.driverName}`);\n }\n try {\n const s = await brotherPrinter.getStatus(printerName);\n const statusStr = s.online ? \"online\" : `offline (${s.statusText}${s.error ? \", \" + s.error : \"\"})`;\n console.log(`Status: ${statusStr}`);\n console.log(`Queue: ${s.queueLength} job(s)`);\n for (const j of s.jobs) {\n console.log(` #${j.id} \"${j.documentName}\" -- ${j.statusText}${j.stuck ? \" [STUCK]\" : \"\"}`);\n }\n if (s.queueWarning) console.log(`Warning: ${s.queueWarning}`);\n } catch (e: any) {\n console.log(`Status: error: ${e.message}`);\n }\n\n if (qlHost) {\n console.log(`QL host: ${qlHost} (TCP/9100)`);\n const { detectQLMediaFromWindows } = await import(\"./ql.js\");\n const media = await detectQLMediaFromWindows(printerName);\n if (media) {\n console.log(`Media: ${media.name} (id ${media.id}, ${media.widthMm}mm${media.heightMm ? `×${media.heightMm}mm` : \", continuous\"})`);\n console.log(` printArea ${media.printAreaDots} dots${media.dieCutMaskedAreaDots ? `, dieCut ${media.dieCutMaskedAreaDots} dots` : \"\"}`);\n } else {\n console.log(`Media: (not detected from Windows driver — pass -ql-media <id>)`);\n }\n } else {\n const detected = await detectTape(printerName);\n const src = detected?.source === \"printer\" ? \"live from printer\" : \"driver default — printer unreachable\";\n console.log(`Loaded tape: ${detected ? `${detected.tape}mm (${src})` : \"(not detected)\"}`);\n }\n}\n\nasync function cmdStatus(opts: Record<string, string | boolean>): Promise<void> {\n const name = (opts.printer as string) || undefined;\n const s = await brotherPrinter.getStatus(name);\n console.log(`Printer: ${s.name}`);\n console.log(`Online: ${s.online ? \"yes\" : \"no\"}`);\n console.log(`Status: ${s.statusText}`);\n if (s.error) console.log(`Error: ${s.error}`);\n console.log(`Queue: ${s.queueLength} job(s)`);\n for (const j of s.jobs) {\n console.log(` #${j.id} \"${j.documentName}\" -- ${j.statusText}${j.stuck ? \" [STUCK]\" : \"\"}`);\n }\n if (s.queueWarning) console.log(`Warning: ${s.queueWarning}`);\n if (s.workOffline) console.log(`Work offline flag: true`);\n}\n\nasync function cmdConfig(opts: Record<string, string | boolean>): Promise<void> {\n const hasUpdate = !!(opts.tape || opts.printer);\n if (!hasUpdate) {\n const cfg = getConfig();\n console.log(`Configuration:`);\n console.log(` File: ${getConfigPath()}`);\n console.log(` Default tape: ${cfg.defaultTape ? cfg.defaultTape + \"mm\" : \"(not set)\"}`);\n console.log(` Default printer: ${cfg.defaultPrinter ?? \"(not set)\"}`);\n console.log(\"\\nValid tape sizes: 6, 9, 12, 18, 24\");\n return;\n }\n if (opts.tape) {\n const t = parseTape(opts.tape as string);\n setConfig({ defaultTape: t });\n console.log(`Default tape set to: ${t}mm`);\n }\n if (opts.printer) {\n setConfig({ defaultPrinter: opts.printer as string });\n console.log(`Default printer set to: ${opts.printer}`);\n }\n}\n\nasync function resolveTape(opts: Record<string, string | boolean>): Promise<TapeSize> {\n /* Explicit -tape skips the status round-trip entirely: the user said\n * what they want, and the live query costs ~1s of PowerShell. */\n if (opts.tape) return parseTape(opts.tape as string);\n const detected = await detectTape(opts.printer as string | undefined);\n if (detected) return detected.tape;\n return getConfig().defaultTape ?? 24;\n}\n\nasync function cmdPrint(\n opts: Record<string, string | boolean>,\n segments: Segment[],\n inputs: string[]\n): Promise<void> {\n const tape = await resolveTape(opts);\n\n // If there are 2+ positional inputs, treat each as a text segment.\n // (A single positional input is handled below via classifyInput so it can\n // auto-detect file paths.)\n if (inputs.length > 1 || (inputs.length >= 1 && segments.length > 0)) {\n for (const inp of inputs) {\n segments.push({ type: \"text\", value: inp });\n }\n inputs.length = 0;\n }\n\n const baseOpts = {\n printer: opts.printer as string | undefined,\n wait: !opts.nowait,\n waitTimeoutMs: opts.timeout ? Math.round(parseFloat(opts.timeout as string) * 1000) : undefined,\n waitIntervalMs: opts.interval ? Math.round(parseFloat(opts.interval as string) * 1000) : undefined,\n onWaiting: makeWaitCallback(),\n log: (msg: string) => outln(msg),\n };\n\n const qlHost = typeof opts.ql === \"string\" ? opts.ql : undefined;\n const qlMediaId = typeof opts.qlMedia === \"string\" ? parseInt(opts.qlMedia, 10) : undefined;\n\n // Multi-segment mode: explicit -text/-qr (>=1 segment), with positional joined in\n if (segments.length > 1 || (segments.length === 1 && inputs.length === 0)) {\n const segOpts: SegmentOptions = {\n ...baseOpts,\n tape,\n textHeight: opts.height as string | undefined,\n space: opts.space as string | undefined,\n };\n if (opts.output) {\n const buffer = await renderSegments(segments, tape, opts.height as string | undefined, opts.space as string | undefined);\n fs.writeFileSync(opts.output as string, buffer);\n outln(`Saved to ${opts.output}`);\n } else if (qlHost) {\n const buffer = await renderSegments(segments, tape, opts.height as string | undefined, opts.space as string | undefined);\n const { printPngToQL } = await import(\"./ql.js\");\n await printPngToQL(qlHost, buffer, qlMediaId, opts.printer as string | undefined, !!opts.verbose);\n outln(`Printed ${segments.length} segment(s) to QL @ ${qlHost}`);\n } else {\n await printSegments(segments, segOpts);\n outln(`Printed ${segments.length} segment(s) on ${tape}mm tape`);\n }\n return;\n }\n\n // Single content op\n const printOpts: PrintOptions = {\n ...baseOpts,\n tape,\n aspect: opts.aspect as string | undefined,\n textHeight: opts.height as string | undefined,\n };\n\n if (opts.clip) {\n printOpts.clip = true;\n } else if (inputs.length === 1) {\n Object.assign(printOpts, classifyInput(inputs[0], opts));\n } else if (inputs.length === 0 && segments.length === 0) {\n if (opts.printer) {\n await cmdPrinterInfo(opts.printer as string, qlHost);\n return;\n }\n showHelp();\n return;\n }\n\n if (opts.output) {\n const buffer = await render(printOpts);\n fs.writeFileSync(opts.output as string, buffer);\n outln(`Saved to ${opts.output}`);\n return;\n }\n if (qlHost) {\n const buffer = await render(printOpts);\n const { printPngToQL } = await import(\"./ql.js\");\n await printPngToQL(qlHost, buffer, qlMediaId, opts.printer as string | undefined, !!opts.verbose);\n outln(`Printed to QL @ ${qlHost}`);\n return;\n }\n await print(printOpts);\n outln(`Printed on ${tape}mm tape`);\n}\n\nfunction classifyInput(input: string, opts: Record<string, string | boolean>): Partial<CorePrintOptions> {\n if (opts.text) return { text: input };\n if (opts.html) return { htmlPath: path.resolve(input) };\n if (opts.image) return { imagePath: path.resolve(input) };\n\n const lower = input.toLowerCase();\n if (lower.endsWith(\".html\") || lower.endsWith(\".htm\")) return { htmlPath: path.resolve(input) };\n if (lower.endsWith(\".txt\")) return { textFile: path.resolve(input) };\n if (/\\.(png|jpg|jpeg|bmp|gif)$/i.test(lower)) return { imagePath: path.resolve(input) };\n if (fs.existsSync(input)) {\n const ext = path.extname(lower);\n if (ext === \".html\" || ext === \".htm\") return { htmlPath: path.resolve(input) };\n return { textFile: path.resolve(input) };\n }\n return { text: input };\n}\n\nfunction makeWaitCallback() {\n let lastReport = -Infinity;\n return (status: PrinterStatus, elapsedMs: number) => {\n const secs = Math.floor(elapsedMs / 1000);\n // Non-TTY (redirected output) can't rewrite in place; report sparsely.\n if (!process.stderr.isTTY) {\n if (secs - lastReport < 30) return;\n lastReport = secs;\n }\n statusLine.update(`[brother-print] waiting for ${status.name} (${status.statusText}${status.error ? \", \" + status.error : \"\"}); ${secs}s`);\n };\n}\n\nmain();\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n/**\n * Brother Label Printer CLI\n * Thin wrapper around api.ts using shared CLI primitives from label-core.\n */\n\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport * as dns from \"dns/promises\";\nimport {\n preprocessSingleQuotes,\n parseArgs,\n} from \"@bobfrankston/label-core\";\nimport type {\n PrintOptions as CorePrintOptions,\n PrinterStatus,\n Segment,\n ValuedOptionSpec,\n BooleanFlagSpec,\n} from \"@bobfrankston/label-core\";\nimport {\n print,\n render,\n renderSegments,\n printSegments,\n getConfig,\n setConfig,\n getConfigPath,\n listPrinters,\n resolvePrinter,\n getDefaultPrinter,\n detectTape,\n brotherPrinter,\n} from \"./api.js\";\nimport type { TapeSize, PrintOptions, SegmentOptions } from \"./api.js\";\n\nconst VERSION = \"1.1.0\";\nconst VALID_TAPES: TapeSize[] = [6, 9, 12, 18, 24];\n\nfunction parseTape(value: string): TapeSize {\n const num = parseInt(value.replace(\"mm\", \"\"), 10) as TapeSize;\n if (!VALID_TAPES.includes(num)) {\n throw new UserError(`Invalid tape size: ${value}. Valid: ${VALID_TAPES.join(\", \")}`);\n }\n return num;\n}\n\nconst VALUED: ValuedOptionSpec[] = [\n { names: [\"-tape\"], key: \"tape\" },\n { names: [\"-p\", \"-printer\"], key: \"printer\" },\n { names: [\"-o\", \"-output\"], key: \"output\" },\n { names: [\"-a\", \"-aspect\"], key: \"aspect\" },\n { names: [\"-ht\", \"-height\"], key: \"height\" },\n { names: [\"-s\", \"-space\"], key: \"space\" },\n { names: [\"-timeout\"], key: \"timeout\" },\n { names: [\"-interval\"], key: \"interval\" },\n { names: [\"-ql\"], key: \"ql\" },\n { names: [\"-ql-media\"], key: \"qlMedia\" },\n { names: [\"-port\"], key: \"port\" },\n];\n\nconst BOOLEAN: BooleanFlagSpec[] = [\n { names: [\"-w\", \"-html\"], key: \"html\" },\n { names: [\"-i\", \"-image\"], key: \"image\" },\n { names: [\"-t\"], key: \"text\" },\n { names: [\"-c\", \"-clip\"], key: \"clip\" },\n { names: [\"-no-wait\", \"-nowait\"], key: \"nowait\" },\n { names: [\"-mdns\"], key: \"mdns\" },\n { names: [\"-vb\", \"-verbose\"], key: \"verbose\" },\n { names: [\"-queue\"], key: \"queue\" },\n { names: [\"-no-cut\", \"-nocut\"], key: \"nocut\" },\n { names: [\"-help\", \"-h\", \"-?\"], key: \"help\" },\n { names: [\"-version\", \"-v\"], key: \"version\" },\n];\n\nconst SUBCOMMANDS = [\"list\", \"status\", \"config\"];\n\nfunction showHelp(): void {\n console.log(`Brother Label Printer CLI v${VERSION}\n\nUsage:\n brother-print [options] <text> Print text\n brother-print [options] <file> Print html/txt/image file (auto-detected)\n brother-print -clip [options] Print clipboard contents (image or text)\n brother-print -text <v> -qr <v> ... Print ordered text/qr segments\n brother-print -list [-mdns] List Brother printers and status\n (-mdns also discovers network printers)\n brother-print -status [-p <name>] Show printer status\n brother-print -config Show / set defaults\n\nCommands take a leading dash so they can never be confused with label content:\na bare word is always something to print, a dashed word is always a command.\n\nTape size is auto-detected from the printer. Use -tape to override.\nSingle quotes can wrap arguments: '7\"' 'line1\\\\nline2'\n\nOptions:\n -tape <size> Tape size: 6, 9, 12, 18, 24 (mm) [auto-detected]\n -p, -printer <name> Printer queue name\n -o, -output <file> Save PNG to file instead of printing\n -a, -aspect <r> Aspect ratio width:height for HTML (e.g. 3.5:2)\n -ht, -height <size> Text height: 12mm, .5in, or 50% (of tape height)\n -s, -space <size> Space between segments: 12px, 1mm, .2in\n -t, -text Force input as literal text (-text <v> for segments)\n -qr <data> QR code segment\n -w, -html Force input as HTML file path\n -i, -image Force input as image file path\n -c, -clip Read content from clipboard (image preferred, then text)\n -no-wait Fail immediately if printer is offline (default: wait)\n -timeout <secs> Max wait time when printer is offline\n -interval <secs> Polling interval while waiting (default 2)\n -mdns With -list: also discover network printers via mDNS\n -ql <host> Print to a Brother QL series printer over TCP/9100\n (bypasses Windows queue; e.g. -ql ql720 or -ql 1.2.3.4)\n -ql-media <id> QL media id (e.g. 271=DK-11201 29×90mm, 259=DK-22205 62mm)\n Required when the printer doesn't respond to status\n -queue Print through the Windows spooler (XPS) instead of\n writing raster bytes straight to the printer's port\n -port <COMn> Serial/Bluetooth port for direct printing (overrides\n the port looked up from the printer queue)\n -no-cut Do not cut the tape after the label (direct path only)\n -vb, -verbose Print extra QL diagnostic messages (status, media source)\n -help Show this help\n -version Show version`);\n}\n\n/** Expected user-facing error: prints one line, no log file, no stack. */\nclass UserError extends Error {\n readonly isUserError = true;\n}\n\n/**\n * Single-line status display: on a TTY the line is rewritten in place\n * (CR + erase-line) instead of scrolling; callers must clear() before any\n * normal output so it doesn't collide with the pending status line.\n */\nconst statusLine = {\n active: false,\n update(msg: string): void {\n if (process.stderr.isTTY) {\n process.stderr.write(`\\r\\x1b[2K${msg}`);\n this.active = true;\n } else {\n console.error(msg);\n }\n },\n clear(): void {\n if (this.active) {\n process.stderr.write(`\\r\\x1b[2K`);\n this.active = false;\n }\n },\n};\n\n/** console.log that first clears any in-place status line. */\nfunction outln(msg: string): void {\n statusLine.clear();\n console.log(msg);\n}\n\nasync function main(): Promise<void> {\n const argv = preprocessSingleQuotes(process.argv.slice(2));\n let parsed;\n try {\n parsed = parseArgs(argv, VALUED, BOOLEAN, SUBCOMMANDS);\n } catch (e: any) {\n console.error(`Error: ${e.message}`);\n process.exit(1);\n }\n\n if (parsed.unknown.length > 0) {\n console.error(`Unknown option(s): ${parsed.unknown.join(\", \")}`);\n console.error(`Run \"brother-print -help\" for usage.`);\n process.exit(1);\n }\n\n /* Bare `list` used to be the command syntax; it is now `-list`. Refusing\n * beats guessing: printing a label that says \"list\" and listing printers\n * are both plausible readings of the same word. */\n if (parsed.ambiguous.length > 0) {\n const w = parsed.ambiguous[0];\n console.error(`Ambiguous argument: \"${w}\" -- commands now take a dash.`);\n console.error(` brother-print -${w} run the ${w} command`);\n console.error(` brother-print -text ${w} print a label that says \"${w}\"`);\n process.exit(1);\n }\n\n if (parsed.opts.help) { showHelp(); return; }\n if (parsed.opts.version) { console.log(VERSION); return; }\n\n try {\n if (typeof parsed.opts.printer === \"string\") {\n parsed.opts.printer = await resolvePrinter(parsed.opts.printer);\n /* Auto-route QL series through the QL TCP path. The XPS / CustomMediaSize\n * pipeline is P-touch-only; sending it to a QL queue produces an XPS\n * error. If the user already passed -ql explicitly, leave it alone. */\n if (!parsed.opts.ql && isQLPrinter(parsed.opts.printer)) {\n const host = await resolveQLHost(parsed.opts.printer);\n if (host) parsed.opts.ql = host;\n }\n }\n switch (parsed.command) {\n case \"list\": await cmdList(parsed.opts); return;\n case \"status\": await cmdStatus(parsed.opts); return;\n case \"config\": await cmdConfig(parsed.opts); return;\n }\n await cmdPrint(parsed.opts, parsed.segments, parsed.inputs);\n } catch (e: any) {\n statusLine.clear();\n /* Timeout/offline are expected conditions, not crashes — one line,\n * no error-report file. */\n if (e?.isUserError || /^Timed out waiting for printer|is offline \\(/.test(e?.message ?? \"\")) {\n console.error(`Error: ${e.message}`);\n process.exit(1);\n }\n reportError(e);\n process.exit(1);\n }\n}\n\nfunction isQLPrinter(name: string): boolean {\n return /\\bQL-/i.test(name);\n}\n\n/**\n * Look up the TCP host for a QL printer's installed Windows queue. Pulls the\n * port name via label-core, then asks PowerShell for that port's\n * PrinterHostAddress. Returns undefined if the port isn't a TCP/IP port (e.g.\n * the QL-820NWB's BRWxxxx Bluetooth port has no host address).\n */\nasync function resolveQLHost(printerName: string): Promise<string | undefined> {\n const { listPrinters: coreListPrinters, runScriptOrThrow } =\n await import(\"@bobfrankston/label-core\");\n const all = await coreListPrinters(/brother|^pt-|^ql-/i);\n const info = all.find(p => p.name === printerName);\n if (!info?.portName) return undefined;\n const port = info.portName.replace(/'/g, \"''\");\n const script = `\n$ErrorActionPreference = 'SilentlyContinue'\n$p = Get-PrinterPort -Name '${port}'\nif ($p -and $p.PrinterHostAddress) { Write-Output $p.PrinterHostAddress }\n`;\n try {\n const out = (await runScriptOrThrow(script)).trim();\n if (!out) return undefined;\n return await resolvableHost(out);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Brother's installer often writes a bare NetBIOS-style hostname (BRWxxxx)\n * as the port's PrinterHostAddress, which won't resolve in environments where\n * the DNS suffix isn't auto-appended. Resolution tiers, in order:\n * 1. as-is via the OS resolver\n * 2. <host>.<suffix> for every DNS suffix the OS knows about (global search\n * list, per-connection suffix, computer domain) — covers the case where\n * the user pings as FQDN manually because Windows isn't auto-appending\n * 3. <host>.local via the OS resolver (Windows 10 1803+ native mDNS)\n * 4. multicast mDNS query directly (bypasses OS resolver — works even when\n * Windows .local resolution is disabled, common in AD/domain environments)\n */\nasync function resolvableHost(host: string): Promise<string> {\n if (/^\\d{1,3}(\\.\\d{1,3}){3}$/.test(host)) return host;\n try {\n await dns.lookup(host);\n return host;\n } catch {}\n if (!host.includes(\".\")) {\n const suffixes = await getDnsSuffixes();\n const { default_fqdn } = await import(\"@bobfrankston/miscinfo\");\n if (default_fqdn && !suffixes.includes(default_fqdn.toLowerCase())) {\n suffixes.push(default_fqdn.toLowerCase());\n }\n for (const suffix of suffixes) {\n const candidate = `${host}.${suffix}`;\n try {\n await dns.lookup(candidate);\n return candidate;\n } catch {}\n }\n }\n const mdnsName = host.includes(\".\") ? host : host + \".local\";\n try {\n await dns.lookup(mdnsName);\n return mdnsName;\n } catch {}\n try {\n const { discoverPdlPrinters } = await import(\"./mdns.js\");\n const printers = await discoverPdlPrinters(2500);\n const target = host.toLowerCase();\n const hit = printers.find(p => {\n const h = p.hostname.toLowerCase().replace(/\\.$/, \"\");\n return h === target || h === target + \".local\" || h.startsWith(target + \".\");\n });\n if (hit && hit.addresses.length > 0) return hit.addresses[0];\n } catch {}\n return host;\n}\n\nlet dnsSuffixCache: string[] | undefined;\n/**\n * Read every DNS suffix the system knows about: the global SuffixSearchList,\n * each adapter's ConnectionSpecificSuffix, and the computer's AD/workgroup\n * domain. Cached per-process. Returns lowercased, de-duplicated, in priority\n * order (search list first since that's what the user explicitly configured).\n */\nasync function getDnsSuffixes(): Promise<string[]> {\n if (dnsSuffixCache) return dnsSuffixCache;\n const { runScriptOrThrow } = await import(\"@bobfrankston/label-core\");\n const script = `\n$ErrorActionPreference = 'SilentlyContinue'\n$out = @()\n$out += (Get-DnsClientGlobalSetting).SuffixSearchList\n$out += Get-DnsClient | Select-Object -ExpandProperty ConnectionSpecificSuffix\n$out += (Get-CimInstance Win32_ComputerSystem).Domain\n$out | Where-Object { $_ -and $_ -ne 'WORKGROUP' } | ForEach-Object { $_.ToLower() } | Select-Object -Unique\n`;\n try {\n const out = await runScriptOrThrow(script);\n dnsSuffixCache = out.split(/\\r?\\n/).map(s => s.trim()).filter(Boolean);\n } catch {\n dnsSuffixCache = [];\n }\n return dnsSuffixCache;\n}\n\n\n/**\n * Print an error with full context: message, cause chain (Node's fetch and\n * other newer APIs put the actual cause in error.cause), and stack on -v.\n */\n/**\n * Report an error: print a one-line summary to stderr and write the full\n * cause-chain (with stacks, codes, paths) to a temp file. Avoids dumping\n * walls of error text into the user's terminal. Set BROTHER_PRINT_DEBUG=1\n * to also include the full chain inline.\n */\nfunction reportError(e: any): void {\n const lines: string[] = [];\n lines.push(`# brother-print error report`);\n lines.push(`# timestamp: ${new Date().toISOString()}`);\n lines.push(`# argv: ${process.argv.join(\" \")}`);\n lines.push(`# cwd: ${process.cwd()}`);\n lines.push(`# pid: ${process.pid}`);\n lines.push(\"\");\n\n let cur = e;\n let depth = 0;\n while (cur) {\n const prefix = depth === 0 ? \"Error\" : \"Caused by\";\n const name = cur.name && cur.name !== \"Error\" ? ` ${cur.name}` : \"\";\n const code = cur.code ? ` [${cur.code}]` : \"\";\n const msg = cur.message ?? String(cur);\n lines.push(`${prefix}${name}${code}: ${msg}`);\n if (cur.path) lines.push(` path: ${cur.path}`);\n if (cur.input) lines.push(` input: ${cur.input}`);\n if (cur.stack) lines.push(String(cur.stack));\n lines.push(\"\");\n cur = cur.cause;\n depth++;\n if (depth > 8) { lines.push(\"... (cause chain truncated at 8 levels)\"); break; }\n }\n\n const dump = lines.join(\"\\n\");\n const tempPath = path.join(os.tmpdir(), `brother-print-error-${Date.now()}-${process.pid}.log`);\n let wroteFile = false;\n try { fs.writeFileSync(tempPath, dump); wroteFile = true; } catch { /* fallback */ }\n\n if (wroteFile) {\n console.error(`Error: ${tempPath}`);\n } else {\n console.error(dump);\n }\n if (process.env.BROTHER_PRINT_DEBUG) {\n console.error(\"--- full report (BROTHER_PRINT_DEBUG enabled) ---\");\n console.error(dump);\n }\n}\n\nasync function cmdList(opts: Record<string, string | boolean>): Promise<void> {\n const printers = await listPrinters();\n /* Brother's listPrinters returns just { name } (legacy shape). To get\n * portName/driverName for the diagnostic line, query label-core's\n * coreListPrinters too. */\n const { listPrinters: coreListPrinters } = await import(\"@bobfrankston/label-core\");\n const all = await coreListPrinters(/brother|^pt-|^ql-/i);\n const byName = new Map(all.map(p => [p.name, p]));\n\n if (printers.length === 0) {\n console.log(\"No installed Brother printers.\");\n } else {\n const sorted = [...printers].sort((a, b) => a.name.localeCompare(b.name));\n console.log(`Brother printers (${sorted.length}):`);\n for (let i = 0; i < sorted.length; i++) {\n const p = sorted[i];\n const info = byName.get(p.name);\n let statusStr = \"?\";\n let queueWarning = \"\";\n try {\n const s = await brotherPrinter.getStatus(p.name);\n statusStr = s.online ? \"online\" : `offline (${s.statusText}${s.error ? \", \" + s.error : \"\"})`;\n queueWarning = s.queueWarning;\n } catch (e: any) {\n statusStr = `status error: ${e.message}`;\n }\n const port = info ? shortenPort(info.portName) : \"(unknown)\";\n const driver = info?.driverName ?? \"(unknown)\";\n console.log(` #${i + 1} ${p.name}`);\n if (info?.comment) console.log(` description: ${info.comment}`);\n if (info?.location) console.log(` location: ${info.location}`);\n console.log(` port: ${port}`);\n if (info?.portName && info.portName !== port) {\n console.log(` full port: ${info.portName}`);\n }\n console.log(` driver: ${driver}`);\n if (info?.shareName && info.shareName !== p.name) {\n console.log(` share name: ${info.shareName}`);\n }\n console.log(` status: ${statusStr}`);\n if (queueWarning) console.log(` warning: ${queueWarning}`);\n }\n }\n\n if (opts.mdns) {\n const { discoverPdlPrinters, isBrother, modelFromTxt, matchesInstalledPort } =\n await import(\"./mdns.js\");\n console.log(\"\");\n console.log(\"Browsing mDNS for _pdl-datastream._tcp (3s)...\");\n const found = (await discoverPdlPrinters()).filter(isBrother);\n if (found.length === 0) {\n console.log(\"No Brother printers responded via mDNS.\");\n return;\n }\n const installedPorts = all.map(p => p.portName);\n const networkOnly = found.filter(m => !installedPorts.some(pn => matchesInstalledPort(m, pn)));\n const matched = found.filter(m => installedPorts.some(pn => matchesInstalledPort(m, pn)));\n\n console.log(`mDNS responders (${found.length}; ${matched.length} matched, ${networkOnly.length} network-only):`);\n let n = 1;\n for (const m of [...matched, ...networkOnly]) {\n const isNetOnly = networkOnly.includes(m);\n const tag = isNetOnly ? \" [network only]\" : \" [installed]\";\n const model = modelFromTxt(m) ?? \"(unknown model)\";\n console.log(` #${n++} ${m.instanceName}${tag}`);\n console.log(` model: ${model}`);\n console.log(` hostname: ${m.hostname.replace(/\\.$/, \"\")}`);\n if (m.addresses.length > 0) {\n console.log(` address: ${m.addresses.join(\", \")}`);\n }\n console.log(` port: ${m.port}`);\n }\n }\n}\n\n/**\n * Pull a short identifier out of a Windows printer port: \"... on hostname\"\n * → hostname; raw IP/hostname kept as-is; USB ports kept as-is.\n */\nfunction shortenPort(portName: string): string {\n if (!portName) return \"(unknown)\";\n const onMatch = portName.match(/\\bon\\s+(\\S+)\\s*$/i);\n if (onMatch) return onMatch[1];\n const hostMatch = portName.match(/\\b(\\d{1,3}(?:\\.\\d{1,3}){3}|[\\w-]+\\.local|[\\w-]+\\.[\\w.-]+)\\b/);\n if (hostMatch) return hostMatch[1];\n return portName;\n}\n\n/**\n * Show details for a single resolved printer: name, port, driver, online\n * status, and the loaded media. For QL printers (auto-detected via the QL\n * TCP path) the media is read from the Windows driver's print ticket; for\n * PT printers detectTape queries the printer live (raw ESC i S status),\n * falling back to the driver ticket when the printer is unreachable.\n */\nasync function cmdPrinterInfo(printerName: string, qlHost: string | undefined): Promise<void> {\n const { listPrinters: coreListPrinters } = await import(\"@bobfrankston/label-core\");\n const all = await coreListPrinters(/brother|^pt-|^ql-/i);\n const info = all.find(p => p.name === printerName);\n\n console.log(`Printer: ${printerName}`);\n if (info?.portName) {\n console.log(`Port: ${info.portName}`);\n }\n if (info?.driverName) {\n console.log(`Driver: ${info.driverName}`);\n }\n try {\n const s = await brotherPrinter.getStatus(printerName);\n const statusStr = s.online ? \"online\" : `offline (${s.statusText}${s.error ? \", \" + s.error : \"\"})`;\n console.log(`Status: ${statusStr}`);\n console.log(`Queue: ${s.queueLength} job(s)`);\n for (const j of s.jobs) {\n console.log(` #${j.id} \"${j.documentName}\" -- ${j.statusText}${j.stuck ? \" [STUCK]\" : \"\"}`);\n }\n if (s.queueWarning) console.log(`Warning: ${s.queueWarning}`);\n } catch (e: any) {\n console.log(`Status: error: ${e.message}`);\n }\n\n if (!qlHost) {\n const { resolvePtModel } = await import(\"./ptdirect.js\");\n const model = resolvePtModel(printerName);\n const direct = await resolvePtPort(printerName);\n if (model && direct) {\n console.log(`Direct: ${direct.port} via ${direct.source}`);\n console.log(` profile ${model.name}${model.verified ? \"\" : \" — geometry not from this model's own manual\"}`);\n } else {\n console.log(`Direct: unavailable (${!model ? \"no raster profile for this model\" : \"no serial port found\"}) — prints via the spooler`);\n }\n }\n\n if (qlHost) {\n console.log(`QL host: ${qlHost} (TCP/9100)`);\n const { detectQLMediaFromWindows } = await import(\"./ql.js\");\n const media = await detectQLMediaFromWindows(printerName);\n if (media) {\n console.log(`Media: ${media.name} (id ${media.id}, ${media.widthMm}mm${media.heightMm ? `×${media.heightMm}mm` : \", continuous\"})`);\n console.log(` printArea ${media.printAreaDots} dots${media.dieCutMaskedAreaDots ? `, dieCut ${media.dieCutMaskedAreaDots} dots` : \"\"}`);\n } else {\n console.log(`Media: (not detected from Windows driver — pass -ql-media <id>)`);\n }\n } else {\n const detected = await detectTape(printerName);\n const src = detected?.source === \"printer\" ? \"live from printer\" : \"driver default — printer unreachable\";\n console.log(`Loaded tape: ${detected ? `${detected.tape}mm (${src})` : \"(not detected)\"}`);\n }\n}\n\nasync function cmdStatus(opts: Record<string, string | boolean>): Promise<void> {\n const name = (opts.printer as string) || undefined;\n const s = await brotherPrinter.getStatus(name);\n console.log(`Printer: ${s.name}`);\n console.log(`Online: ${s.online ? \"yes\" : \"no\"}`);\n console.log(`Status: ${s.statusText}`);\n if (s.error) console.log(`Error: ${s.error}`);\n console.log(`Queue: ${s.queueLength} job(s)`);\n for (const j of s.jobs) {\n console.log(` #${j.id} \"${j.documentName}\" -- ${j.statusText}${j.stuck ? \" [STUCK]\" : \"\"}`);\n }\n if (s.queueWarning) console.log(`Warning: ${s.queueWarning}`);\n if (s.workOffline) console.log(`Work offline flag: true`);\n}\n\nasync function cmdConfig(opts: Record<string, string | boolean>): Promise<void> {\n const hasUpdate = !!(opts.tape || opts.printer);\n if (!hasUpdate) {\n const cfg = getConfig();\n console.log(`Configuration:`);\n console.log(` File: ${getConfigPath()}`);\n console.log(` Default tape: ${cfg.defaultTape ? cfg.defaultTape + \"mm\" : \"(not set)\"}`);\n console.log(` Default printer: ${cfg.defaultPrinter ?? \"(not set)\"}`);\n console.log(\"\\nValid tape sizes: 6, 9, 12, 18, 24\");\n return;\n }\n if (opts.tape) {\n const t = parseTape(opts.tape as string);\n setConfig({ defaultTape: t });\n console.log(`Default tape set to: ${t}mm`);\n }\n if (opts.printer) {\n setConfig({ defaultPrinter: opts.printer as string });\n console.log(`Default printer set to: ${opts.printer}`);\n }\n}\n\nasync function resolveTape(opts: Record<string, string | boolean>): Promise<TapeSize> {\n /* Explicit -tape skips the status round-trip entirely: the user said\n * what they want, and the live query costs ~1s of PowerShell. */\n if (opts.tape) return parseTape(opts.tape as string);\n const detected = await detectTape(opts.printer as string | undefined);\n if (detected) return detected.tape;\n return getConfig().defaultTape ?? 24;\n}\n\nasync function cmdPrint(\n opts: Record<string, string | boolean>,\n segments: Segment[],\n inputs: string[]\n): Promise<void> {\n const tape = await resolveTape(opts);\n\n // If there are 2+ positional inputs, treat each as a text segment.\n // (A single positional input is handled below via classifyInput so it can\n // auto-detect file paths.)\n if (inputs.length > 1 || (inputs.length >= 1 && segments.length > 0)) {\n for (const inp of inputs) {\n segments.push({ type: \"text\", value: inp });\n }\n inputs.length = 0;\n }\n\n const baseOpts = {\n printer: opts.printer as string | undefined,\n wait: !opts.nowait,\n waitTimeoutMs: opts.timeout ? Math.round(parseFloat(opts.timeout as string) * 1000) : undefined,\n waitIntervalMs: opts.interval ? Math.round(parseFloat(opts.interval as string) * 1000) : undefined,\n onWaiting: makeWaitCallback(),\n log: (msg: string) => outln(msg),\n };\n\n const qlHost = typeof opts.ql === \"string\" ? opts.ql : undefined;\n const qlMediaId = typeof opts.qlMedia === \"string\" ? parseInt(opts.qlMedia, 10) : undefined;\n\n // Multi-segment mode: explicit -text/-qr (>=1 segment), with positional joined in\n if (segments.length > 1 || (segments.length === 1 && inputs.length === 0)) {\n const segOpts: SegmentOptions = {\n ...baseOpts,\n tape,\n textHeight: opts.height as string | undefined,\n space: opts.space as string | undefined,\n };\n let segDirectPort: string;\n if (opts.output) {\n const buffer = await renderSegments(segments, tape, opts.height as string | undefined, opts.space as string | undefined);\n fs.writeFileSync(opts.output as string, buffer);\n outln(`Saved to ${opts.output}`);\n } else if (qlHost) {\n const buffer = await renderSegments(segments, tape, opts.height as string | undefined, opts.space as string | undefined);\n const { printPngToQL } = await import(\"./ql.js\");\n await printPngToQL(qlHost, buffer, qlMediaId, opts.printer as string | undefined, !!opts.verbose);\n outln(`Printed ${segments.length} segment(s) on ${(opts.printer as string) || \"QL\"} @ ${qlHost}, ${tape}mm (direct TCP/9100)`);\n } else if (segDirectPort = await tryPrintDirect(\n await renderSegments(segments, tape, opts.height as string | undefined, opts.space as string | undefined),\n opts, tape)) {\n reportPrinted(`${segments.length} segment(s) `, opts, tape, segDirectPort);\n } else {\n await printSegments(segments, segOpts);\n reportPrinted(`${segments.length} segment(s) `, opts, tape, null);\n }\n return;\n }\n\n // Single content op\n const printOpts: PrintOptions = {\n ...baseOpts,\n tape,\n aspect: opts.aspect as string | undefined,\n textHeight: opts.height as string | undefined,\n };\n\n if (opts.clip) {\n printOpts.clip = true;\n } else if (inputs.length === 1) {\n Object.assign(printOpts, classifyInput(inputs[0], opts));\n } else if (inputs.length === 0 && segments.length === 0) {\n if (opts.printer) {\n await cmdPrinterInfo(opts.printer as string, qlHost);\n return;\n }\n showHelp();\n return;\n }\n\n if (opts.output) {\n const buffer = await render(printOpts);\n fs.writeFileSync(opts.output as string, buffer);\n outln(`Saved to ${opts.output}`);\n return;\n }\n if (qlHost) {\n const buffer = await render(printOpts);\n const { printPngToQL } = await import(\"./ql.js\");\n await printPngToQL(qlHost, buffer, qlMediaId, opts.printer as string | undefined, !!opts.verbose);\n outln(`Printed on ${(opts.printer as string) || \"QL\"} @ ${qlHost} (direct TCP/9100)`);\n return;\n }\n const directPort = await tryPrintDirect(await render(printOpts), opts, tape);\n if (directPort) {\n reportPrinted(\"\", opts, tape, directPort);\n return;\n }\n await print(printOpts);\n reportPrinted(\"\", opts, tape, null);\n}\n\n/**\n * Name the printer, the tape and the route a label actually took.\n *\n * \"Printed on 24mm tape\" is not something the user can check: it does not say\n * which of four Brother printers took it, and it reads identically whether the\n * bytes reached the printer or merely reached the Windows queue -- which is\n * where labels disappear. Naming the target and the route makes the line\n * verifiable, and still means something when read back in a log later.\n */\nfunction describeTarget(opts: Record<string, string | boolean>, tape: TapeSize, port: string): string {\n const printer = (opts.printer as string) || getDefaultPrinter();\n return port\n ? `${printer}, ${tape}mm tape (direct to ${port})`\n : `${printer}, ${tape}mm tape`;\n}\n\n/**\n * The verb has to be honest about what happened. A direct write reached the\n * printer, so \"Printed\" is a claim we can stand behind. Handing a job to the\n * Windows spooler is not printing -- the job can sit Retained in Error behind\n * another dead job and never reach the tape, which is exactly how labels have\n * been going missing. Say \"Queued\" for that, and name the printer either way.\n */\nfunction reportPrinted(what: string, opts: Record<string, string | boolean>, tape: TapeSize, port: string): void {\n const verb = port ? \"Printed\" : \"Queued\";\n const tail = port ? \"\" : \" -- the spooler has it; check the queue if nothing comes out\";\n outln(`${verb} ${what}on ${describeTarget(opts, tape, port)}${tail}`);\n}\n\n/**\n * Write the rendered label straight to the printer's port, skipping the\n * Windows spooler. Returns false when this printer has no direct path, so the\n * caller can fall back to the XPS/queue route.\n *\n * The direct route is the default because the queue is where labels go to die:\n * a job that fails is left Retained and blocks every later job until someone\n * clears it by hand, and `WorkOffline` discards jobs without a word. Writing\n * the bytes ourselves either succeeds or throws — there is no third state that\n * looks like success and prints nothing. `-queue` opts back in.\n */\nasync function tryPrintDirect(\n png: Buffer,\n opts: Record<string, string | boolean>,\n tape: TapeSize\n): Promise<string> {\n if (opts.queue) {\n /* A queue can be pointed at a discard port so the spooler stops\n * fighting us for the printer's serial port. Printing to it would\n * report success and put nothing on the tape, which is the one\n * outcome this whole module exists to prevent. */\n await refuseDiscardQueue(opts.printer as string);\n return null;\n }\n /* Fall back to the same default the spooler path uses, so omitting -p does\n * not silently drop the label into the queue. */\n const printerName = (opts.printer as string) || getDefaultPrinter();\n if (!printerName) return null;\n\n const { resolvePtModel, printPtDirect } = await import(\"./ptdirect.js\");\n if (!resolvePtModel(printerName)) return null;\n\n const port = (opts.port as string) || (await resolvePtPort(printerName))?.port;\n if (!port) return null;\n\n const jobsBefore = await listJobIds(printerName);\n try {\n await printPtDirect(png, {\n port,\n printerName,\n tape,\n autoCut: !opts.nocut,\n log: opts.verbose ? (m: string) => outln(m) : undefined,\n });\n } finally {\n /* Clear it even when the write failed -- a failed open still leaves the\n * phantom behind, and that is precisely when a wedged queue is most\n * confusing to look at. */\n await clearPhantomJobs(printerName, jobsBefore);\n }\n return port;\n}\n\n/** Ports that swallow whatever the spooler sends them. */\nconst DISCARD_PORTS = /^(nul|null|nul:|null:)$/i;\n\n/**\n * List the spooler's current job ids for a printer. Best-effort: a failure\n * here must never stop a label printing.\n */\nasync function listJobIds(printerName: string): Promise<Set<number>> {\n try {\n const { runScriptOrThrow } = await import(\"@bobfrankston/label-core\");\n const out = await runScriptOrThrow(\n `@(Get-PrintJob -PrinterName '${printerName.replace(/'/g, \"''\")}' -ErrorAction SilentlyContinue).Id -join ','`\n );\n return new Set(out.trim().split(\",\").map(Number).filter(n => !isNaN(n)));\n } catch {\n return new Set();\n }\n}\n\n/**\n * Remove the empty job Windows invents when we open the printer's port.\n *\n * Writing directly to a serial port that a print queue is bound to makes the\n * spooler materialise a zero-byte job -- proven with a script that only opens\n * the port and writes an initialise sequence. That job then parks itself in\n * Error and drags the queue down with it, which is what made the queue look\n * broken after every successful direct print.\n *\n * The queue has to stay bound to the port: that binding is what establishes\n * and holds the Bluetooth RFCOMM link. Open the port with the queue pointed\n * elsewhere and the link will not come up at all. So the phantom cannot be\n * prevented, only cleared.\n *\n * Scoped by identity, not by size: only jobs that did not exist before we\n * opened the port are removed. Size is no use as a filter -- the spooler\n * records a copy of the bytes we put on the wire, so these jobs are not empty\n * (1205 and 4373 bytes were observed for two ordinary labels).\n *\n * The residual risk is a real job submitted by another program during the\n * second or so a direct print takes. That window is narrow and the alternative\n * -- leaving the queue permanently in Error after every label -- is worse.\n */\nasync function clearPhantomJobs(printerName: string, before: Set<number>): Promise<void> {\n try {\n const { runScriptOrThrow } = await import(\"@bobfrankston/label-core\");\n const name = printerName.replace(/'/g, \"''\");\n const skip = [...before].join(\",\") || \"-1\";\n /* The spooler creates the job around the time the handle closes, so\n * give it a moment to appear before looking, and a moment to act on\n * the delete before returning -- a job caught mid-print lingers in\n * \"Deleting\" otherwise. */\n await runScriptOrThrow(`\n$ErrorActionPreference = 'SilentlyContinue'\n$before = @(${skip})\nStart-Sleep -Milliseconds 900\nGet-PrintJob -PrinterName '${name}' | Where-Object { $_.Id -notin $before } |\n ForEach-Object { Remove-PrintJob -PrinterName '${name}' -ID $_.Id }\nStart-Sleep -Milliseconds 600\n`);\n } catch { /* cosmetic cleanup; never fail a print over it */ }\n}\n\n/**\n * Refuse `-queue` when the printer's Windows queue points at a discard port.\n *\n * Repointing a queue away from the printer's real port is how we stop the\n * spooler from creating a phantom job every time we open that port. The cost\n * is that the queue no longer goes anywhere, so `-queue` must fail loudly\n * rather than cheerfully reporting a label that was never printed.\n */\nasync function refuseDiscardQueue(printerName: string): Promise<void> {\n const name = printerName || getDefaultPrinter();\n if (!name) return;\n const { listPrinters: coreListPrinters } = await import(\"@bobfrankston/label-core\");\n const info = (await coreListPrinters(/brother|^pt-|^ql-/i)).find(p => p.name === name);\n const portName = (info?.portName ?? \"\").replace(/:$/, \"\");\n if (!DISCARD_PORTS.test(portName)) return;\n throw new UserError(\n `${name}'s Windows queue points at \"${info.portName}\", which discards everything sent to it — ` +\n `-queue would report success and print nothing. Drop -queue to print directly, ` +\n `or repoint the queue at the printer's port with: Set-Printer -Name \"${name}\" -PortName \"COMn:\"`\n );\n}\n\n/**\n * Find the serial port to write a P-touch label to.\n *\n * The printer queue's PortName is the obvious source but it goes stale:\n * Windows reassigns a Bluetooth printer's outgoing COM number when it\n * re-pairs (the PT-D610BT here was installed on COM8 and came back on COM10),\n * and the queue keeps pointing at the old one. Worse, the abandoned number is\n * often still a valid *incoming* Bluetooth port with nothing behind it, so the\n * stale queue looks openable and simply swallows the job.\n *\n * So: ask Bluetooth which port actually belongs to this printer, and fall back\n * to the queue's port only when no Bluetooth match exists (a genuinely wired\n * serial printer). Returns null when neither yields a COM port.\n */\nasync function resolvePtPort(printerName: string): Promise<{ port: string; source: string }> {\n const { listPrinters: coreListPrinters, runScriptOrThrow } =\n await import(\"@bobfrankston/label-core\");\n\n /* Bluetooth SPP ports carry the remote device's address in their instance\n * id; BTHPORT maps that address to the advertised device name, which\n * contains the model (e.g. \"PT-D610BT5465\"). Match on the model token. */\n const model = /PT-([A-Z0-9]+)/i.exec(printerName)?.[1];\n if (model) {\n const script = [\n \"$ErrorActionPreference = 'SilentlyContinue'\",\n \"Get-PnpDevice -Class Ports -PresentOnly | Where-Object { $_.FriendlyName -match 'Bluetooth' } | ForEach-Object {\",\n \" if ($_.InstanceId -match '&0&([0-9A-Fa-f]{12})_') {\",\n \" $addr = $matches[1].ToLower()\",\n \" $raw = (Get-ItemProperty \\\"HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Services\\\\BTHPORT\\\\Parameters\\\\Devices\\\\$addr\\\").Name\",\n \" if ($raw -and $_.FriendlyName -match '\\\\((COM\\\\d+)\\\\)') {\",\n \" $com = $matches[1]\",\n \" $name = [System.Text.Encoding]::ASCII.GetString($raw).Trim([char]0)\",\n \" Write-Output \\\"$com=$name\\\"\",\n \" }\",\n \" }\",\n \"}\",\n ].join(\"\\n\");\n try {\n const out = (await runScriptOrThrow(script)).trim();\n for (const line of out.split(/\\r?\\n/)) {\n const eq = line.indexOf(\"=\");\n if (eq < 0) continue;\n const com = line.slice(0, eq).trim();\n const name = line.slice(eq + 1).trim();\n const squashed = name.replace(/[^A-Za-z0-9]/g, \"\").toUpperCase();\n if (com && squashed.includes(model.toUpperCase())) {\n return { port: com, source: `Bluetooth device ${name}` };\n }\n }\n } catch { /* fall through to the queue's port */ }\n }\n\n const info = (await coreListPrinters(/brother|^pt-/i)).find(p => p.name === printerName);\n const m = /^(COM\\d+):?$/i.exec(info?.portName ?? \"\");\n if (m) return { port: m[1], source: `printer queue port ${info.portName}` };\n return null;\n}\n\nfunction classifyInput(input: string, opts: Record<string, string | boolean>): Partial<CorePrintOptions> {\n if (opts.text) return { text: input };\n if (opts.html) return { htmlPath: path.resolve(input) };\n if (opts.image) return { imagePath: path.resolve(input) };\n\n const lower = input.toLowerCase();\n if (lower.endsWith(\".html\") || lower.endsWith(\".htm\")) return { htmlPath: path.resolve(input) };\n if (lower.endsWith(\".txt\")) return { textFile: path.resolve(input) };\n if (/\\.(png|jpg|jpeg|bmp|gif)$/i.test(lower)) return { imagePath: path.resolve(input) };\n if (fs.existsSync(input)) {\n const ext = path.extname(lower);\n if (ext === \".html\" || ext === \".htm\") return { htmlPath: path.resolve(input) };\n return { textFile: path.resolve(input) };\n }\n return { text: input };\n}\n\nfunction makeWaitCallback() {\n let lastReport = -Infinity;\n return (status: PrinterStatus, elapsedMs: number) => {\n const secs = Math.floor(elapsedMs / 1000);\n // Non-TTY (redirected output) can't rewrite in place; report sparsely.\n if (!process.stderr.isTTY) {\n if (secs - lastReport < 30) return;\n lastReport = secs;\n }\n statusLine.update(`[brother-print] waiting for ${status.name} (${status.statusText}${status.error ? \", \" + status.error : \"\"}); ${secs}s`);\n };\n}\n\nmain();\n"]}