@thermal-label/brother-ql-node 0.0.1 → 0.2.1

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.
Files changed (65) hide show
  1. package/dist/__tests__/discovery.test.js +141 -68
  2. package/dist/__tests__/discovery.test.js.map +1 -1
  3. package/dist/__tests__/integration/print.test.d.ts +2 -0
  4. package/dist/__tests__/integration/print.test.d.ts.map +1 -0
  5. package/dist/__tests__/integration/print.test.js +71 -0
  6. package/dist/__tests__/integration/print.test.js.map +1 -0
  7. package/dist/__tests__/printer.test.js +137 -208
  8. package/dist/__tests__/printer.test.js.map +1 -1
  9. package/dist/discovery.d.ts +39 -4
  10. package/dist/discovery.d.ts.map +1 -1
  11. package/dist/discovery.js +88 -15
  12. package/dist/discovery.js.map +1 -1
  13. package/dist/index.d.ts +2 -8
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2 -6
  16. package/dist/index.js.map +1 -1
  17. package/dist/printer.d.ts +32 -15
  18. package/dist/printer.d.ts.map +1 -1
  19. package/dist/printer.js +70 -149
  20. package/dist/printer.js.map +1 -1
  21. package/package.json +6 -4
  22. package/dist/__tests__/errors.test.d.ts +0 -2
  23. package/dist/__tests__/errors.test.d.ts.map +0 -1
  24. package/dist/__tests__/errors.test.js +0 -20
  25. package/dist/__tests__/errors.test.js.map +0 -1
  26. package/dist/__tests__/integration/print-image.test.d.ts +0 -2
  27. package/dist/__tests__/integration/print-image.test.d.ts.map +0 -1
  28. package/dist/__tests__/integration/print-image.test.js +0 -22
  29. package/dist/__tests__/integration/print-image.test.js.map +0 -1
  30. package/dist/__tests__/integration/print-text.test.d.ts +0 -2
  31. package/dist/__tests__/integration/print-text.test.d.ts.map +0 -1
  32. package/dist/__tests__/integration/print-text.test.js +0 -25
  33. package/dist/__tests__/integration/print-text.test.js.map +0 -1
  34. package/dist/__tests__/integration/print-two-color.test.d.ts +0 -2
  35. package/dist/__tests__/integration/print-two-color.test.d.ts.map +0 -1
  36. package/dist/__tests__/integration/print-two-color.test.js +0 -28
  37. package/dist/__tests__/integration/print-two-color.test.js.map +0 -1
  38. package/dist/__tests__/integration/tcp.test.d.ts +0 -2
  39. package/dist/__tests__/integration/tcp.test.d.ts.map +0 -1
  40. package/dist/__tests__/integration/tcp.test.js +0 -20
  41. package/dist/__tests__/integration/tcp.test.js.map +0 -1
  42. package/dist/__tests__/tcp-transport.test.d.ts +0 -2
  43. package/dist/__tests__/tcp-transport.test.d.ts.map +0 -1
  44. package/dist/__tests__/tcp-transport.test.js +0 -115
  45. package/dist/__tests__/tcp-transport.test.js.map +0 -1
  46. package/dist/__tests__/usb-transport.test.d.ts +0 -2
  47. package/dist/__tests__/usb-transport.test.d.ts.map +0 -1
  48. package/dist/__tests__/usb-transport.test.js +0 -99
  49. package/dist/__tests__/usb-transport.test.js.map +0 -1
  50. package/dist/errors.d.ts +0 -8
  51. package/dist/errors.d.ts.map +0 -1
  52. package/dist/errors.js +0 -15
  53. package/dist/errors.js.map +0 -1
  54. package/dist/status.d.ts +0 -2
  55. package/dist/status.d.ts.map +0 -1
  56. package/dist/status.js +0 -2
  57. package/dist/status.js.map +0 -1
  58. package/dist/transport.d.ts +0 -32
  59. package/dist/transport.d.ts.map +0 -1
  60. package/dist/transport.js +0 -120
  61. package/dist/transport.js.map +0 -1
  62. package/dist/types.d.ts +0 -13
  63. package/dist/types.d.ts.map +0 -1
  64. package/dist/types.js +0 -2
  65. package/dist/types.js.map +0 -1
@@ -1,216 +1,145 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { createBitmap } from '@mbtech-nl/bitmap';
3
- import { MEDIA, DEVICES } from '@thermal-label/brother-ql-core';
4
- const mockWrite = vi.fn().mockImplementation(() => Promise.resolve());
5
- const mockRead = vi.fn().mockResolvedValue(new Uint8Array(32).fill(0));
6
- const mockClose = vi.fn().mockImplementation(() => Promise.resolve());
7
- const mockTransport = {
8
- write: mockWrite,
9
- read: mockRead,
10
- close: mockClose,
11
- };
12
- vi.mock('../transport.js', () => ({
13
- UsbTransport: {
14
- open: vi.fn().mockImplementation(() => Promise.resolve(mockTransport)),
15
- },
16
- TcpTransport: {
17
- connect: vi.fn().mockImplementation(() => Promise.resolve(mockTransport)),
18
- },
19
- }));
20
- vi.mock('../discovery.js', () => ({
21
- listPrinters: vi.fn(() => [
22
- {
23
- device: DEVICES.QL_820NWB,
24
- serialNumber: undefined,
25
- path: '1.5',
26
- transport: 'usb',
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { MediaNotSpecifiedError } from '@thermal-label/contracts';
3
+ import { DEVICES, MEDIA } from '@thermal-label/brother-ql-core';
4
+ import { BrotherQLPrinter } from '../printer.js';
5
+ function makeTransport(statusBytes = new Uint8Array(32)) {
6
+ const written = [];
7
+ const transport = {
8
+ get connected() {
9
+ return true;
27
10
  },
28
- ]),
29
- DEVICES,
30
- }));
31
- const { mockLoadImage, mockCreateCanvas } = vi.hoisted(() => ({
32
- mockLoadImage: vi.fn(),
33
- mockCreateCanvas: vi.fn(),
34
- }));
35
- vi.mock('@napi-rs/canvas', () => ({
36
- loadImage: mockLoadImage,
37
- createCanvas: mockCreateCanvas,
38
- }));
39
- beforeEach(() => {
40
- mockWrite.mockClear().mockImplementation(() => Promise.resolve());
41
- mockRead.mockClear().mockResolvedValue(new Uint8Array(32).fill(0));
42
- mockClose.mockClear().mockImplementation(() => Promise.resolve());
43
- const mockContext = {
44
- drawImage: vi.fn(),
45
- getImageData: vi.fn().mockReturnValue({ data: new Uint8Array(400) }),
11
+ write: vi.fn((data) => {
12
+ written.push(new Uint8Array(data));
13
+ return Promise.resolve();
14
+ }),
15
+ read: vi.fn(() => Promise.resolve(statusBytes)),
16
+ close: vi.fn(() => Promise.resolve()),
46
17
  };
47
- mockCreateCanvas
48
- .mockReset()
49
- .mockReturnValue({ getContext: vi.fn().mockReturnValue(mockContext) });
50
- mockLoadImage.mockReset().mockResolvedValue({ width: 10, height: 10 });
51
- });
18
+ return { transport, written };
19
+ }
20
+ function solidRgba(width, height) {
21
+ return {
22
+ width,
23
+ height,
24
+ data: new Uint8Array(width * height * 4).fill(0),
25
+ };
26
+ }
27
+ function redRgba(width, height) {
28
+ const data = new Uint8Array(width * height * 4);
29
+ for (let i = 0; i < data.length; i += 4) {
30
+ data[i] = 255;
31
+ data[i + 1] = 0;
32
+ data[i + 2] = 0;
33
+ data[i + 3] = 255;
34
+ }
35
+ return { width, height, data };
36
+ }
52
37
  describe('BrotherQLPrinter', () => {
53
- it('print() writes the encoded byte stream via transport', async () => {
54
- const { BrotherQLPrinter } = await import('../printer.js');
55
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
56
- const bitmap = createBitmap(720, 10);
57
- const media = MEDIA[259];
58
- await printer.print([{ bitmap, media }]);
59
- expect(mockWrite).toHaveBeenCalledOnce();
60
- const written = mockWrite.mock.calls[0][0];
61
- // Starts with ESC i a 01 (raster mode), then 200-byte invalidate
62
- expect(written[0]).toBe(0x1b);
63
- expect(written[1]).toBe(0x69);
64
- expect(written[2]).toBe(0x61);
65
- expect(written.at(-1)).toBe(0x1a);
66
- });
67
- it('getStatus() sends status request and parses 32-byte response', async () => {
68
- const statusBytes = new Uint8Array(32);
69
- statusBytes[0] = 0x80;
70
- statusBytes[10] = 62;
71
- statusBytes[11] = 0x0a;
72
- mockRead.mockResolvedValueOnce(statusBytes);
73
- const { BrotherQLPrinter } = await import('../printer.js');
74
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
38
+ it('exposes adapter metadata', () => {
39
+ const { transport } = makeTransport();
40
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
41
+ expect(printer.family).toBe('brother-ql');
42
+ expect(printer.model).toBe('QL-820NWB');
43
+ expect(printer.device).toBe(DEVICES.QL_820NWB);
44
+ expect(printer.transportType).toBe('usb');
45
+ expect(printer.connected).toBe(true);
46
+ });
47
+ it('print() throws MediaNotSpecifiedError without media or status', async () => {
48
+ const { transport } = makeTransport();
49
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
50
+ await expect(printer.print(solidRgba(64, 64))).rejects.toBeInstanceOf(MediaNotSpecifiedError);
51
+ });
52
+ it('print() encodes a single-colour job for non-colour-capable media', async () => {
53
+ const { transport, written } = makeTransport();
54
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
55
+ await printer.print(solidRgba(64, 64), MEDIA[259]);
56
+ expect(written.length).toBeGreaterThan(0);
57
+ });
58
+ it('print() uses detected media from a prior getStatus when media is omitted', async () => {
59
+ const bytes = new Uint8Array(32);
60
+ bytes[10] = 62;
61
+ bytes[11] = 0x0a;
62
+ const { transport, written } = makeTransport(bytes);
63
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
64
+ await printer.getStatus();
65
+ const before = written.length;
66
+ await printer.print(solidRgba(64, 64));
67
+ expect(written.length).toBe(before + 1);
68
+ });
69
+ it('print() splits two-colour bitmap when media.colorCapable is true', async () => {
70
+ const { transport, written } = makeTransport();
71
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
72
+ await printer.print(redRgba(64, 64), MEDIA[251]);
73
+ // Two-colour job header includes the expanded-mode byte sequence —
74
+ // just assert a job was emitted; byte-level details are covered by
75
+ // the core protocol tests.
76
+ expect(written.length).toBeGreaterThan(0);
77
+ });
78
+ it('createPreview() returns two planes on colorCapable media', async () => {
79
+ const { transport } = makeTransport();
80
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
81
+ const preview = await printer.createPreview(redRgba(64, 64), { media: MEDIA[251] });
82
+ expect(preview.planes.map(p => p.name)).toEqual(['black', 'red']);
83
+ expect(preview.assumed).toBe(false);
84
+ });
85
+ it('createPreview() returns one plane on non-colorCapable media', async () => {
86
+ const { transport } = makeTransport();
87
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
88
+ const preview = await printer.createPreview(solidRgba(64, 64), { media: MEDIA[259] });
89
+ expect(preview.planes).toHaveLength(1);
90
+ expect(preview.planes[0].name).toBe('black');
91
+ });
92
+ it('createPreview() falls back to DEFAULT_MEDIA with assumed=true', async () => {
93
+ const { transport } = makeTransport();
94
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
95
+ const preview = await printer.createPreview(solidRgba(64, 64));
96
+ expect(preview.assumed).toBe(true);
97
+ expect(preview.media.id).toBe(259);
98
+ });
99
+ it('createPreview() reuses detected media from a prior getStatus', async () => {
100
+ const bytes = new Uint8Array(32);
101
+ bytes[10] = 62;
102
+ bytes[11] = 0x0a;
103
+ const { transport } = makeTransport(bytes);
104
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
105
+ await printer.getStatus();
106
+ const preview = await printer.createPreview(solidRgba(64, 64));
107
+ expect(preview.assumed).toBe(false);
108
+ expect(preview.media.id).toBe(259);
109
+ });
110
+ it('getStatus() polls until 32 bytes arrive and returns BrotherQLStatus', async () => {
111
+ const bytes = new Uint8Array(32);
112
+ bytes[10] = 62;
113
+ bytes[11] = 0x0a;
114
+ const { transport } = makeTransport(bytes);
115
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
75
116
  const status = await printer.getStatus();
76
- expect(mockWrite).toHaveBeenCalledOnce();
77
- const req = mockWrite.mock.calls[0][0];
78
- expect(req[0]).toBe(0x1b);
79
- expect(req[1]).toBe(0x69);
80
- expect(req[2]).toBe(0x53);
81
- expect(status.mediaWidthMm).toBe(62);
82
- expect(status.mediaType).toBe('continuous');
83
- });
84
- it('printTwoColor() throws UnsupportedOperationError on non-two-color device', async () => {
85
- const { BrotherQLPrinter } = await import('../printer.js');
86
- const { UnsupportedOperationError } = await import('../errors.js');
87
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_700, 'usb');
88
- const bitmap = createBitmap(720, 10);
89
- const media = MEDIA[259];
90
- await expect(printer.printTwoColor(bitmap, bitmap, media)).rejects.toThrow(UnsupportedOperationError);
91
- });
92
- it('printTwoColor() succeeds on two-color capable device', async () => {
93
- const { BrotherQLPrinter } = await import('../printer.js');
94
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
95
- const bitmap = createBitmap(720, 10);
96
- const media = MEDIA[259];
97
- await printer.printTwoColor(bitmap, bitmap, media);
98
- expect(mockWrite).toHaveBeenCalledOnce();
99
- });
100
- it('printTwoColor() passes options through to print', async () => {
101
- const { BrotherQLPrinter } = await import('../printer.js');
102
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
103
- const bitmap = createBitmap(720, 10);
104
- await printer.printTwoColor(bitmap, bitmap, MEDIA[259], { autoCut: true });
105
- expect(mockWrite).toHaveBeenCalledOnce();
106
- });
107
- it('printText() renders text and writes via transport', async () => {
108
- const { BrotherQLPrinter } = await import('../printer.js');
109
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
110
- const media = MEDIA[259];
111
- await printer.printText('hello', media);
112
- expect(mockWrite).toHaveBeenCalledOnce();
113
- });
114
- it('printText() forwards invert option', async () => {
115
- const { BrotherQLPrinter } = await import('../printer.js');
116
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
117
- await printer.printText('hi', MEDIA[259], { invert: true });
118
- expect(mockWrite).toHaveBeenCalledOnce();
119
- });
120
- it('printText() passes PageOptions through to print', async () => {
121
- const { BrotherQLPrinter } = await import('../printer.js');
122
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
123
- await printer.printText('hi', MEDIA[259], { autoCut: true });
124
- expect(mockWrite).toHaveBeenCalledOnce();
125
- });
126
- it('printImage() decodes a Buffer and prints', async () => {
127
- const { BrotherQLPrinter } = await import('../printer.js');
128
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
129
- await printer.printImage(Buffer.alloc(100), MEDIA[259]);
130
- expect(mockLoadImage).toHaveBeenCalledOnce();
131
- expect(mockWrite).toHaveBeenCalledOnce();
132
- });
133
- it('printImage() loads an image from a file path', async () => {
134
- const { BrotherQLPrinter } = await import('../printer.js');
135
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
136
- await printer.printImage('/tmp/test.png', MEDIA[259]);
137
- expect(mockLoadImage).toHaveBeenCalledWith('/tmp/test.png');
138
- expect(mockWrite).toHaveBeenCalledOnce();
139
- });
140
- it('printImage() passes through options to renderImage', async () => {
141
- const { BrotherQLPrinter } = await import('../printer.js');
142
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
143
- await printer.printImage(Buffer.alloc(100), MEDIA[259], {
144
- threshold: 100,
145
- dither: true,
146
- invert: true,
147
- rotate: 90,
148
- });
149
- expect(mockWrite).toHaveBeenCalledOnce();
117
+ expect(status.rawBytes.length).toBe(32);
118
+ expect(status.editorLiteMode).toBe(false);
119
+ expect(status.detectedMedia?.id).toBe(259);
150
120
  });
151
- it('printImage() passes PageOptions through to print', async () => {
152
- const { BrotherQLPrinter } = await import('../printer.js');
153
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
154
- await printer.printImage(Buffer.alloc(100), MEDIA[259], { autoCut: true });
155
- expect(mockWrite).toHaveBeenCalledOnce();
156
- });
157
- it('printImage() throws when canvas is unavailable for a buffer', async () => {
158
- mockLoadImage.mockRejectedValueOnce(new Error('module not found'));
159
- const { BrotherQLPrinter } = await import('../printer.js');
160
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
161
- await expect(printer.printImage(Buffer.alloc(10), MEDIA[259])).rejects.toThrow('Cannot decode image buffer');
162
- });
163
- it('printImage() throws when canvas is unavailable for a file path', async () => {
164
- mockLoadImage.mockRejectedValueOnce(new Error('module not found'));
165
- const { BrotherQLPrinter } = await import('../printer.js');
166
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
167
- await expect(printer.printImage('/tmp/test.png', MEDIA[259])).rejects.toThrow('Cannot load image file');
168
- });
169
- it('close() delegates to transport close', async () => {
170
- const { BrotherQLPrinter } = await import('../printer.js');
171
- const printer = new BrotherQLPrinter(mockTransport, DEVICES.QL_820NWB, 'usb');
121
+ it('close() awaits the transport', async () => {
122
+ const { transport } = makeTransport();
123
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
172
124
  await printer.close();
173
- expect(mockClose).toHaveBeenCalledOnce();
174
- });
175
- });
176
- describe('openPrinter', () => {
177
- it('opens the first discovered printer when no options given', async () => {
178
- const { openPrinter } = await import('../printer.js');
179
- const printer = await openPrinter();
180
- expect(printer.device.name).toBe('QL-820NWB');
181
- expect(printer.transport).toBe('usb');
182
- });
183
- it('opens printer by vid and pid when specified', async () => {
184
- const { openPrinter } = await import('../printer.js');
185
- const printer = await openPrinter({ pid: DEVICES.QL_820NWB.pid, vid: DEVICES.QL_820NWB.vid });
186
- expect(printer.device.name).toBe('QL-820NWB');
187
- expect(printer.transport).toBe('usb');
188
- });
189
- it('throws for an unknown pid', async () => {
190
- const { openPrinter } = await import('../printer.js');
191
- await expect(openPrinter({ pid: 0x9999 })).rejects.toThrow('Unknown device');
192
- });
193
- it('throws when no printers are found', async () => {
194
- const { listPrinters } = await import('../discovery.js');
195
- vi.mocked(listPrinters).mockReturnValueOnce([]);
196
- const { openPrinter } = await import('../printer.js');
197
- await expect(openPrinter()).rejects.toThrow('No Brother QL printers found');
198
- });
199
- });
200
- describe('openPrinterTcp', () => {
201
- it('connects via TCP and returns a printer', async () => {
202
- const { openPrinterTcp } = await import('../printer.js');
203
- const printer = await openPrinterTcp('192.168.1.100');
204
- expect(printer.transport).toBe('tcp');
205
- expect(mockWrite).toHaveBeenCalledOnce();
206
- expect(mockRead).toHaveBeenCalledOnce();
207
- });
208
- it('uses custom port when specified', async () => {
209
- const { TcpTransport } = await import('../transport.js');
210
- const { openPrinterTcp } = await import('../printer.js');
211
- await openPrinterTcp('192.168.1.100', 4444);
212
- const connectMock = vi.mocked(TcpTransport).connect;
213
- expect(connectMock).toHaveBeenCalledWith('192.168.1.100', 4444);
214
- });
125
+ // Dodge @typescript-eslint/unbound-method — the point is to verify
126
+ // the mock was called, not to keep a `this`-bound reference.
127
+ // eslint-disable-next-line @typescript-eslint/unbound-method
128
+ expect(vi.mocked(transport.close)).toHaveBeenCalled();
129
+ });
130
+ it('getStatus() throws when the printer never queues a response', async () => {
131
+ // transport.read always returns 0 bytes — mirrors the USB path where
132
+ // the printer hasn't responded yet.
133
+ const transport = {
134
+ get connected() {
135
+ return true;
136
+ },
137
+ write: vi.fn(() => Promise.resolve()),
138
+ read: vi.fn(() => Promise.resolve(new Uint8Array(0))),
139
+ close: vi.fn(() => Promise.resolve()),
140
+ };
141
+ const printer = new BrotherQLPrinter(DEVICES.QL_820NWB, transport, 'usb');
142
+ await expect(printer.getStatus()).rejects.toThrow(/did not respond to status request/);
143
+ }, 10_000);
215
144
  });
216
145
  //# sourceMappingURL=printer.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"printer.test.js","sourceRoot":"","sources":["../../src/__tests__/printer.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"printer.test.js","sourceRoot":"","sources":["../../src/__tests__/printer.test.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,40 @@
1
- import { DEVICES } from '@thermal-label/brother-ql-core';
2
- import { type PrinterInfo } from './types.js';
3
- export declare function listPrinters(): PrinterInfo[];
4
- export { DEVICES };
1
+ import type { DiscoveredPrinter, OpenOptions, PrinterDiscovery } from '@thermal-label/contracts';
2
+ import { BrotherQLPrinter } from './printer.js';
3
+ /**
4
+ * Driver-specific `openPrinter` options.
5
+ *
6
+ * Extends the contracts `OpenOptions` with `path` / `baudRate` for
7
+ * serial (RFCOMM over OS-paired Bluetooth on the QL-820NWB, or any
8
+ * USB-to-serial adapter). Baud rate is forwarded to the OS driver;
9
+ * RFCOMM ignores it, but `serialport` requires a value.
10
+ */
11
+ export interface BrotherQLOpenOptions extends OpenOptions {
12
+ /**
13
+ * Serial device path — e.g. `/dev/rfcomm0` (Linux) or `COM3`
14
+ * (Windows) after pairing the printer via the OS Bluetooth
15
+ * settings. Mutually exclusive with `host` and the USB fields.
16
+ */
17
+ path?: string;
18
+ /** Baud rate override; defaults to 9600. */
19
+ baudRate?: number;
20
+ }
21
+ /**
22
+ * `PrinterDiscovery` implementation for Brother QL printers.
23
+ *
24
+ * `listPrinters()` enumerates USB and skips printers in Editor Lite
25
+ * mass-storage mode (a warning is logged — the user has to switch
26
+ * them out of Editor Lite manually). Network printers open via
27
+ * `openPrinter({ host, port })`; there is no mDNS implementation so
28
+ * `listPrinters()` never surfaces them.
29
+ */
30
+ export declare class BrotherQLDiscovery implements PrinterDiscovery {
31
+ readonly family = "brother-ql";
32
+ listPrinters(): Promise<DiscoveredPrinter[]>;
33
+ openPrinter(options?: BrotherQLOpenOptions): Promise<BrotherQLPrinter>;
34
+ }
35
+ /**
36
+ * Named export discovered by the unified `thermal-label-cli` — the CLI
37
+ * walks installed drivers looking for `mod.discovery`.
38
+ */
39
+ export declare const discovery: BrotherQLDiscovery;
5
40
  //# sourceMappingURL=discovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAiC,MAAM,gCAAgC,CAAC;AACxF,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAI9C,wBAAgB,YAAY,IAAI,WAAW,EAAE,CA8B5C;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjG,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAqB,SAAQ,WAAW;IACvD;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAqDD;;;;;;;;GAQG;AACH,qBAAa,kBAAmB,YAAW,gBAAgB;IACzD,QAAQ,CAAC,MAAM,gBAAgB;IAEzB,YAAY,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAU5C,WAAW,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAqCjF;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,oBAA2B,CAAC"}
package/dist/discovery.js CHANGED
@@ -1,11 +1,19 @@
1
- import usb from 'usb';
2
- import { DEVICES, findDevice, isMassStorageMode } from '@thermal-label/brother-ql-core';
3
- import {} from './types.js';
1
+ import { DEVICES, findDevice, isMassStorageMode, } from '@thermal-label/brother-ql-core';
2
+ import { SerialTransport, TcpTransport, UsbTransport } from '@thermal-label/transport/node';
3
+ import * as usb from 'usb';
4
+ import { BrotherQLPrinter } from './printer.js';
4
5
  const BROTHER_VID = 0x04f9;
5
- export function listPrinters() {
6
+ async function readSerialNumber(device, idx) {
7
+ return new Promise(resolve => {
8
+ device.getStringDescriptor(idx, (err, value) => {
9
+ resolve(err ? undefined : value);
10
+ });
11
+ });
12
+ }
13
+ async function enumerateUsbDevices() {
6
14
  const results = [];
7
- for (const usbDevice of usb.getDeviceList()) {
8
- const desc = usbDevice.deviceDescriptor;
15
+ for (const device of usb.getDeviceList()) {
16
+ const desc = device.deviceDescriptor;
9
17
  if (desc.idVendor !== BROTHER_VID)
10
18
  continue;
11
19
  if (isMassStorageMode(desc.idProduct)) {
@@ -14,18 +22,83 @@ export function listPrinters() {
14
22
  'Hold the Editor Lite button until the LED turns off to switch to printer mode.');
15
23
  continue;
16
24
  }
17
- const device = findDevice(desc.idVendor, desc.idProduct);
18
- if (!device)
25
+ const descriptor = findDevice(desc.idVendor, desc.idProduct);
26
+ if (!descriptor)
19
27
  continue;
20
- const path = `${usbDevice.busNumber.toString()}.${usbDevice.deviceAddress.toString()}`;
21
- results.push({
22
- device,
23
- serialNumber: undefined,
24
- path,
28
+ let serialNumber;
29
+ if (desc.iSerialNumber) {
30
+ device.open();
31
+ try {
32
+ serialNumber = await readSerialNumber(device, desc.iSerialNumber);
33
+ }
34
+ finally {
35
+ device.close();
36
+ }
37
+ }
38
+ results.push({ device, descriptor, serialNumber });
39
+ }
40
+ return results;
41
+ }
42
+ /**
43
+ * `PrinterDiscovery` implementation for Brother QL printers.
44
+ *
45
+ * `listPrinters()` enumerates USB and skips printers in Editor Lite
46
+ * mass-storage mode (a warning is logged — the user has to switch
47
+ * them out of Editor Lite manually). Network printers open via
48
+ * `openPrinter({ host, port })`; there is no mDNS implementation so
49
+ * `listPrinters()` never surfaces them.
50
+ */
51
+ export class BrotherQLDiscovery {
52
+ family = 'brother-ql';
53
+ async listPrinters() {
54
+ const found = await enumerateUsbDevices();
55
+ return found.map(({ device, descriptor, serialNumber }) => ({
56
+ device: descriptor,
57
+ ...(serialNumber === undefined ? {} : { serialNumber }),
25
58
  transport: 'usb',
59
+ connectionId: `${String(device.busNumber)}.${String(device.deviceAddress)}`,
60
+ }));
61
+ }
62
+ async openPrinter(options = {}) {
63
+ if (options.path !== undefined) {
64
+ const transport = await SerialTransport.open(options.path, options.baudRate);
65
+ // Serial (typically RFCOMM) carries no identifying metadata —
66
+ // fall back to the most capable descriptor with a serial
67
+ // transport tag. `getStatus()` still returns accurate
68
+ // detectedMedia regardless of which descriptor we attach.
69
+ const descriptor = Object.values(DEVICES).find(d => d.transports.includes('serial'));
70
+ /* v8 ignore next -- DEVICES always has QL_820NWB with 'serial' in transports */
71
+ if (!descriptor)
72
+ throw new Error('No serial-capable Brother QL descriptor found.');
73
+ return new BrotherQLPrinter(descriptor, transport, 'serial');
74
+ }
75
+ if (options.host !== undefined) {
76
+ const transport = await TcpTransport.connect(options.host, options.port);
77
+ const descriptor = Object.values(DEVICES).find(d => d.network !== 'none');
78
+ /* v8 ignore next -- DEVICES always has network-capable entries */
79
+ if (!descriptor)
80
+ throw new Error('No network-capable Brother QL descriptor found.');
81
+ return new BrotherQLPrinter(descriptor, transport, 'tcp');
82
+ }
83
+ const found = await enumerateUsbDevices();
84
+ const match = found.find(entry => {
85
+ if (options.vid !== undefined && entry.descriptor.vid !== options.vid)
86
+ return false;
87
+ if (options.pid !== undefined && entry.descriptor.pid !== options.pid)
88
+ return false;
89
+ if (options.serialNumber !== undefined && entry.serialNumber !== options.serialNumber)
90
+ return false;
91
+ return true;
26
92
  });
93
+ if (!match)
94
+ throw new Error('No compatible Brother QL printer found.');
95
+ const transport = await UsbTransport.open(match.descriptor.vid, match.descriptor.pid);
96
+ return new BrotherQLPrinter(match.descriptor, transport, 'usb');
27
97
  }
28
- return results;
29
98
  }
30
- export { DEVICES };
99
+ /**
100
+ * Named export discovered by the unified `thermal-label-cli` — the CLI
101
+ * walks installed drivers looking for `mod.discovery`.
102
+ */
103
+ export const discovery = new BrotherQLDiscovery();
31
104
  //# sourceMappingURL=discovery.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACxF,OAAO,EAAoB,MAAM,YAAY,CAAC;AAE9C,MAAM,WAAW,GAAG,MAAM,CAAC;AAE3B,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAkB,EAAE,CAAC;IAElC,KAAK,MAAM,SAAS,IAAI,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,SAAS,CAAC,gBAAgB,CAAC;QACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,WAAW;YAAE,SAAS;QAE5C,IAAI,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACtC,sCAAsC;YACtC,OAAO,CAAC,IAAI,CACV,2EAA2E,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK;gBACvH,gFAAgF,CACnF,CAAC;YACF,SAAS;QACX,CAAC;QAED,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM;YAAE,SAAS;QAEtB,MAAM,IAAI,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,SAAS,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC;QAEvF,OAAO,CAAC,IAAI,CAAC;YACX,MAAM;YACN,YAAY,EAAE,SAAS;YACvB,IAAI;YACJ,SAAS,EAAE,KAAK;SACjB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,3 @@
1
- export { UsbTransport, TcpTransport } from './transport.js';
2
- export { BrotherQLPrinter, openPrinter, openPrinterTcp } from './printer.js';
3
- export { listPrinters } from './discovery.js';
4
- export { UnsupportedOperationError, PrinterError } from './errors.js';
5
- export type { Transport } from './transport.js';
6
- export type { OpenOptions, PrinterInfo } from './types.js';
7
- export { DEVICES, MEDIA, findDevice, findMedia, findMediaByWidth, encodeJob, renderText, renderImage, } from '@thermal-label/brother-ql-core';
8
- export type { DeviceDescriptor, MediaDescriptor, PageData, PageOptions, JobOptions, PrinterStatus, LabelBitmap, RawImageData, MediaType, TextPrintOptions, ImagePrintOptions, } from '@thermal-label/brother-ql-core';
1
+ export { BrotherQLDiscovery, discovery, type BrotherQLOpenOptions } from './discovery.js';
2
+ export { BrotherQLPrinter } from './printer.js';
9
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEtE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG3D,OAAO,EACL,OAAO,EACP,KAAK,EACL,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,WAAW,GACZ,MAAM,gCAAgC,CAAC;AACxC,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,QAAQ,EACR,WAAW,EACX,UAAU,EACV,aAAa,EACb,WAAW,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,3 @@
1
- export { UsbTransport, TcpTransport } from './transport.js';
2
- export { BrotherQLPrinter, openPrinter, openPrinterTcp } from './printer.js';
3
- export { listPrinters } from './discovery.js';
4
- export { UnsupportedOperationError, PrinterError } from './errors.js';
5
- // Re-export core API so consumers only need one import
6
- export { DEVICES, MEDIA, findDevice, findMedia, findMediaByWidth, encodeJob, renderText, renderImage, } from '@thermal-label/brother-ql-core';
1
+ export { BrotherQLDiscovery, discovery } from './discovery.js';
2
+ export { BrotherQLPrinter } from './printer.js';
7
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAKtE,uDAAuD;AACvD,OAAO,EACL,OAAO,EACP,KAAK,EACL,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,WAAW,GACZ,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAA6B,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}