@thermal-label/brother-ql-core 0.0.1 → 0.3.0

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 (68) hide show
  1. package/dist/__tests__/devices.test.js +16 -2
  2. package/dist/__tests__/devices.test.js.map +1 -1
  3. package/dist/__tests__/media.test.js +37 -6
  4. package/dist/__tests__/media.test.js.map +1 -1
  5. package/dist/__tests__/pack-bits.test.d.ts +2 -0
  6. package/dist/__tests__/pack-bits.test.d.ts.map +1 -0
  7. package/dist/__tests__/pack-bits.test.js +90 -0
  8. package/dist/__tests__/pack-bits.test.js.map +1 -0
  9. package/dist/__tests__/preview.test.d.ts +2 -0
  10. package/dist/__tests__/preview.test.d.ts.map +1 -0
  11. package/dist/__tests__/preview.test.js +41 -0
  12. package/dist/__tests__/preview.test.js.map +1 -0
  13. package/dist/__tests__/protocol.test.js +46 -1
  14. package/dist/__tests__/protocol.test.js.map +1 -1
  15. package/dist/__tests__/status.test.js +28 -22
  16. package/dist/__tests__/status.test.js.map +1 -1
  17. package/dist/devices.d.ts +40 -21
  18. package/dist/devices.d.ts.map +1 -1
  19. package/dist/devices.js +38 -20
  20. package/dist/devices.js.map +1 -1
  21. package/dist/index.d.ts +8 -4
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +5 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/media.d.ts +43 -4
  26. package/dist/media.d.ts.map +1 -1
  27. package/dist/media.js +92 -24
  28. package/dist/media.js.map +1 -1
  29. package/dist/orientation.d.ts +11 -0
  30. package/dist/orientation.d.ts.map +1 -0
  31. package/dist/orientation.js +10 -0
  32. package/dist/orientation.js.map +1 -0
  33. package/dist/pack-bits.d.ts +20 -0
  34. package/dist/pack-bits.d.ts.map +1 -0
  35. package/dist/pack-bits.js +61 -0
  36. package/dist/pack-bits.js.map +1 -0
  37. package/dist/preview.d.ts +13 -0
  38. package/dist/preview.d.ts.map +1 -0
  39. package/dist/preview.js +31 -0
  40. package/dist/preview.js.map +1 -0
  41. package/dist/protocol.d.ts +2 -2
  42. package/dist/protocol.d.ts.map +1 -1
  43. package/dist/protocol.js +14 -8
  44. package/dist/protocol.js.map +1 -1
  45. package/dist/status.d.ts +20 -2
  46. package/dist/status.d.ts.map +1 -1
  47. package/dist/status.js +59 -45
  48. package/dist/status.js.map +1 -1
  49. package/dist/types.d.ts +46 -30
  50. package/dist/types.d.ts.map +1 -1
  51. package/dist/types.js +1 -1
  52. package/dist/types.js.map +1 -1
  53. package/package.json +3 -2
  54. package/src/__tests__/devices.test.ts +18 -2
  55. package/src/__tests__/media.test.ts +39 -6
  56. package/src/__tests__/pack-bits.test.ts +92 -0
  57. package/src/__tests__/preview.test.ts +52 -0
  58. package/src/__tests__/protocol.test.ts +47 -1
  59. package/src/__tests__/status.test.ts +31 -22
  60. package/src/devices.ts +41 -22
  61. package/src/index.ts +45 -11
  62. package/src/media.ts +105 -27
  63. package/src/orientation.ts +11 -0
  64. package/src/pack-bits.ts +64 -0
  65. package/src/preview.ts +35 -0
  66. package/src/protocol.ts +16 -9
  67. package/src/status.ts +62 -47
  68. package/src/types.ts +52 -32
@@ -14,7 +14,7 @@ import {
14
14
  buildExpandedMode,
15
15
  encodeJob,
16
16
  } from '../protocol.js';
17
- import { type PageData } from '../types.js';
17
+ import type { PageData } from '../types.js';
18
18
  import { MEDIA } from '../media.js';
19
19
 
20
20
  describe('buildInvalidate', () => {
@@ -170,6 +170,52 @@ describe('encodeJob', () => {
170
170
  }
171
171
  expect(found).toBe(true);
172
172
  });
173
+
174
+ it('compress option PackBits-encodes each raster row (LEN < uncompressed size)', () => {
175
+ // All-zero bitmap → every row is 90 zero bytes. PackBits collapses each
176
+ // row to 2 wire bytes (0xA7 0x00), so the LEN byte in the row header
177
+ // should be 2 instead of 90.
178
+ const page: PageData = { ...makePage(696, 3), options: { compress: true } };
179
+ const buf = encodeJob([page]);
180
+ // Find single-color row headers (0x67 0x00 LEN). With compression on,
181
+ // LEN should be 2 for each row, and the payload byte should be 0x00.
182
+ const rowHeaders: number[] = [];
183
+ for (let i = 0; i < buf.length - 4; i++) {
184
+ if (buf[i] === 0x67 && buf[i + 1] === 0x00) {
185
+ // Skip the byte sequence inside the 200-byte invalidate block
186
+ // (which is also all zeros, so 0x67 won't appear there). Heuristic:
187
+ // verify the next byte after LEN is the PackBits header 0xA7.
188
+ if (buf[i + 2] === 2 && buf[i + 3] === 0xa7 && buf[i + 4] === 0x00) {
189
+ rowHeaders.push(i);
190
+ }
191
+ }
192
+ }
193
+ expect(rowHeaders.length).toBe(3);
194
+ });
195
+
196
+ it('compress option two-color: both planes PackBits-encoded per row', () => {
197
+ const bitmap = createBitmap(696, 2);
198
+ const redBitmap = createBitmap(696, 2);
199
+ const page: PageData = {
200
+ bitmap,
201
+ redBitmap,
202
+ media: media62,
203
+ options: { compress: true },
204
+ };
205
+ const buf = encodeJob([page]);
206
+ const blackRows: number[] = [];
207
+ const redRows: number[] = [];
208
+ for (let i = 0; i < buf.length - 4; i++) {
209
+ // Each compressed row is [0x77 0x01|0x02 0x02 0xA7 0x00] for an empty
210
+ // 696-pin row (90 zero bytes → 2 PackBits bytes).
211
+ if (buf[i] === 0x77 && buf[i + 2] === 2 && buf[i + 3] === 0xa7 && buf[i + 4] === 0x00) {
212
+ if (buf[i + 1] === 0x01) blackRows.push(i);
213
+ if (buf[i + 1] === 0x02) redRows.push(i);
214
+ }
215
+ }
216
+ expect(blackRows.length).toBe(2);
217
+ expect(redRows.length).toBe(2);
218
+ });
173
219
  });
174
220
 
175
221
  describe('buildRasterMode', () => {
@@ -33,44 +33,53 @@ describe('parseStatus', () => {
33
33
  it('returns ready=true with no errors', () => {
34
34
  const status = parseStatus(makeStatusBytes());
35
35
  expect(status.ready).toBe(true);
36
- expect(status.errors).toHaveLength(0);
36
+ expect(status.errors).toEqual([]);
37
37
  });
38
38
 
39
- it('parses media width and type', () => {
39
+ it('resolves 62mm continuous to detectedMedia', () => {
40
40
  const status = parseStatus(makeStatusBytes({ mediaWidthMm: 62, mediaTypeByte: 0x0a }));
41
- expect(status.mediaWidthMm).toBe(62);
42
- expect(status.mediaType).toBe('continuous');
41
+ expect(status.mediaLoaded).toBe(true);
42
+ expect(status.detectedMedia?.id).toBe(259);
43
+ expect(status.detectedMedia?.widthMm).toBe(62);
44
+ expect(status.detectedMedia?.type).toBe('continuous');
43
45
  });
44
46
 
45
- it('parses media length from byte 17 (0 for continuous, mm for die-cut)', () => {
46
- const cont = parseStatus(makeStatusBytes({ mediaLengthMm: 0 }));
47
- expect(cont.mediaLengthMm).toBe(0);
48
- const diecut = parseStatus(makeStatusBytes({ mediaTypeByte: 0x0b, mediaLengthMm: 90 }));
49
- expect(diecut.mediaLengthMm).toBe(90);
47
+ it('resolves 62x29mm die-cut to detectedMedia', () => {
48
+ const status = parseStatus(
49
+ makeStatusBytes({ mediaWidthMm: 62, mediaTypeByte: 0x0b, mediaLengthMm: 29 }),
50
+ );
51
+ expect(status.detectedMedia?.id).toBe(274);
52
+ expect(status.detectedMedia?.type).toBe('die-cut');
53
+ expect(status.detectedMedia?.heightMm).toBe(29);
50
54
  });
51
55
 
52
- it('parses die-cut media type', () => {
53
- const status = parseStatus(makeStatusBytes({ mediaTypeByte: 0x0b }));
54
- expect(status.mediaType).toBe('die-cut');
56
+ it('leaves detectedMedia undefined for unknown media', () => {
57
+ const status = parseStatus(makeStatusBytes({ mediaWidthMm: 100, mediaTypeByte: 0x0a }));
58
+ expect(status.detectedMedia).toBeUndefined();
55
59
  });
56
60
 
57
- it('returns null mediaType for unknown byte', () => {
58
- const status = parseStatus(makeStatusBytes({ mediaTypeByte: 0xff }));
59
- expect(status.mediaType).toBeNull();
61
+ it('leaves mediaLoaded=false when width is 0', () => {
62
+ const status = parseStatus(makeStatusBytes({ mediaWidthMm: 0, mediaTypeByte: 0 }));
63
+ expect(status.mediaLoaded).toBe(false);
60
64
  });
61
65
 
62
- it('parses error info 1 bits', () => {
63
- const status = parseStatus(makeStatusBytes({ errInfo1: 0b00000001 })); // No media
64
- expect(status.errors).toContain('No media');
66
+ it('surfaces no_media error code for err1 bit 0', () => {
67
+ const status = parseStatus(makeStatusBytes({ errInfo1: 0b00000001 }));
68
+ expect(status.errors.map(e => e.code)).toContain('no_media');
65
69
  expect(status.ready).toBe(false);
66
70
  });
67
71
 
68
- it('parses error info 2 bits', () => {
69
- const status = parseStatus(makeStatusBytes({ errInfo2: 0b00010000 })); // Cover open
70
- expect(status.errors).toContain('Cover open');
72
+ it('surfaces cover_open error code for err2 bit 4', () => {
73
+ const status = parseStatus(makeStatusBytes({ errInfo2: 0b00010000 }));
74
+ expect(status.errors.map(e => e.code)).toContain('cover_open');
71
75
  expect(status.ready).toBe(false);
72
76
  });
73
77
 
78
+ it('surfaces cutter_jam error code for err1 bit 2', () => {
79
+ const status = parseStatus(makeStatusBytes({ errInfo1: 0b00000100 }));
80
+ expect(status.errors.map(e => e.code)).toContain('cutter_jam');
81
+ });
82
+
74
83
  it('ready=false when statusType is error (0x02)', () => {
75
84
  const status = parseStatus(makeStatusBytes({ statusType: 0x02 }));
76
85
  expect(status.ready).toBe(false);
@@ -82,7 +91,7 @@ describe('parseStatus', () => {
82
91
  expect(status.rawBytes).toEqual(bytes);
83
92
  });
84
93
 
85
- it('editorLiteMode is false (detected at discovery time, not from status bytes)', () => {
94
+ it('editorLiteMode is on the BrotherQLStatus extension', () => {
86
95
  const status = parseStatus(makeStatusBytes());
87
96
  expect(status.editorLiteMode).toBe(false);
88
97
  });
package/src/devices.ts CHANGED
@@ -1,199 +1,214 @@
1
- import { type DeviceDescriptor } from './types.js';
1
+ import type { BrotherQLDevice } from './types.js';
2
2
 
3
3
  const MASS_STORAGE_PIDS = new Set([0x20aa, 0x20ab]);
4
4
 
5
5
  export const DEVICES = {
6
6
  QL_820NWB: {
7
7
  name: 'QL-820NWB',
8
+ family: 'brother-ql',
9
+ transports: ['usb', 'webusb', 'tcp', 'serial', 'web-serial'],
8
10
  vid: 0x04f9,
9
11
  pid: 0x20a7,
10
12
  headPins: 720,
11
13
  bytesPerRow: 90,
12
14
  twoColor: true,
13
15
  network: 'wifi+wired',
14
- bluetooth: false,
15
16
  autocut: true,
16
17
  compression: true,
17
18
  editorLite: true,
18
19
  },
19
20
  QL_820NWBc: {
20
21
  name: 'QL-820NWBc',
22
+ family: 'brother-ql',
23
+ transports: ['usb', 'webusb', 'tcp', 'serial', 'web-serial'],
21
24
  vid: 0x04f9,
22
25
  pid: 0x209d,
23
26
  headPins: 720,
24
27
  bytesPerRow: 90,
25
28
  twoColor: true,
26
29
  network: 'wifi+wired',
27
- bluetooth: false,
28
30
  autocut: true,
29
31
  compression: true,
30
32
  editorLite: true,
31
33
  },
32
34
  QL_810W: {
33
35
  name: 'QL-810W',
36
+ family: 'brother-ql',
37
+ transports: ['usb', 'webusb', 'tcp'],
34
38
  vid: 0x04f9,
35
39
  pid: 0x209c,
36
40
  headPins: 720,
37
41
  bytesPerRow: 90,
38
42
  twoColor: true,
39
43
  network: 'wifi',
40
- bluetooth: false,
41
44
  autocut: true,
42
45
  compression: true,
43
46
  editorLite: true,
44
47
  },
45
48
  QL_800: {
46
49
  name: 'QL-800',
50
+ family: 'brother-ql',
51
+ transports: ['usb', 'webusb'],
47
52
  vid: 0x04f9,
48
53
  pid: 0x209b,
49
54
  headPins: 720,
50
55
  bytesPerRow: 90,
51
56
  twoColor: true,
52
57
  network: 'none',
53
- bluetooth: false,
54
58
  autocut: true,
55
59
  compression: true,
56
60
  editorLite: true,
57
61
  },
58
62
  QL_720NW: {
59
63
  name: 'QL-720NW',
64
+ family: 'brother-ql',
65
+ transports: ['usb', 'webusb', 'tcp'],
60
66
  vid: 0x04f9,
61
67
  pid: 0x2045,
62
68
  headPins: 720,
63
69
  bytesPerRow: 90,
64
70
  twoColor: false,
65
71
  network: 'wired',
66
- bluetooth: false,
67
72
  autocut: true,
68
73
  compression: true,
69
74
  editorLite: false,
70
75
  },
71
76
  QL_710W: {
72
77
  name: 'QL-710W',
78
+ family: 'brother-ql',
79
+ transports: ['usb', 'webusb', 'tcp'],
73
80
  vid: 0x04f9,
74
81
  pid: 0x2044,
75
82
  headPins: 720,
76
83
  bytesPerRow: 90,
77
84
  twoColor: false,
78
85
  network: 'wifi',
79
- bluetooth: false,
80
86
  autocut: true,
81
87
  compression: true,
82
88
  editorLite: true,
83
89
  },
84
90
  QL_700: {
85
91
  name: 'QL-700',
92
+ family: 'brother-ql',
93
+ transports: ['usb', 'webusb'],
86
94
  vid: 0x04f9,
87
95
  pid: 0x2042,
88
96
  headPins: 720,
89
97
  bytesPerRow: 90,
90
98
  twoColor: false,
91
99
  network: 'none',
92
- bluetooth: false,
93
100
  autocut: true,
94
101
  compression: true,
95
102
  editorLite: true,
96
103
  },
97
104
  QL_600: {
98
105
  name: 'QL-600',
106
+ family: 'brother-ql',
107
+ transports: ['usb', 'webusb'],
99
108
  vid: 0x04f9,
100
109
  pid: 0x2100,
101
110
  headPins: 720,
102
111
  bytesPerRow: 90,
103
112
  twoColor: false,
104
113
  network: 'none',
105
- bluetooth: false,
106
114
  autocut: true,
107
115
  compression: true,
108
116
  editorLite: false,
109
117
  },
110
118
  QL_580N: {
111
119
  name: 'QL-580N',
120
+ family: 'brother-ql',
121
+ transports: ['usb', 'webusb', 'tcp'],
112
122
  vid: 0x04f9,
113
123
  pid: 0x201b,
114
124
  headPins: 720,
115
125
  bytesPerRow: 90,
116
126
  twoColor: false,
117
127
  network: 'wired',
118
- bluetooth: false,
119
128
  autocut: true,
120
129
  compression: true,
121
130
  editorLite: false,
122
131
  },
123
132
  QL_570: {
124
133
  name: 'QL-570',
134
+ family: 'brother-ql',
135
+ transports: ['usb', 'webusb'],
125
136
  vid: 0x04f9,
126
137
  pid: 0x2019,
127
138
  headPins: 720,
128
139
  bytesPerRow: 90,
129
140
  twoColor: false,
130
141
  network: 'none',
131
- bluetooth: false,
132
142
  autocut: true,
133
143
  compression: true,
134
144
  editorLite: false,
135
145
  },
136
146
  QL_560: {
137
147
  name: 'QL-560',
148
+ family: 'brother-ql',
149
+ transports: ['usb', 'webusb'],
138
150
  vid: 0x04f9,
139
151
  pid: 0x2018,
140
152
  headPins: 720,
141
153
  bytesPerRow: 90,
142
154
  twoColor: false,
143
155
  network: 'none',
144
- bluetooth: false,
145
156
  autocut: true,
146
157
  compression: false,
147
158
  editorLite: false,
148
159
  },
149
160
  QL_550: {
150
161
  name: 'QL-550',
162
+ family: 'brother-ql',
163
+ transports: ['usb', 'webusb'],
151
164
  vid: 0x04f9,
152
165
  pid: 0x2016,
153
166
  headPins: 720,
154
167
  bytesPerRow: 90,
155
168
  twoColor: false,
156
169
  network: 'none',
157
- bluetooth: false,
158
170
  autocut: false,
159
171
  compression: false,
160
172
  editorLite: false,
161
173
  },
162
174
  QL_500: {
163
175
  name: 'QL-500',
176
+ family: 'brother-ql',
177
+ transports: ['usb', 'webusb'],
164
178
  vid: 0x04f9,
165
179
  pid: 0x2013,
166
180
  headPins: 720,
167
181
  bytesPerRow: 90,
168
182
  twoColor: false,
169
183
  network: 'none',
170
- bluetooth: false,
171
184
  autocut: false,
172
185
  compression: false,
173
186
  editorLite: false,
174
187
  },
175
188
  QL_650TD: {
176
189
  name: 'QL-650TD',
190
+ family: 'brother-ql',
191
+ transports: ['usb', 'webusb'],
177
192
  vid: 0x04f9,
178
193
  pid: 0x201c,
179
194
  headPins: 720,
180
195
  bytesPerRow: 90,
181
196
  twoColor: false,
182
197
  network: 'none',
183
- bluetooth: false,
184
198
  autocut: true,
185
199
  compression: true,
186
200
  editorLite: false,
187
201
  },
188
202
  QL_1100: {
189
203
  name: 'QL-1100',
204
+ family: 'brother-ql',
205
+ transports: ['usb', 'webusb'],
190
206
  vid: 0x04f9,
191
207
  pid: 0x20a8,
192
208
  headPins: 1296,
193
209
  bytesPerRow: 162,
194
210
  twoColor: false,
195
211
  network: 'none',
196
- bluetooth: false,
197
212
  autocut: true,
198
213
  compression: true,
199
214
  editorLite: true,
@@ -201,13 +216,14 @@ export const DEVICES = {
201
216
  },
202
217
  QL_1110NWB: {
203
218
  name: 'QL-1110NWB',
219
+ family: 'brother-ql',
220
+ transports: ['usb', 'webusb', 'tcp'],
204
221
  vid: 0x04f9,
205
222
  pid: 0x20a9,
206
223
  headPins: 1296,
207
224
  bytesPerRow: 162,
208
225
  twoColor: false,
209
226
  network: 'wifi+wired',
210
- bluetooth: false,
211
227
  autocut: true,
212
228
  compression: true,
213
229
  editorLite: true,
@@ -215,46 +231,49 @@ export const DEVICES = {
215
231
  },
216
232
  QL_1115NWB: {
217
233
  name: 'QL-1115NWB',
234
+ family: 'brother-ql',
235
+ transports: ['usb', 'webusb', 'tcp'],
218
236
  vid: 0x04f9,
219
237
  pid: 0x20ac,
220
238
  headPins: 1296,
221
239
  bytesPerRow: 162,
222
240
  twoColor: false,
223
241
  network: 'wifi+wired',
224
- bluetooth: false,
225
242
  autocut: true,
226
243
  compression: true,
227
244
  editorLite: true,
228
245
  },
229
246
  QL_1050: {
230
247
  name: 'QL-1050',
248
+ family: 'brother-ql',
249
+ transports: ['usb', 'webusb'],
231
250
  vid: 0x04f9,
232
251
  pid: 0x2027,
233
252
  headPins: 1296,
234
253
  bytesPerRow: 162,
235
254
  twoColor: false,
236
255
  network: 'none',
237
- bluetooth: false,
238
256
  autocut: true,
239
257
  compression: true,
240
258
  editorLite: false,
241
259
  },
242
260
  QL_1060N: {
243
261
  name: 'QL-1060N',
262
+ family: 'brother-ql',
263
+ transports: ['usb', 'webusb', 'tcp'],
244
264
  vid: 0x04f9,
245
265
  pid: 0x2028,
246
266
  headPins: 1296,
247
267
  bytesPerRow: 162,
248
268
  twoColor: false,
249
269
  network: 'wired',
250
- bluetooth: false,
251
270
  autocut: true,
252
271
  compression: true,
253
272
  editorLite: false,
254
273
  },
255
- } as const satisfies Record<string, DeviceDescriptor>;
274
+ } as const satisfies Record<string, BrotherQLDevice>;
256
275
 
257
- export function findDevice(vid: number, pid: number): DeviceDescriptor | undefined {
276
+ export function findDevice(vid: number, pid: number): BrotherQLDevice | undefined {
258
277
  return Object.values(DEVICES).find(d => d.vid === vid && d.pid === pid);
259
278
  }
260
279
 
package/src/index.ts CHANGED
@@ -1,22 +1,56 @@
1
- export type { LabelBitmap, RawImageData } from '@mbtech-nl/bitmap';
2
- export { renderText, renderImage, rotateBitmap, flipHorizontal } from '@mbtech-nl/bitmap';
1
+ export type { LabelBitmap, PaletteEntry, RawImageData } from '@mbtech-nl/bitmap';
2
+ export {
3
+ flipHorizontal,
4
+ renderImage,
5
+ renderMultiPlaneImage,
6
+ renderText,
7
+ rotateBitmap,
8
+ } from '@mbtech-nl/bitmap';
9
+
10
+ export type {
11
+ DeviceDescriptor,
12
+ MediaDescriptor,
13
+ PreviewOptions,
14
+ PreviewPlane,
15
+ PreviewResult,
16
+ PrintOptions,
17
+ PrinterAdapter,
18
+ PrinterError,
19
+ PrinterStatus,
20
+ RotateDirection,
21
+ Transport,
22
+ TransportType,
23
+ } from '@thermal-label/contracts';
24
+
25
+ export {
26
+ MediaNotSpecifiedError,
27
+ pickRotation,
28
+ UnsupportedOperationError,
29
+ } from '@thermal-label/contracts';
3
30
 
4
31
  export { DEVICES, findDevice, isMassStorageMode } from './devices.js';
5
- export { MEDIA, findMedia, findMediaByWidth } from './media.js';
32
+ export {
33
+ DEFAULT_MEDIA,
34
+ MEDIA,
35
+ findMedia,
36
+ findMediaByDimensions,
37
+ findMediaByWidth,
38
+ } from './media.js';
39
+ export { ROTATE_DIRECTION } from './orientation.js';
6
40
  export { encodeJob } from './protocol.js';
7
41
  export { parseStatus, STATUS_REQUEST } from './status.js';
42
+ export { createPreviewOffline } from './preview.js';
8
43
 
9
44
  export type {
10
- MediaType,
11
- HeadWidth,
45
+ BrotherQLDevice,
46
+ BrotherQLMedia,
47
+ BrotherQLPrintOptions,
48
+ BrotherQLStatus,
12
49
  ColorMode,
50
+ HeadWidth,
51
+ JobOptions,
52
+ MediaType,
13
53
  NetworkSupport,
14
- DeviceDescriptor,
15
- MediaDescriptor,
16
54
  PageData,
17
55
  PageOptions,
18
- JobOptions,
19
- PrinterStatus,
20
- TextPrintOptions,
21
- ImagePrintOptions,
22
56
  } from './types.js';