@bobfrankston/brother-label 1.1.8 → 1.1.10

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
@@ -6,6 +6,7 @@
6
6
  import * as fs from "fs";
7
7
  import * as os from "os";
8
8
  import * as path from "path";
9
+ import * as dns from "dns/promises";
9
10
  import { preprocessSingleQuotes, parseArgs, } from "@bobfrankston/label-core";
10
11
  import { print, render, renderSegments, printSegments, getConfig, setConfig, getConfigPath, listPrinters, detectTapeSize, brotherPrinter, } from "./api.js";
11
12
  const VERSION = "1.1.0";
@@ -26,6 +27,8 @@ const VALUED = [
26
27
  { names: ["-s", "-space"], key: "space" },
27
28
  { names: ["-timeout"], key: "timeout" },
28
29
  { names: ["-interval"], key: "interval" },
30
+ { names: ["-ql"], key: "ql" },
31
+ { names: ["-ql-media"], key: "qlMedia" },
29
32
  ];
30
33
  const BOOLEAN = [
31
34
  { names: ["-w", "-html"], key: "html" },
@@ -34,6 +37,7 @@ const BOOLEAN = [
34
37
  { names: ["-c", "-clip"], key: "clip" },
35
38
  { names: ["-no-wait", "-nowait"], key: "nowait" },
36
39
  { names: ["-mdns"], key: "mdns" },
40
+ { names: ["-vb", "-verbose"], key: "verbose" },
37
41
  { names: ["-help", "-h", "-?"], key: "help" },
38
42
  { names: ["-version", "-v"], key: "version" },
39
43
  ];
@@ -70,6 +74,11 @@ Options:
70
74
  -timeout <secs> Max wait time when printer is offline
71
75
  -interval <secs> Polling interval while waiting (default 2)
72
76
  -mdns With "list": also discover network printers via mDNS
77
+ -ql <host> Print to a Brother QL series printer over TCP/9100
78
+ (bypasses Windows queue; e.g. -ql ql720 or -ql 1.2.3.4)
79
+ -ql-media <id> QL media id (e.g. 271=DK-11201 29×90mm, 259=DK-22205 62mm)
80
+ Required when the printer doesn't respond to status
81
+ -vb, -verbose Print extra QL diagnostic messages (status, media source)
73
82
  -help Show this help
74
83
  -version Show version`);
75
84
  }
@@ -103,6 +112,14 @@ async function main() {
103
112
  try {
104
113
  if (typeof parsed.opts.printer === "string") {
105
114
  parsed.opts.printer = await resolvePrinter(parsed.opts.printer);
115
+ /* Auto-route QL series through the QL TCP path. The XPS / CustomMediaSize
116
+ * pipeline is P-touch-only; sending it to a QL queue produces an XPS
117
+ * error. If the user already passed -ql explicitly, leave it alone. */
118
+ if (!parsed.opts.ql && isQLPrinter(parsed.opts.printer)) {
119
+ const host = await resolveQLHost(parsed.opts.printer);
120
+ if (host)
121
+ parsed.opts.ql = host;
122
+ }
106
123
  }
107
124
  switch (parsed.command) {
108
125
  case "list":
@@ -126,6 +143,120 @@ async function main() {
126
143
  process.exit(1);
127
144
  }
128
145
  }
146
+ function isQLPrinter(name) {
147
+ return /\bQL-/i.test(name);
148
+ }
149
+ /**
150
+ * Look up the TCP host for a QL printer's installed Windows queue. Pulls the
151
+ * port name via label-core, then asks PowerShell for that port's
152
+ * PrinterHostAddress. Returns undefined if the port isn't a TCP/IP port (e.g.
153
+ * the QL-820NWB's BRWxxxx Bluetooth port has no host address).
154
+ */
155
+ async function resolveQLHost(printerName) {
156
+ const { listPrinters: coreListPrinters, runScriptOrThrow } = await import("@bobfrankston/label-core");
157
+ const all = await coreListPrinters(/brother|^pt-|^ql-/i);
158
+ const info = all.find(p => p.name === printerName);
159
+ if (!info?.portName)
160
+ return undefined;
161
+ const port = info.portName.replace(/'/g, "''");
162
+ const script = `
163
+ $ErrorActionPreference = 'SilentlyContinue'
164
+ $p = Get-PrinterPort -Name '${port}'
165
+ if ($p -and $p.PrinterHostAddress) { Write-Output $p.PrinterHostAddress }
166
+ `;
167
+ try {
168
+ const out = (await runScriptOrThrow(script)).trim();
169
+ if (!out)
170
+ return undefined;
171
+ return await resolvableHost(out);
172
+ }
173
+ catch {
174
+ return undefined;
175
+ }
176
+ }
177
+ /**
178
+ * Brother's installer often writes a bare NetBIOS-style hostname (BRWxxxx)
179
+ * as the port's PrinterHostAddress, which won't resolve in environments where
180
+ * the DNS suffix isn't auto-appended. Resolution tiers, in order:
181
+ * 1. as-is via the OS resolver
182
+ * 2. <host>.<suffix> for every DNS suffix the OS knows about (global search
183
+ * list, per-connection suffix, computer domain) — covers the case where
184
+ * the user pings as FQDN manually because Windows isn't auto-appending
185
+ * 3. <host>.local via the OS resolver (Windows 10 1803+ native mDNS)
186
+ * 4. multicast mDNS query directly (bypasses OS resolver — works even when
187
+ * Windows .local resolution is disabled, common in AD/domain environments)
188
+ */
189
+ async function resolvableHost(host) {
190
+ if (/^\d{1,3}(\.\d{1,3}){3}$/.test(host))
191
+ return host;
192
+ try {
193
+ await dns.lookup(host);
194
+ return host;
195
+ }
196
+ catch { }
197
+ if (!host.includes(".")) {
198
+ const suffixes = await getDnsSuffixes();
199
+ const { default_fqdn } = await import("@bobfrankston/miscinfo");
200
+ if (default_fqdn && !suffixes.includes(default_fqdn.toLowerCase())) {
201
+ suffixes.push(default_fqdn.toLowerCase());
202
+ }
203
+ for (const suffix of suffixes) {
204
+ const candidate = `${host}.${suffix}`;
205
+ try {
206
+ await dns.lookup(candidate);
207
+ return candidate;
208
+ }
209
+ catch { }
210
+ }
211
+ }
212
+ const mdnsName = host.includes(".") ? host : host + ".local";
213
+ try {
214
+ await dns.lookup(mdnsName);
215
+ return mdnsName;
216
+ }
217
+ catch { }
218
+ try {
219
+ const { discoverPdlPrinters } = await import("./mdns.js");
220
+ const printers = await discoverPdlPrinters(2500);
221
+ const target = host.toLowerCase();
222
+ const hit = printers.find(p => {
223
+ const h = p.hostname.toLowerCase().replace(/\.$/, "");
224
+ return h === target || h === target + ".local" || h.startsWith(target + ".");
225
+ });
226
+ if (hit && hit.addresses.length > 0)
227
+ return hit.addresses[0];
228
+ }
229
+ catch { }
230
+ return host;
231
+ }
232
+ let dnsSuffixCache;
233
+ /**
234
+ * Read every DNS suffix the system knows about: the global SuffixSearchList,
235
+ * each adapter's ConnectionSpecificSuffix, and the computer's AD/workgroup
236
+ * domain. Cached per-process. Returns lowercased, de-duplicated, in priority
237
+ * order (search list first since that's what the user explicitly configured).
238
+ */
239
+ async function getDnsSuffixes() {
240
+ if (dnsSuffixCache)
241
+ return dnsSuffixCache;
242
+ const { runScriptOrThrow } = await import("@bobfrankston/label-core");
243
+ const script = `
244
+ $ErrorActionPreference = 'SilentlyContinue'
245
+ $out = @()
246
+ $out += (Get-DnsClientGlobalSetting).SuffixSearchList
247
+ $out += Get-DnsClient | Select-Object -ExpandProperty ConnectionSpecificSuffix
248
+ $out += (Get-CimInstance Win32_ComputerSystem).Domain
249
+ $out | Where-Object { $_ -and $_ -ne 'WORKGROUP' } | ForEach-Object { $_.ToLower() } | Select-Object -Unique
250
+ `;
251
+ try {
252
+ const out = await runScriptOrThrow(script);
253
+ dnsSuffixCache = out.split(/\r?\n/).map(s => s.trim()).filter(Boolean);
254
+ }
255
+ catch {
256
+ dnsSuffixCache = [];
257
+ }
258
+ return dnsSuffixCache;
259
+ }
129
260
  /**
130
261
  * Resolve a -p value to an installed Windows queue name. Accepts:
131
262
  * #N 1-based index into the list shown by `brother-label list`
@@ -315,6 +446,48 @@ function shortenPort(portName) {
315
446
  return hostMatch[1];
316
447
  return portName;
317
448
  }
449
+ /**
450
+ * Show details for a single resolved printer: name, port, driver, online
451
+ * status, and the loaded media. For QL printers (auto-detected via the QL
452
+ * TCP path) the media is read from the Windows driver's print ticket; for
453
+ * PT printers it's read by detectTapeSize the same way.
454
+ */
455
+ async function cmdPrinterInfo(printerName, qlHost) {
456
+ const { listPrinters: coreListPrinters } = await import("@bobfrankston/label-core");
457
+ const all = await coreListPrinters(/brother|^pt-|^ql-/i);
458
+ const info = all.find(p => p.name === printerName);
459
+ console.log(`Printer: ${printerName}`);
460
+ if (info?.portName) {
461
+ console.log(`Port: ${info.portName}`);
462
+ }
463
+ if (info?.driverName) {
464
+ console.log(`Driver: ${info.driverName}`);
465
+ }
466
+ try {
467
+ const s = await brotherPrinter.getStatus(printerName);
468
+ const statusStr = s.online ? "online" : `offline (${s.statusText}${s.error ? ", " + s.error : ""})`;
469
+ console.log(`Status: ${statusStr}`);
470
+ }
471
+ catch (e) {
472
+ console.log(`Status: error: ${e.message}`);
473
+ }
474
+ if (qlHost) {
475
+ console.log(`QL host: ${qlHost} (TCP/9100)`);
476
+ const { detectQLMediaFromWindows } = await import("./ql.js");
477
+ const media = await detectQLMediaFromWindows(printerName);
478
+ if (media) {
479
+ console.log(`Media: ${media.name} (id ${media.id}, ${media.widthMm}mm${media.heightMm ? `×${media.heightMm}mm` : ", continuous"})`);
480
+ console.log(` printArea ${media.printAreaDots} dots${media.dieCutMaskedAreaDots ? `, dieCut ${media.dieCutMaskedAreaDots} dots` : ""}`);
481
+ }
482
+ else {
483
+ console.log(`Media: (not detected from Windows driver — pass -ql-media <id>)`);
484
+ }
485
+ }
486
+ else {
487
+ const tape = await detectTapeSize(printerName);
488
+ console.log(`Loaded tape: ${tape ? tape + "mm" : "(not detected)"}`);
489
+ }
490
+ }
318
491
  async function cmdStatus(opts) {
319
492
  const name = opts.printer || undefined;
320
493
  const s = await brotherPrinter.getStatus(name);
@@ -380,6 +553,8 @@ async function cmdPrint(opts, segments, inputs) {
380
553
  onWaiting: makeWaitCallback(),
381
554
  log: (msg) => console.log(msg),
382
555
  };
556
+ const qlHost = typeof opts.ql === "string" ? opts.ql : undefined;
557
+ const qlMediaId = typeof opts.qlMedia === "string" ? parseInt(opts.qlMedia, 10) : undefined;
383
558
  // Multi-segment mode: explicit -text/-qr (>=1 segment), with positional joined in
384
559
  if (segments.length > 1 || (segments.length === 1 && inputs.length === 0)) {
385
560
  const segOpts = {
@@ -393,6 +568,12 @@ async function cmdPrint(opts, segments, inputs) {
393
568
  fs.writeFileSync(opts.output, buffer);
394
569
  console.log(`Saved to ${opts.output}`);
395
570
  }
571
+ else if (qlHost) {
572
+ const buffer = await renderSegments(segments, tape, opts.height, opts.space);
573
+ const { printPngToQL } = await import("./ql.js");
574
+ await printPngToQL(qlHost, buffer, qlMediaId, opts.printer, !!opts.verbose);
575
+ console.log(`Printed ${segments.length} segment(s) to QL @ ${qlHost}`);
576
+ }
396
577
  else {
397
578
  await printSegments(segments, segOpts);
398
579
  console.log(`Printed ${segments.length} segment(s) on ${tape}mm tape`);
@@ -413,6 +594,10 @@ async function cmdPrint(opts, segments, inputs) {
413
594
  Object.assign(printOpts, classifyInput(inputs[0], opts));
414
595
  }
415
596
  else if (inputs.length === 0 && segments.length === 0) {
597
+ if (opts.printer) {
598
+ await cmdPrinterInfo(opts.printer, qlHost);
599
+ return;
600
+ }
416
601
  showHelp();
417
602
  return;
418
603
  }
@@ -422,6 +607,13 @@ async function cmdPrint(opts, segments, inputs) {
422
607
  console.log(`Saved to ${opts.output}`);
423
608
  return;
424
609
  }
610
+ if (qlHost) {
611
+ const buffer = await render(printOpts);
612
+ const { printPngToQL } = await import("./ql.js");
613
+ await printPngToQL(qlHost, buffer, qlMediaId, opts.printer, !!opts.verbose);
614
+ console.log(`Printed to QL @ ${qlHost}`);
615
+ return;
616
+ }
425
617
  await print(printOpts);
426
618
  console.log(`Printed on ${tape}mm tape`);
427
619
  }
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 {\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 detectTapeSize,\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 Error(`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];\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: [\"-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\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 -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\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 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 }\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 if (e?.isUserError) {\n console.error(`Error: ${e.message}`);\n process.exit(1);\n }\n reportError(e);\n process.exit(1);\n }\n}\n\n/**\n * Resolve a -p value to an installed Windows queue name. Accepts:\n * #N 1-based index into the list shown by `brother-label list`\n * <exact> Full queue name (case-sensitive match shortcut)\n * <substr> Case-insensitive substring against name or port (e.g. \"ql820\",\n * \"172.20.1.165\", \"BRW4CD577B59B6A\"). Errors if ambiguous.\n */\nasync function resolvePrinter(value: string): Promise<string> {\n const { listPrinters: coreListPrinters } = await import(\"@bobfrankston/label-core\");\n const all = await coreListPrinters(/brother|^pt-|^ql-/i);\n const sorted = [...all].sort((a, b) => a.name.localeCompare(b.name));\n\n if (sorted.length === 0) {\n throw new UserError(`No Brother printers installed. Run 'brother-label list' to verify.`);\n }\n\n const idx = value.match(/^#(\\d+)$/);\n if (idx) {\n const n = parseInt(idx[1], 10);\n if (n < 1 || n > sorted.length) {\n throw new UserError(`-p ${value}: only ${sorted.length} printer(s) installed (use 'brother-label list').`);\n }\n return sorted[n - 1].name;\n }\n\n const exact = sorted.find(p => p.name === value);\n if (exact) return exact.name;\n\n const lower = value.toLowerCase();\n const norm = (s: string) => s.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n const target = norm(value);\n const matches = sorted.filter(p => {\n const name = p.name.toLowerCase();\n const port = (p.portName || \"\").toLowerCase();\n if (name.includes(lower) || port.includes(lower)) return true;\n // Normalized fallback: \"ql820\" matches \"Brother QL-820NWB\"\n return norm(p.name).includes(target) || norm(p.portName || \"\").includes(target);\n });\n if (matches.length === 1) return matches[0].name;\n if (matches.length === 0) {\n throw new UserError(`No printer matches '${value}'. Run 'brother-label list' to see available printers.`);\n }\n const names = matches.map(p => p.name).join(\", \");\n throw new UserError(`'${value}' is ambiguous — matches: ${names}`);\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 try {\n const s = await brotherPrinter.getStatus(p.name);\n statusStr = s.online ? \"online\" : `offline (${s.statusText}${s.error ? \", \" + s.error : \"\"})`;\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 }\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\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 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 const explicit = opts.tape ? parseTape(opts.tape as string) : null;\n const detected = await detectTapeSize(opts.printer as string | undefined);\n if (explicit) {\n if (detected && detected !== explicit) {\n console.warn(`Warning: -tape ${explicit}mm specified but printer reports ${detected}mm tape loaded`);\n }\n return explicit;\n }\n if (detected) return detected;\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) => console.log(msg),\n };\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 console.log(`Saved to ${opts.output}`);\n } else {\n await printSegments(segments, segOpts);\n console.log(`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 showHelp();\n return;\n }\n\n if (opts.output) {\n const buffer = await render(printOpts);\n fs.writeFileSync(opts.output as string, buffer);\n console.log(`Saved to ${opts.output}`);\n return;\n }\n await print(printOpts);\n console.log(`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 = 0;\n return (status: PrinterStatus, elapsedMs: number, alternatives: PrinterStatus[]) => {\n const secs = Math.floor(elapsedMs / 1000);\n if (secs - lastReport < 5) return;\n lastReport = secs;\n const altStr = alternatives.length > 0\n ? ` (online alternatives: ${alternatives.map(a => a.name).join(\", \")})`\n : \"\";\n console.log(`[brother-print] still waiting for ${status.name} (${status.statusText}${status.error ? \", \" + status.error : \"\"}); ${secs}s elapsed${altStr}`);\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 detectTapeSize,\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 Error(`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\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\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 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 if (e?.isUserError) {\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 * Resolve a -p value to an installed Windows queue name. Accepts:\n * #N 1-based index into the list shown by `brother-label list`\n * <exact> Full queue name (case-sensitive match shortcut)\n * <substr> Case-insensitive substring against name or port (e.g. \"ql820\",\n * \"172.20.1.165\", \"BRW4CD577B59B6A\"). Errors if ambiguous.\n */\nasync function resolvePrinter(value: string): Promise<string> {\n const { listPrinters: coreListPrinters } = await import(\"@bobfrankston/label-core\");\n const all = await coreListPrinters(/brother|^pt-|^ql-/i);\n const sorted = [...all].sort((a, b) => a.name.localeCompare(b.name));\n\n if (sorted.length === 0) {\n throw new UserError(`No Brother printers installed. Run 'brother-label list' to verify.`);\n }\n\n const idx = value.match(/^#(\\d+)$/);\n if (idx) {\n const n = parseInt(idx[1], 10);\n if (n < 1 || n > sorted.length) {\n throw new UserError(`-p ${value}: only ${sorted.length} printer(s) installed (use 'brother-label list').`);\n }\n return sorted[n - 1].name;\n }\n\n const exact = sorted.find(p => p.name === value);\n if (exact) return exact.name;\n\n const lower = value.toLowerCase();\n const norm = (s: string) => s.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n const target = norm(value);\n const matches = sorted.filter(p => {\n const name = p.name.toLowerCase();\n const port = (p.portName || \"\").toLowerCase();\n if (name.includes(lower) || port.includes(lower)) return true;\n // Normalized fallback: \"ql820\" matches \"Brother QL-820NWB\"\n return norm(p.name).includes(target) || norm(p.portName || \"\").includes(target);\n });\n if (matches.length === 1) return matches[0].name;\n if (matches.length === 0) {\n throw new UserError(`No printer matches '${value}'. Run 'brother-label list' to see available printers.`);\n }\n const names = matches.map(p => p.name).join(\", \");\n throw new UserError(`'${value}' is ambiguous — matches: ${names}`);\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 try {\n const s = await brotherPrinter.getStatus(p.name);\n statusStr = s.online ? \"online\" : `offline (${s.statusText}${s.error ? \", \" + s.error : \"\"})`;\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 }\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 it's read by detectTapeSize the same way.\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 } 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 tape = await detectTapeSize(printerName);\n console.log(`Loaded tape: ${tape ? tape + \"mm\" : \"(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 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 const explicit = opts.tape ? parseTape(opts.tape as string) : null;\n const detected = await detectTapeSize(opts.printer as string | undefined);\n if (explicit) {\n if (detected && detected !== explicit) {\n console.warn(`Warning: -tape ${explicit}mm specified but printer reports ${detected}mm tape loaded`);\n }\n return explicit;\n }\n if (detected) return detected;\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) => console.log(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 console.log(`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 console.log(`Printed ${segments.length} segment(s) to QL @ ${qlHost}`);\n } else {\n await printSegments(segments, segOpts);\n console.log(`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 console.log(`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 console.log(`Printed to QL @ ${qlHost}`);\n return;\n }\n await print(printOpts);\n console.log(`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 = 0;\n return (status: PrinterStatus, elapsedMs: number, alternatives: PrinterStatus[]) => {\n const secs = Math.floor(elapsedMs / 1000);\n if (secs - lastReport < 5) return;\n lastReport = secs;\n const altStr = alternatives.length > 0\n ? ` (online alternatives: ${alternatives.map(a => a.name).join(\", \")})`\n : \"\";\n console.log(`[brother-print] still waiting for ${status.name} (${status.statusText}${status.error ? \", \" + status.error : \"\"}); ${secs}s elapsed${altStr}`);\n };\n}\n\nmain();\n"]}