@thermal-label/brother-ql-web 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.
- package/dist/__tests__/printer.test.js +106 -146
- package/dist/__tests__/printer.test.js.map +1 -1
- package/dist/__tests__/webusb-mock.d.ts +6 -14
- package/dist/__tests__/webusb-mock.d.ts.map +1 -1
- package/dist/__tests__/webusb-mock.js +54 -32
- package/dist/__tests__/webusb-mock.js.map +1 -1
- package/dist/index.d.ts +1 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/index.js.map +1 -1
- package/dist/printer.d.ts +36 -14
- package/dist/printer.d.ts.map +1 -1
- package/dist/printer.js +74 -97
- package/dist/printer.js.map +1 -1
- package/package.json +7 -4
- package/dist/__tests__/request.test.d.ts +0 -2
- package/dist/__tests__/request.test.d.ts.map +0 -1
- package/dist/__tests__/request.test.js +0 -57
- package/dist/__tests__/request.test.js.map +0 -1
- package/dist/request.d.ts +0 -7
- package/dist/request.d.ts.map +0 -1
- package/dist/request.js +0 -18
- package/dist/request.js.map +0 -1
|
@@ -1,156 +1,116 @@
|
|
|
1
|
-
import { describe,
|
|
2
|
-
import {
|
|
3
|
-
import { DEVICES,
|
|
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 { fromUSBDevice, requestPrinter } from '../printer.js';
|
|
4
5
|
import { createMockUSBDevice } from './webusb-mock.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
function solidRgba(width, height) {
|
|
7
|
+
return { width, height, data: new Uint8Array(width * height * 4).fill(0) };
|
|
8
|
+
}
|
|
9
|
+
function redRgba(width, height) {
|
|
10
|
+
const data = new Uint8Array(width * height * 4);
|
|
11
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
12
|
+
data[i] = 255;
|
|
13
|
+
data[i + 1] = 0;
|
|
14
|
+
data[i + 2] = 0;
|
|
15
|
+
data[i + 3] = 255;
|
|
16
|
+
}
|
|
17
|
+
return { width, height, data };
|
|
8
18
|
}
|
|
9
19
|
describe('WebBrotherQLPrinter', () => {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
expect(
|
|
23
|
-
});
|
|
24
|
-
it('
|
|
25
|
-
const
|
|
26
|
-
await
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
expect(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
});
|
|
50
|
-
const printer =
|
|
20
|
+
it('exposes adapter metadata for a QL-820NWB', async () => {
|
|
21
|
+
const device = createMockUSBDevice({ productId: 0x20a7 });
|
|
22
|
+
const printer = await fromUSBDevice(device);
|
|
23
|
+
expect(printer.family).toBe('brother-ql');
|
|
24
|
+
expect(printer.model).toBe('QL-820NWB');
|
|
25
|
+
expect(printer.device.twoColor).toBe(true);
|
|
26
|
+
expect(printer.connected).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
it('print() splits two-colour images when media.colorCapable is true', async () => {
|
|
29
|
+
const device = createMockUSBDevice({ productId: 0x20a7 });
|
|
30
|
+
const printer = await fromUSBDevice(device);
|
|
31
|
+
await printer.print(redRgba(64, 64), MEDIA[251]);
|
|
32
|
+
expect(device.__transfers.length).toBeGreaterThan(0);
|
|
33
|
+
});
|
|
34
|
+
it('createPreview() returns two planes on colorCapable media', async () => {
|
|
35
|
+
const device = createMockUSBDevice({ productId: 0x20a7 });
|
|
36
|
+
const printer = await fromUSBDevice(device);
|
|
37
|
+
const preview = await printer.createPreview(redRgba(64, 64), { media: MEDIA[251] });
|
|
38
|
+
expect(preview.planes.map(p => p.name)).toEqual(['black', 'red']);
|
|
39
|
+
expect(preview.assumed).toBe(false);
|
|
40
|
+
});
|
|
41
|
+
it('createPreview() returns one plane on non-colorCapable media', async () => {
|
|
42
|
+
const device = createMockUSBDevice({ productId: 0x20a7 });
|
|
43
|
+
const printer = await fromUSBDevice(device);
|
|
44
|
+
const preview = await printer.createPreview(solidRgba(64, 64), { media: MEDIA[259] });
|
|
45
|
+
expect(preview.planes).toHaveLength(1);
|
|
46
|
+
});
|
|
47
|
+
it('createPreview() reuses detected media from a prior getStatus', async () => {
|
|
48
|
+
const bytes = new Uint8Array(32);
|
|
49
|
+
bytes[10] = 62;
|
|
50
|
+
bytes[11] = 0x0a;
|
|
51
|
+
const device = createMockUSBDevice({ productId: 0x20a7, statusBytes: bytes });
|
|
52
|
+
const printer = await fromUSBDevice(device);
|
|
53
|
+
await printer.getStatus();
|
|
54
|
+
const preview = await printer.createPreview(solidRgba(64, 64));
|
|
55
|
+
expect(preview.assumed).toBe(false);
|
|
56
|
+
expect(preview.media.id).toBe(259);
|
|
57
|
+
});
|
|
58
|
+
it('createPreview() falls back to DEFAULT_MEDIA with assumed=true', async () => {
|
|
59
|
+
const device = createMockUSBDevice({ productId: 0x20a7 });
|
|
60
|
+
const printer = await fromUSBDevice(device);
|
|
61
|
+
const preview = await printer.createPreview(solidRgba(64, 64));
|
|
62
|
+
expect(preview.assumed).toBe(true);
|
|
63
|
+
expect(preview.media.id).toBe(259);
|
|
64
|
+
});
|
|
65
|
+
it('close() releases the underlying USB device', async () => {
|
|
66
|
+
const device = createMockUSBDevice({ productId: 0x20a7 });
|
|
67
|
+
const printer = await fromUSBDevice(device);
|
|
68
|
+
await printer.close();
|
|
69
|
+
expect(device.opened).toBe(false);
|
|
70
|
+
expect(printer.connected).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
it('print() writes an encoded raster job for non-colorCapable media', async () => {
|
|
73
|
+
const device = createMockUSBDevice({ productId: 0x20a7 });
|
|
74
|
+
const printer = await fromUSBDevice(device);
|
|
75
|
+
await printer.print(solidRgba(64, 64), MEDIA[259]);
|
|
76
|
+
expect(device.__transfers.length).toBeGreaterThan(0);
|
|
77
|
+
});
|
|
78
|
+
it('print() throws MediaNotSpecifiedError when media is missing', async () => {
|
|
79
|
+
const device = createMockUSBDevice({ productId: 0x20a7 });
|
|
80
|
+
const printer = await fromUSBDevice(device);
|
|
81
|
+
await expect(printer.print(solidRgba(64, 64))).rejects.toBeInstanceOf(MediaNotSpecifiedError);
|
|
82
|
+
});
|
|
83
|
+
it('getStatus returns BrotherQLStatus with detected media when present', async () => {
|
|
84
|
+
const bytes = new Uint8Array(32);
|
|
85
|
+
bytes[10] = 62;
|
|
86
|
+
bytes[11] = 0x0a;
|
|
87
|
+
const device = createMockUSBDevice({ productId: 0x20a7, statusBytes: bytes });
|
|
88
|
+
const printer = await fromUSBDevice(device);
|
|
51
89
|
const status = await printer.getStatus();
|
|
52
|
-
|
|
53
|
-
expect(
|
|
54
|
-
expect(status.
|
|
55
|
-
expect(status.mediaType).toBe('continuous');
|
|
56
|
-
});
|
|
57
|
-
it('getStatus throws when no data is returned', async () => {
|
|
58
|
-
mock.spies.transferIn.mockResolvedValueOnce({ status: 'ok', data: null });
|
|
59
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
60
|
-
await expect(printer.getStatus()).rejects.toThrow('No status data received');
|
|
61
|
-
});
|
|
62
|
-
it('disconnect releases interface and closes device', async () => {
|
|
63
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
64
|
-
await printer.disconnect();
|
|
65
|
-
expect(mock.spies.releaseInterface).toHaveBeenCalledWith(0);
|
|
66
|
-
expect(mock.spies.close).toHaveBeenCalledOnce();
|
|
67
|
-
});
|
|
68
|
-
it('isConnected reflects device opened state', async () => {
|
|
69
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
70
|
-
expect(printer.isConnected()).toBe(false);
|
|
71
|
-
await mock.device.open();
|
|
72
|
-
expect(printer.isConnected()).toBe(true);
|
|
73
|
-
});
|
|
74
|
-
it('printText() renders text and sends to device', async () => {
|
|
75
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
76
|
-
await printer.printText('hello', media62mm);
|
|
77
|
-
expect(mock.spies.transferOut).toHaveBeenCalled();
|
|
90
|
+
expect(status.rawBytes.length).toBe(32);
|
|
91
|
+
expect(status.editorLiteMode).toBe(false);
|
|
92
|
+
expect(status.detectedMedia?.id).toBe(259);
|
|
78
93
|
});
|
|
79
|
-
it('
|
|
80
|
-
const
|
|
81
|
-
await
|
|
82
|
-
expect(mock.spies.transferOut).toHaveBeenCalled();
|
|
94
|
+
it('throws for unknown USB devices', async () => {
|
|
95
|
+
const device = createMockUSBDevice({ vendorId: 0x1234, productId: 0x5678 });
|
|
96
|
+
await expect(fromUSBDevice(device)).rejects.toThrow('Unsupported USB device');
|
|
83
97
|
});
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
expect(mock.spies.transferOut).toHaveBeenCalled();
|
|
93
|
-
});
|
|
94
|
-
it('printImage() passes renderImage options', async () => {
|
|
95
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
96
|
-
await printer.printImage(makeImageData(), media62mm, {
|
|
97
|
-
threshold: 100,
|
|
98
|
-
dither: true,
|
|
99
|
-
invert: true,
|
|
98
|
+
});
|
|
99
|
+
describe('requestPrinter', () => {
|
|
100
|
+
it('passes the brother-ql VID/PIDs to navigator.usb.requestDevice', async () => {
|
|
101
|
+
const device = createMockUSBDevice({ productId: 0x20a7 });
|
|
102
|
+
const requestDevice = vi.fn(() => Promise.resolve(device));
|
|
103
|
+
Object.defineProperty(globalThis, 'navigator', {
|
|
104
|
+
value: { usb: { requestDevice } },
|
|
105
|
+
configurable: true,
|
|
100
106
|
});
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
it('printImage() passes PageOptions through to print', async () => {
|
|
109
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
110
|
-
await printer.printImage(makeImageData(), media62mm, { autoCut: true });
|
|
111
|
-
expect(mock.spies.transferOut).toHaveBeenCalled();
|
|
112
|
-
});
|
|
113
|
-
it('printImageURL() fetches URL and prints via canvas', async () => {
|
|
114
|
-
const blobMock = new Blob();
|
|
115
|
-
const bmpMock = { width: 10, height: 10 };
|
|
116
|
-
const ctxMock = {
|
|
117
|
-
drawImage: vi.fn(),
|
|
118
|
-
getImageData: vi.fn().mockReturnValue(makeImageData()),
|
|
119
|
-
};
|
|
120
|
-
const canvasMock = { getContext: vi.fn().mockReturnValue(ctxMock) };
|
|
121
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ blob: vi.fn().mockResolvedValue(blobMock) }));
|
|
122
|
-
vi.stubGlobal('createImageBitmap', vi.fn().mockResolvedValue(bmpMock));
|
|
123
|
-
vi.stubGlobal('OffscreenCanvas', vi.fn().mockReturnValue(canvasMock));
|
|
124
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
125
|
-
await printer.printImageURL('https://example.com/label.png', media62mm);
|
|
126
|
-
expect(mock.spies.transferOut).toHaveBeenCalled();
|
|
127
|
-
});
|
|
128
|
-
it('printImageURL() throws when canvas context cannot be obtained', async () => {
|
|
129
|
-
const blobMock = new Blob();
|
|
130
|
-
const bmpMock = { width: 10, height: 10 };
|
|
131
|
-
const canvasMock = { getContext: vi.fn().mockReturnValue(null) };
|
|
132
|
-
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ blob: vi.fn().mockResolvedValue(blobMock) }));
|
|
133
|
-
vi.stubGlobal('createImageBitmap', vi.fn().mockResolvedValue(bmpMock));
|
|
134
|
-
vi.stubGlobal('OffscreenCanvas', vi.fn().mockReturnValue(canvasMock));
|
|
135
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
136
|
-
await expect(printer.printImageURL('https://example.com/label.png', media62mm)).rejects.toThrow('Could not get canvas context');
|
|
137
|
-
});
|
|
138
|
-
it('printTwoColor throws on non-two-color device', async () => {
|
|
139
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_700);
|
|
140
|
-
const imgData = makeImageData();
|
|
141
|
-
await expect(printer.printTwoColor(imgData, imgData, media62mm)).rejects.toThrow('does not support two-color');
|
|
142
|
-
});
|
|
143
|
-
it('printTwoColor() renders and prints both channels', async () => {
|
|
144
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
145
|
-
const imgData = makeImageData();
|
|
146
|
-
await printer.printTwoColor(imgData, imgData, media62mm);
|
|
147
|
-
expect(mock.spies.transferOut).toHaveBeenCalled();
|
|
148
|
-
});
|
|
149
|
-
it('printTwoColor() passes options through to print', async () => {
|
|
150
|
-
const printer = new WebBrotherQLPrinter(mock.device, DEVICES.QL_820NWB);
|
|
151
|
-
const imgData = makeImageData();
|
|
152
|
-
await printer.printTwoColor(imgData, imgData, media62mm, { autoCut: true });
|
|
153
|
-
expect(mock.spies.transferOut).toHaveBeenCalled();
|
|
107
|
+
await requestPrinter();
|
|
108
|
+
expect(requestDevice).toHaveBeenCalledOnce();
|
|
109
|
+
const call = requestDevice.mock.calls[0][0];
|
|
110
|
+
const pids = call.filters.map(f => f.productId);
|
|
111
|
+
for (const d of Object.values(DEVICES)) {
|
|
112
|
+
expect(pids).toContain(d.pid);
|
|
113
|
+
}
|
|
154
114
|
});
|
|
155
115
|
});
|
|
156
116
|
//# sourceMappingURL=printer.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printer.test.js","sourceRoot":"","sources":["../../src/__tests__/printer.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"printer.test.js","sourceRoot":"","sources":["../../src/__tests__/printer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
releaseInterface: ReturnType<typeof vi.fn>;
|
|
8
|
-
transferOut: ReturnType<typeof vi.fn>;
|
|
9
|
-
transferIn: ReturnType<typeof vi.fn>;
|
|
10
|
-
}
|
|
11
|
-
export interface MockUSBDevice {
|
|
12
|
-
device: USBDevice;
|
|
13
|
-
spies: MockUSBDeviceSpies;
|
|
1
|
+
export interface MockUSBDevice extends USBDevice {
|
|
2
|
+
__transfers: {
|
|
3
|
+
endpointNumber: number;
|
|
4
|
+
data: Uint8Array;
|
|
5
|
+
}[];
|
|
6
|
+
__statusBytes: Uint8Array;
|
|
14
7
|
}
|
|
15
8
|
export declare function createMockUSBDevice(overrides?: {
|
|
16
9
|
vendorId?: number;
|
|
17
10
|
productId?: number;
|
|
18
|
-
serialNumber?: string;
|
|
19
11
|
statusBytes?: Uint8Array;
|
|
20
12
|
}): MockUSBDevice;
|
|
21
13
|
//# sourceMappingURL=webusb-mock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webusb-mock.d.ts","sourceRoot":"","sources":["../../src/__tests__/webusb-mock.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"webusb-mock.d.ts","sourceRoot":"","sources":["../../src/__tests__/webusb-mock.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,WAAW,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAE,EAAE,CAAC;IAC5D,aAAa,EAAE,UAAU,CAAC;CAC3B;AAED,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B,GAAG,aAAa,CAoEhB"}
|
|
@@ -1,44 +1,66 @@
|
|
|
1
1
|
import { vi } from 'vitest';
|
|
2
2
|
export function createMockUSBDevice(overrides) {
|
|
3
|
-
const
|
|
4
|
-
open: vi.fn().mockImplementation(() => Promise.resolve()),
|
|
5
|
-
close: vi.fn().mockImplementation(() => Promise.resolve()),
|
|
6
|
-
selectConfiguration: vi.fn().mockImplementation(() => Promise.resolve()),
|
|
7
|
-
claimInterface: vi.fn().mockImplementation(() => Promise.resolve()),
|
|
8
|
-
releaseInterface: vi.fn().mockImplementation(() => Promise.resolve()),
|
|
9
|
-
transferOut: vi
|
|
10
|
-
.fn()
|
|
11
|
-
.mockImplementation(() => Promise.resolve({ bytesWritten: 0, status: 'ok' })),
|
|
12
|
-
transferIn: vi.fn().mockImplementation(() => Promise.resolve({
|
|
13
|
-
status: 'ok',
|
|
14
|
-
data: new DataView((overrides?.statusBytes ?? new Uint8Array(32)).buffer),
|
|
15
|
-
})),
|
|
16
|
-
};
|
|
3
|
+
const transfers = [];
|
|
17
4
|
let opened = false;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
5
|
+
const endpoints = [
|
|
6
|
+
{ endpointNumber: 2, direction: 'out' },
|
|
7
|
+
{ endpointNumber: 1, direction: 'in' },
|
|
8
|
+
];
|
|
9
|
+
const configuration = {
|
|
10
|
+
configurationValue: 1,
|
|
11
|
+
configurationName: null,
|
|
12
|
+
interfaces: [
|
|
13
|
+
{
|
|
14
|
+
interfaceNumber: 0,
|
|
15
|
+
alternate: {
|
|
16
|
+
alternateSetting: 0,
|
|
17
|
+
interfaceClass: 7,
|
|
18
|
+
interfaceSubclass: 1,
|
|
19
|
+
interfaceProtocol: 2,
|
|
20
|
+
interfaceName: null,
|
|
21
|
+
endpoints,
|
|
22
|
+
},
|
|
23
|
+
alternates: [],
|
|
24
|
+
claimed: false,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
const statusBytes = overrides?.statusBytes ?? new Uint8Array(32);
|
|
26
29
|
const device = {
|
|
27
30
|
vendorId: overrides?.vendorId ?? 0x04f9,
|
|
28
31
|
productId: overrides?.productId ?? 0x20a7,
|
|
29
|
-
serialNumber:
|
|
30
|
-
configuration: { interfaces: [{ interfaceNumber: 0, claimed: false }] },
|
|
32
|
+
serialNumber: undefined,
|
|
31
33
|
get opened() {
|
|
32
34
|
return opened;
|
|
33
35
|
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
configuration,
|
|
37
|
+
open: vi.fn(() => {
|
|
38
|
+
opened = true;
|
|
39
|
+
return Promise.resolve();
|
|
40
|
+
}),
|
|
41
|
+
close: vi.fn(() => {
|
|
42
|
+
opened = false;
|
|
43
|
+
return Promise.resolve();
|
|
44
|
+
}),
|
|
45
|
+
selectConfiguration: vi.fn(() => Promise.resolve()),
|
|
46
|
+
claimInterface: vi.fn(() => Promise.resolve()),
|
|
47
|
+
releaseInterface: vi.fn(() => Promise.resolve()),
|
|
48
|
+
transferOut: vi.fn((endpointNumber, data) => {
|
|
49
|
+
const array = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
50
|
+
transfers.push({ endpointNumber, data: Uint8Array.from(array) });
|
|
51
|
+
return Promise.resolve({ bytesWritten: array.byteLength, status: 'ok' });
|
|
52
|
+
}),
|
|
53
|
+
transferIn: vi.fn((_endpointNumber, length) => {
|
|
54
|
+
const out = new Uint8Array(length);
|
|
55
|
+
out.set(statusBytes.subarray(0, length));
|
|
56
|
+
return Promise.resolve({
|
|
57
|
+
data: new DataView(out.buffer),
|
|
58
|
+
status: 'ok',
|
|
59
|
+
});
|
|
60
|
+
}),
|
|
61
|
+
__transfers: transfers,
|
|
62
|
+
__statusBytes: statusBytes,
|
|
41
63
|
};
|
|
42
|
-
return
|
|
64
|
+
return device;
|
|
43
65
|
}
|
|
44
66
|
//# sourceMappingURL=webusb-mock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webusb-mock.js","sourceRoot":"","sources":["../../src/__tests__/webusb-mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"webusb-mock.js","sourceRoot":"","sources":["../../src/__tests__/webusb-mock.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
export { WebBrotherQLPrinter } from './printer.js';
|
|
2
|
-
export { requestPrinter, fromUSBDevice } from './request.js';
|
|
3
|
-
export type { RequestOptions } from './request.js';
|
|
4
|
-
export type { DeviceDescriptor, MediaDescriptor, PageData, PageOptions, JobOptions, PrinterStatus, TextPrintOptions, ImagePrintOptions, MediaType, } from '@thermal-label/brother-ql-core';
|
|
5
|
-
export { DEVICES, MEDIA, findDevice, findMedia, findMediaByWidth, renderText, renderImage, rotateBitmap, } from '@thermal-label/brother-ql-core';
|
|
6
|
-
export type { LabelBitmap, RawImageData } from '@thermal-label/brother-ql-core';
|
|
1
|
+
export { DEFAULT_FILTERS, WebBrotherQLPrinter, fromUSBDevice, requestPrinter, type RequestOptions, } from './printer.js';
|
|
7
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export { WebBrotherQLPrinter } from './printer.js';
|
|
2
|
-
export { requestPrinter, fromUSBDevice } from './request.js';
|
|
3
|
-
export { DEVICES, MEDIA, findDevice, findMedia, findMediaByWidth, renderText, renderImage, rotateBitmap, } from '@thermal-label/brother-ql-core';
|
|
1
|
+
export { DEFAULT_FILTERS, WebBrotherQLPrinter, fromUSBDevice, requestPrinter, } from './printer.js';
|
|
4
2
|
//# 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,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,aAAa,EACb,cAAc,GAEf,MAAM,cAAc,CAAC"}
|
package/dist/printer.d.ts
CHANGED
|
@@ -1,16 +1,38 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export
|
|
3
|
-
|
|
4
|
-
readonly descriptor: DeviceDescriptor;
|
|
5
|
-
constructor(device: USBDevice, descriptor: DeviceDescriptor);
|
|
6
|
-
isConnected(): boolean;
|
|
7
|
-
getStatus(): Promise<PrinterStatus>;
|
|
8
|
-
print(pages: PageData[], options?: JobOptions): Promise<void>;
|
|
9
|
-
printText(text: string, media: MediaDescriptor, options?: TextPrintOptions): Promise<void>;
|
|
10
|
-
printImage(imageData: ImageData, media: MediaDescriptor, options?: ImagePrintOptions): Promise<void>;
|
|
11
|
-
printImageURL(url: string, media: MediaDescriptor, options?: ImagePrintOptions): Promise<void>;
|
|
12
|
-
printTwoColor(blackImageData: ImageData, redImageData: ImageData, media: MediaDescriptor, options?: PageOptions): Promise<void>;
|
|
13
|
-
disconnect(): Promise<void>;
|
|
1
|
+
import { type BrotherQLDevice, type BrotherQLStatus, type MediaDescriptor, type PreviewOptions, type PreviewResult, type PrinterAdapter, type RawImageData, type Transport } from '@thermal-label/brother-ql-core';
|
|
2
|
+
export interface RequestOptions {
|
|
3
|
+
filters?: USBDeviceFilter[];
|
|
14
4
|
}
|
|
15
|
-
|
|
5
|
+
/**
|
|
6
|
+
* WebUSB `PrinterAdapter` for Brother QL printers.
|
|
7
|
+
*
|
|
8
|
+
* Same two-colour handling as the node driver — `splitTwoColor()` runs
|
|
9
|
+
* internally when the selected media is `colorCapable`.
|
|
10
|
+
*/
|
|
11
|
+
export declare class WebBrotherQLPrinter implements PrinterAdapter {
|
|
12
|
+
readonly family: "brother-ql";
|
|
13
|
+
readonly device: BrotherQLDevice;
|
|
14
|
+
private readonly transport;
|
|
15
|
+
private lastStatus;
|
|
16
|
+
constructor(device: BrotherQLDevice, transport: Transport);
|
|
17
|
+
get model(): string;
|
|
18
|
+
get connected(): boolean;
|
|
19
|
+
print(image: RawImageData, media?: MediaDescriptor): Promise<void>;
|
|
20
|
+
createPreview(image: RawImageData, options?: PreviewOptions): Promise<PreviewResult>;
|
|
21
|
+
getStatus(): Promise<BrotherQLStatus>;
|
|
22
|
+
close(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export declare const DEFAULT_FILTERS: USBDeviceFilter[];
|
|
25
|
+
/**
|
|
26
|
+
* Show the browser's USB picker and wrap the selected device.
|
|
27
|
+
*
|
|
28
|
+
* Requires a user gesture. Opens the device and claims interface 0 via
|
|
29
|
+
* `WebUsbTransport.fromDevice()`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function requestPrinter(options?: RequestOptions): Promise<WebBrotherQLPrinter>;
|
|
32
|
+
/**
|
|
33
|
+
* Wrap an already-selected `USBDevice`.
|
|
34
|
+
*
|
|
35
|
+
* @throws when the VID/PID is not in the Brother QL registry.
|
|
36
|
+
*/
|
|
37
|
+
export declare function fromUSBDevice(usbDevice: USBDevice): Promise<WebBrotherQLPrinter>;
|
|
16
38
|
//# sourceMappingURL=printer.d.ts.map
|
package/dist/printer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printer.d.ts","sourceRoot":"","sources":["../src/printer.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"printer.d.ts","sourceRoot":"","sources":["../src/printer.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,eAAe,EAEpB,KAAK,eAAe,EACpB,KAAK,eAAe,EAEpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,gCAAgC,CAAC;AAOxC,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,YAAW,cAAc;IACxD,QAAQ,CAAC,MAAM,eAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAEjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,UAAU,CAA8B;gBAEpC,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS;IAKzD,IAAI,KAAK,IAAI,MAAM,CAElB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAEK,KAAK,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBxE,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAW9E,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC;IAQrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAED,eAAO,MAAM,eAAe,mBAA0C,CAAC;AAEvE;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAI/F;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAStF"}
|
package/dist/printer.js
CHANGED
|
@@ -1,114 +1,91 @@
|
|
|
1
|
-
import { encodeJob, findDevice, parseStatus, renderImage,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const BULK_IN_ENDPOINT = 1;
|
|
1
|
+
import { DEFAULT_MEDIA, DEVICES, STATUS_REQUEST, createPreviewOffline, encodeJob, findDevice, parseStatus, renderImage, splitTwoColor, } from '@thermal-label/brother-ql-core';
|
|
2
|
+
import { MediaNotSpecifiedError } from '@thermal-label/contracts';
|
|
3
|
+
import { buildUsbFilters } from '@thermal-label/transport';
|
|
4
|
+
import { WebUsbTransport } from '@thermal-label/transport/web';
|
|
6
5
|
const STATUS_BYTE_COUNT = 32;
|
|
7
|
-
|
|
6
|
+
/**
|
|
7
|
+
* WebUSB `PrinterAdapter` for Brother QL printers.
|
|
8
|
+
*
|
|
9
|
+
* Same two-colour handling as the node driver — `splitTwoColor()` runs
|
|
10
|
+
* internally when the selected media is `colorCapable`.
|
|
11
|
+
*/
|
|
8
12
|
export class WebBrotherQLPrinter {
|
|
13
|
+
family = 'brother-ql';
|
|
9
14
|
device;
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
transport;
|
|
16
|
+
lastStatus;
|
|
17
|
+
constructor(device, transport) {
|
|
12
18
|
this.device = device;
|
|
13
|
-
this.
|
|
19
|
+
this.transport = transport;
|
|
14
20
|
}
|
|
15
|
-
|
|
16
|
-
return this.device.
|
|
21
|
+
get model() {
|
|
22
|
+
return this.device.name;
|
|
17
23
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const result = await this.device.transferIn(BULK_IN_ENDPOINT, STATUS_BYTE_COUNT);
|
|
21
|
-
if (!result.data)
|
|
22
|
-
throw new Error('No status data received');
|
|
23
|
-
return parseStatus(new Uint8Array(result.data.buffer));
|
|
24
|
-
}
|
|
25
|
-
async print(pages, options) {
|
|
26
|
-
const bytes = encodeJob(pages, options);
|
|
27
|
-
await this.device.transferOut(BULK_OUT_ENDPOINT, bytes);
|
|
24
|
+
get connected() {
|
|
25
|
+
return this.transport.connected;
|
|
28
26
|
}
|
|
29
|
-
async
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
bitmap,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
await this.print([page]);
|
|
27
|
+
async print(image, media) {
|
|
28
|
+
const resolvedMedia = (media ?? this.lastStatus?.detectedMedia);
|
|
29
|
+
if (!resolvedMedia)
|
|
30
|
+
throw new MediaNotSpecifiedError();
|
|
31
|
+
let page;
|
|
32
|
+
if (resolvedMedia.colorCapable) {
|
|
33
|
+
const { black, red } = splitTwoColor(image);
|
|
34
|
+
page = { bitmap: black, redBitmap: red, media: resolvedMedia };
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const bitmap = renderImage(image, { dither: true });
|
|
38
|
+
page = { bitmap, media: resolvedMedia };
|
|
39
|
+
}
|
|
40
|
+
const bytes = encodeJob([page]);
|
|
41
|
+
await this.transport.write(bytes);
|
|
45
42
|
}
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
...(
|
|
55
|
-
|
|
56
|
-
...(invert ? { invert: true } : {}),
|
|
43
|
+
createPreview(image, options) {
|
|
44
|
+
const override = options?.media;
|
|
45
|
+
const detected = this.lastStatus?.detectedMedia;
|
|
46
|
+
if (override)
|
|
47
|
+
return Promise.resolve(createPreviewOffline(image, override));
|
|
48
|
+
if (detected)
|
|
49
|
+
return Promise.resolve(createPreviewOffline(image, detected));
|
|
50
|
+
return Promise.resolve({
|
|
51
|
+
...createPreviewOffline(image, DEFAULT_MEDIA),
|
|
52
|
+
assumed: true,
|
|
57
53
|
});
|
|
58
|
-
const rotationAngle = rotate ?? 0;
|
|
59
|
-
const bitmap = rotationAngle === 0 ? rotateBitmap(rawBitmap, 270) : rotateBitmap(rawBitmap, rotationAngle);
|
|
60
|
-
const page = {
|
|
61
|
-
bitmap,
|
|
62
|
-
media,
|
|
63
|
-
...(Object.keys(pageOptions).length > 0 ? { options: pageOptions } : {}),
|
|
64
|
-
};
|
|
65
|
-
await this.print([page]);
|
|
66
54
|
}
|
|
67
|
-
async
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (!ctx)
|
|
74
|
-
throw new Error('Could not get canvas context');
|
|
75
|
-
ctx.drawImage(bmp, 0, 0);
|
|
76
|
-
const imageData = ctx.getImageData(0, 0, bmp.width, bmp.height);
|
|
77
|
-
await this.printImage(imageData, media, options);
|
|
78
|
-
}
|
|
79
|
-
async printTwoColor(blackImageData, redImageData, media, options) {
|
|
80
|
-
if (!this.descriptor.twoColor) {
|
|
81
|
-
throw new Error(`Device ${this.descriptor.name} does not support two-color printing. ` +
|
|
82
|
-
'Use a QL-800, QL-810W, or QL-820NWB.');
|
|
83
|
-
}
|
|
84
|
-
const toRaw = (img) => ({
|
|
85
|
-
width: img.width,
|
|
86
|
-
height: img.height,
|
|
87
|
-
data: new Uint8Array(img.data.buffer),
|
|
88
|
-
});
|
|
89
|
-
const blackBitmap = rotateBitmap(renderImage(toRaw(blackImageData)), 270);
|
|
90
|
-
const redBitmap = rotateBitmap(renderImage(toRaw(redImageData)), 270);
|
|
91
|
-
const page = {
|
|
92
|
-
bitmap: blackBitmap,
|
|
93
|
-
redBitmap,
|
|
94
|
-
media,
|
|
95
|
-
...(options !== undefined ? { options } : {}),
|
|
96
|
-
};
|
|
97
|
-
await this.print([page]);
|
|
55
|
+
async getStatus() {
|
|
56
|
+
await this.transport.write(STATUS_REQUEST);
|
|
57
|
+
const bytes = await this.transport.read(STATUS_BYTE_COUNT);
|
|
58
|
+
const status = parseStatus(bytes);
|
|
59
|
+
this.lastStatus = status;
|
|
60
|
+
return status;
|
|
98
61
|
}
|
|
99
|
-
async
|
|
100
|
-
await this.
|
|
101
|
-
await this.device.close();
|
|
62
|
+
async close() {
|
|
63
|
+
await this.transport.close();
|
|
102
64
|
}
|
|
103
65
|
}
|
|
104
|
-
export
|
|
105
|
-
|
|
66
|
+
export const DEFAULT_FILTERS = buildUsbFilters(Object.values(DEVICES));
|
|
67
|
+
/**
|
|
68
|
+
* Show the browser's USB picker and wrap the selected device.
|
|
69
|
+
*
|
|
70
|
+
* Requires a user gesture. Opens the device and claims interface 0 via
|
|
71
|
+
* `WebUsbTransport.fromDevice()`.
|
|
72
|
+
*/
|
|
73
|
+
export async function requestPrinter(options = {}) {
|
|
74
|
+
const filters = options.filters ?? DEFAULT_FILTERS;
|
|
75
|
+
const usbDevice = await navigator.usb.requestDevice({ filters });
|
|
76
|
+
return fromUSBDevice(usbDevice);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Wrap an already-selected `USBDevice`.
|
|
80
|
+
*
|
|
81
|
+
* @throws when the VID/PID is not in the Brother QL registry.
|
|
82
|
+
*/
|
|
83
|
+
export async function fromUSBDevice(usbDevice) {
|
|
84
|
+
const descriptor = findDevice(usbDevice.vendorId, usbDevice.productId);
|
|
106
85
|
if (!descriptor) {
|
|
107
|
-
throw new Error(`Unsupported device: VID
|
|
86
|
+
throw new Error(`Unsupported USB device: VID=0x${usbDevice.vendorId.toString(16)} PID=0x${usbDevice.productId.toString(16)}`);
|
|
108
87
|
}
|
|
109
|
-
await
|
|
110
|
-
|
|
111
|
-
await device.claimInterface(USB_INTERFACE);
|
|
112
|
-
return new WebBrotherQLPrinter(device, descriptor);
|
|
88
|
+
const transport = await WebUsbTransport.fromDevice(usbDevice);
|
|
89
|
+
return new WebBrotherQLPrinter(descriptor, transport);
|
|
113
90
|
}
|
|
114
91
|
//# sourceMappingURL=printer.js.map
|
package/dist/printer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"printer.js","sourceRoot":"","sources":["../src/printer.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"printer.js","sourceRoot":"","sources":["../src/printer.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,OAAO,EACP,cAAc,EACd,oBAAoB,EACpB,SAAS,EACT,UAAU,EACV,WAAW,EACX,WAAW,EACX,aAAa,GAWd,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAM7B;;;;;GAKG;AACH,MAAM,OAAO,mBAAmB;IACrB,MAAM,GAAG,YAAqB,CAAC;IAC/B,MAAM,CAAkB;IAEhB,SAAS,CAAY;IAC9B,UAAU,CAA8B;IAEhD,YAAY,MAAuB,EAAE,SAAoB;QACvD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,KAAmB,EAAE,KAAuB;QACtD,MAAM,aAAa,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,aAAa,CAA+B,CAAC;QAC9F,IAAI,CAAC,aAAa;YAAE,MAAM,IAAI,sBAAsB,EAAE,CAAC;QAEvD,IAAI,IAAc,CAAC;QACnB,IAAI,aAAa,CAAC,YAAY,EAAE,CAAC;YAC/B,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YAC5C,IAAI,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QACjE,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YACpD,IAAI,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC;QAC1C,CAAC;QAED,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAChC,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,aAAa,CAAC,KAAmB,EAAE,OAAwB;QACzD,MAAM,QAAQ,GAAG,OAAO,EAAE,KAAmC,CAAC;QAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,aAA2C,CAAC;QAC9E,IAAI,QAAQ;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC5E,IAAI,QAAQ;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC5E,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,GAAG,oBAAoB,CAAC,KAAK,EAAE,aAAa,CAAC;YAC7C,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,SAAS;QACb,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAC3C,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;AAEvE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAA0B,EAAE;IAC/D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,eAAe,CAAC;IACnD,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACjE,OAAO,aAAa,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAoB;IACtD,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACvE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,iCAAiC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAC7G,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC9D,OAAO,IAAI,mBAAmB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;AACxD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thermal-label/brother-ql-web",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "WebUSB browser driver for Brother QL label printers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"brother",
|
|
@@ -44,21 +44,24 @@
|
|
|
44
44
|
},
|
|
45
45
|
"sideEffects": false,
|
|
46
46
|
"main": "./dist/index.js",
|
|
47
|
-
"types": "./
|
|
47
|
+
"types": "./dist/index.d.ts",
|
|
48
48
|
"exports": {
|
|
49
49
|
".": {
|
|
50
50
|
"import": "./dist/index.js",
|
|
51
|
-
"types": "./
|
|
51
|
+
"types": "./dist/index.d.ts"
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@thermal-label/
|
|
55
|
+
"@thermal-label/contracts": "^0.1.2",
|
|
56
|
+
"@thermal-label/transport": "^0.2.0",
|
|
57
|
+
"@thermal-label/brother-ql-core": "0.2.1"
|
|
56
58
|
},
|
|
57
59
|
"peerDependencies": {
|
|
58
60
|
"typescript": ">=5.0"
|
|
59
61
|
},
|
|
60
62
|
"devDependencies": {
|
|
61
63
|
"@mbtech-nl/tsconfig": "^1.0.0",
|
|
64
|
+
"@types/w3c-web-usb": "^1.0.0",
|
|
62
65
|
"@vitest/coverage-v8": "^2.1.9",
|
|
63
66
|
"jsdom": "^26.1.0",
|
|
64
67
|
"typescript": "~5.5.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/request.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { DEVICES } from '@thermal-label/brother-ql-core';
|
|
3
|
-
import { fromUSBDevice } from '../request.js';
|
|
4
|
-
import { createMockUSBDevice } from './webusb-mock.js';
|
|
5
|
-
const mockRequestDevice = vi.fn();
|
|
6
|
-
Object.defineProperty(globalThis, 'navigator', {
|
|
7
|
-
value: { usb: { requestDevice: mockRequestDevice } },
|
|
8
|
-
writable: true,
|
|
9
|
-
});
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
mockRequestDevice.mockClear();
|
|
12
|
-
});
|
|
13
|
-
describe('requestPrinter', () => {
|
|
14
|
-
it('passes all known printer-class PIDs to requestDevice', async () => {
|
|
15
|
-
const { device } = createMockUSBDevice({ productId: 0x20a7 });
|
|
16
|
-
mockRequestDevice.mockResolvedValueOnce(device);
|
|
17
|
-
const { requestPrinter } = await import('../request.js');
|
|
18
|
-
await requestPrinter();
|
|
19
|
-
expect(mockRequestDevice).toHaveBeenCalledOnce();
|
|
20
|
-
const [opts] = mockRequestDevice.mock.calls[0];
|
|
21
|
-
const pids = opts.filters.map(f => f.productId);
|
|
22
|
-
for (const d of Object.values(DEVICES)) {
|
|
23
|
-
expect(pids).toContain(d.pid);
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
it('does not include mass-storage PIDs in filters', async () => {
|
|
27
|
-
const { device } = createMockUSBDevice({ productId: 0x20a7 });
|
|
28
|
-
mockRequestDevice.mockResolvedValueOnce(device);
|
|
29
|
-
const { requestPrinter } = await import('../request.js');
|
|
30
|
-
await requestPrinter();
|
|
31
|
-
const [opts] = mockRequestDevice.mock.calls[0];
|
|
32
|
-
const pids = opts.filters.map(f => f.productId);
|
|
33
|
-
expect(pids).not.toContain(0x20aa);
|
|
34
|
-
expect(pids).not.toContain(0x20ab);
|
|
35
|
-
});
|
|
36
|
-
it('uses custom filters when provided', async () => {
|
|
37
|
-
const { device } = createMockUSBDevice({ productId: 0x20a7 });
|
|
38
|
-
mockRequestDevice.mockResolvedValueOnce(device);
|
|
39
|
-
const customFilters = [{ vendorId: 0x04f9, productId: 0x20a7 }];
|
|
40
|
-
const { requestPrinter } = await import('../request.js');
|
|
41
|
-
await requestPrinter({ filters: customFilters });
|
|
42
|
-
const [opts] = mockRequestDevice.mock.calls[0];
|
|
43
|
-
expect(opts.filters).toEqual(customFilters);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
describe('fromUSBDevice', () => {
|
|
47
|
-
it('returns WebBrotherQLPrinter for known device', () => {
|
|
48
|
-
const { device } = createMockUSBDevice({ productId: 0x20a7 });
|
|
49
|
-
const printer = fromUSBDevice(device);
|
|
50
|
-
expect(printer.descriptor.name).toBe('QL-820NWB');
|
|
51
|
-
});
|
|
52
|
-
it('throws for unknown product ID', () => {
|
|
53
|
-
const { device } = createMockUSBDevice({ productId: 0x9999 });
|
|
54
|
-
expect(() => fromUSBDevice(device)).toThrow('Unsupported device');
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
//# sourceMappingURL=request.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request.test.js","sourceRoot":"","sources":["../../src/__tests__/request.test.ts"],"names":[],"mappings":"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"}
|
package/dist/request.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { WebBrotherQLPrinter } from './printer.js';
|
|
2
|
-
export interface RequestOptions {
|
|
3
|
-
filters?: USBDeviceFilter[];
|
|
4
|
-
}
|
|
5
|
-
export declare function requestPrinter(options?: RequestOptions): Promise<WebBrotherQLPrinter>;
|
|
6
|
-
export declare function fromUSBDevice(device: USBDevice): WebBrotherQLPrinter;
|
|
7
|
-
//# sourceMappingURL=request.d.ts.map
|
package/dist/request.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAiB,MAAM,cAAc,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC7B;AAMD,wBAAsB,cAAc,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAI3F;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,mBAAmB,CAMpE"}
|
package/dist/request.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { DEVICES, findDevice } from '@thermal-label/brother-ql-core';
|
|
2
|
-
import { WebBrotherQLPrinter, openWebDevice } from './printer.js';
|
|
3
|
-
function defaultFilters() {
|
|
4
|
-
return Object.values(DEVICES).map(d => ({ vendorId: d.vid, productId: d.pid }));
|
|
5
|
-
}
|
|
6
|
-
export async function requestPrinter(options) {
|
|
7
|
-
const filters = options?.filters ?? defaultFilters();
|
|
8
|
-
const device = await navigator.usb.requestDevice({ filters });
|
|
9
|
-
return openWebDevice(device);
|
|
10
|
-
}
|
|
11
|
-
export function fromUSBDevice(device) {
|
|
12
|
-
const descriptor = findDevice(0x04f9, device.productId);
|
|
13
|
-
if (!descriptor) {
|
|
14
|
-
throw new Error(`Unsupported device: productId=0x${device.productId.toString(16)}`);
|
|
15
|
-
}
|
|
16
|
-
return new WebBrotherQLPrinter(device, descriptor);
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=request.js.map
|
package/dist/request.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAMlE,SAAS,cAAc;IACrB,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAwB;IAC3D,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,CAAC;IACrD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9D,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAiB;IAC7C,MAAM,UAAU,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IACxD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,IAAI,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACrD,CAAC"}
|