@thermal-label/brother-ql-web 0.5.0 → 0.6.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/printer.js CHANGED
@@ -1,5 +1,5 @@
1
- import { DEFAULT_MEDIA, DEVICES, ROTATE_DIRECTION, STATUS_REQUEST, createPreviewOffline, encodeJobForEngine, findDevice, flipHorizontal, parseStatus, pickRotation, renderImage, renderMultiPlaneImage, } from '@thermal-label/brother-ql-core';
2
- import { MediaNotSpecifiedError } from '@thermal-label/contracts';
1
+ import { DEFAULT_MEDIA, DEVICES, ROTATE_DIRECTION, STATUS_REQUEST, buildInitialize, buildInvalidate, createPreviewOffline, encodeJobForEngine, findDevice, flipHorizontal, parseStatus, pickRotation, renderImage, renderMultiPlaneImage, } from '@thermal-label/brother-ql-core';
2
+ import { MediaNotSpecifiedError, pollingOnStatus, WriteSerializer } from '@thermal-label/contracts';
3
3
  import { WebUsbTransport } from '@thermal-label/transport/web';
4
4
  // Detect transport errors across module boundaries — under pnpm link /
5
5
  // multi-version installs `instanceof` checks against the contracts
@@ -9,11 +9,12 @@ function isTransportClosedError(err) {
9
9
  return err instanceof Error && err.name === 'TransportClosedError';
10
10
  }
11
11
  const STATUS_BYTE_COUNT = 32;
12
- // Brother QL printers push unsolicited 32-byte status frames on lid
13
- // open/close, media insert, end of job, errors, etc. We run a
14
- // persistent read loop that picks up every frame, parses it, and
15
- // notifies subscribers instant updates with no polling. `getStatus()`
16
- // writes ESC iS and awaits the next frame from the same stream.
12
+ // A persistent read loop is the sole reader of the bulk-IN pipe: it
13
+ // parses every 32-byte status frame the printer emits and dispatches it
14
+ // to `statusListeners`. `getStatus()` writes ESC iS and awaits the next
15
+ // frame from that stream; spontaneous frames (lid open/close, media
16
+ // insert, end of job, errors) flow through the same loop. `onStatus()`
17
+ // is a polling shim over `getStatus()` — see that method.
17
18
  const STATUS_RESPONSE_TIMEOUT_MS = 1500;
18
19
  const READ_LOOP_BACKOFF_MS = 100;
19
20
  // Same OUT-pipe chunking as the Node driver — see packages/node/src/printer.ts
@@ -37,6 +38,27 @@ export class WebBrotherQLPrinter {
37
38
  statusListeners = new Set();
38
39
  readLoopStarted = false;
39
40
  readLoopStopped = false;
41
+ /**
42
+ * Serialises every bulk-OUT operation (print + getStatus). Required
43
+ * because `getStatus()` may write the QL preamble (`buildInvalidate` —
44
+ * 200×0x00 + `ESC @`) to put the parser in a known state, and the
45
+ * preamble's "invalidate" cancels any in-flight print job. Polling
46
+ * concurrently with a print would shred the raster stream.
47
+ *
48
+ * Plan 15 A4: this was a hand-rolled `writeLock`/`runLocked` pair;
49
+ * it is now the shared `WriteSerializer` from `@thermal-label/contracts`
50
+ * so all four drivers serialise identically. Behaviour is unchanged —
51
+ * `WriteSerializer.run()` is exactly the old `runLocked` semantics.
52
+ */
53
+ serializer = new WriteSerializer();
54
+ /**
55
+ * Whether the printer's command parser is in a known-clean state.
56
+ * Set to `true` after a successful `getStatus()`; flipped back to
57
+ * `false` on timeout so the next attempt re-sends the preamble. The
58
+ * preamble (200-byte invalidate + `ESC @`) is only needed once per
59
+ * session unless the parser falls back into a confused state.
60
+ */
61
+ parserReady = false;
40
62
  constructor(device, transport) {
41
63
  this.device = device;
42
64
  this.transport = transport;
@@ -57,7 +79,16 @@ export class WebBrotherQLPrinter {
57
79
  // on the right side of the printed face when the leading edge is held
58
80
  // up. Mirror the rendered bitmap so the input image's x-axis matches
59
81
  // the printed x-axis. Verified on QL-820NWBc + DK-22251.
60
- const pageOptions = options?.highRes === true ? { highResolution: true } : undefined;
82
+ // PackBits compression on by default for the web path. Bench
83
+ // experience: WebUSB pacing alone (1024 / 20 ms) isn't enough on
84
+ // QL_700-class firmware — uncompressed raster rows can stall the
85
+ // print engine even when bytes are arriving. Compression keeps
86
+ // each row small enough to ride the firmware's buffer comfortably
87
+ // and matches the encoding the Brother driver itself emits.
88
+ const pageOptions = {
89
+ compress: true,
90
+ ...(options?.highRes === true ? { highResolution: true } : {}),
91
+ };
61
92
  let page;
62
93
  if (resolvedMedia.palette) {
63
94
  const { black, red } = renderMultiPlaneImage(image, {
@@ -68,7 +99,7 @@ export class WebBrotherQLPrinter {
68
99
  bitmap: flipHorizontal(black),
69
100
  redBitmap: flipHorizontal(red),
70
101
  media: resolvedMedia,
71
- ...(pageOptions ? { options: pageOptions } : {}),
102
+ options: pageOptions,
72
103
  };
73
104
  }
74
105
  else {
@@ -76,13 +107,13 @@ export class WebBrotherQLPrinter {
76
107
  page = {
77
108
  bitmap,
78
109
  media: resolvedMedia,
79
- ...(pageOptions ? { options: pageOptions } : {}),
110
+ options: pageOptions,
80
111
  };
81
112
  }
82
113
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- every brother-ql device has at least one engine (data invariant)
83
114
  const engine = this.device.engines[0];
84
115
  const bytes = encodeJobForEngine([page], {}, engine, this.device.name);
85
- await this.writeChunked(bytes);
116
+ await this.serializer.run(() => this.writeChunked(bytes));
86
117
  }
87
118
  async writeChunked(bytes) {
88
119
  for (let off = 0; off < bytes.length; off += USB_CHUNK_SIZE) {
@@ -111,23 +142,51 @@ export class WebBrotherQLPrinter {
111
142
  * `getStatus()` subscribes transiently, writes the request, and the
112
143
  * subscription receives the response (alongside any spontaneous
113
144
  * frames; see `onStatus()`).
145
+ *
146
+ * The QL preamble (200×0x00 invalidate + `ESC @` initialize) is
147
+ * sent only when the parser hasn't been confirmed clean — first
148
+ * call of the session, or after a previous timeout. Steady-state
149
+ * polls send bare `ESC iS`. Bench observation: a freshly-opened QL
150
+ * doesn't reply to bare `ESC iS` until the invalidate flushes any
151
+ * stale parser state from a prior session.
114
152
  */
115
153
  async getStatus() {
116
- const next = this.nextStatusFrame(STATUS_RESPONSE_TIMEOUT_MS);
117
- await this.transport.write(STATUS_REQUEST);
118
- return next;
154
+ return this.serializer.run(async () => {
155
+ const next = this.nextStatusFrame(STATUS_RESPONSE_TIMEOUT_MS);
156
+ if (!this.parserReady) {
157
+ await this.transport.write(buildInvalidate());
158
+ await this.transport.write(buildInitialize());
159
+ }
160
+ await this.transport.write(STATUS_REQUEST);
161
+ try {
162
+ const status = await next;
163
+ this.parserReady = true;
164
+ return status;
165
+ }
166
+ catch (err) {
167
+ // Timeout / read failure — printer may be in a confused
168
+ // state. Re-arm the preamble for the next attempt.
169
+ this.parserReady = false;
170
+ throw err;
171
+ }
172
+ });
119
173
  }
120
174
  /**
121
- * Subscribe to push-based status updates. Brother QL printers emit
122
- * unsolicited frames on lid open/close, media insert, errors, and
123
- * end-of-job each one fires `cb` synchronously after parsing.
124
- * Returns an unsubscribe function.
175
+ * Subscribe to status updates. A polling shim built on
176
+ * `pollingOnStatus` from contracts it calls `getStatus()` on first
177
+ * subscribe and then every `DEFAULT_POLLING_INTERVAL_MS`, matching the
178
+ * labelwriter and labelmanager web drivers (plan 11 §`onStatus`
179
+ * parity).
180
+ *
181
+ * An earlier revision skipped polling and relied solely on the
182
+ * printer's unsolicited frames. That was a workaround for the Chromium
183
+ * WebUSB sub-packet stall — `getStatus()`'s `read()` would hang, so
184
+ * polling looked unreliable and was dropped. `WebUsbTransport.read()`
185
+ * now rounds reads up to the endpoint packet size, so `getStatus()` is
186
+ * dependable and polling is restored.
125
187
  */
126
188
  onStatus(cb) {
127
- this.statusListeners.add(cb);
128
- return () => {
129
- this.statusListeners.delete(cb);
130
- };
189
+ return pollingOnStatus(this, cb);
131
190
  }
132
191
  nextStatusFrame(timeoutMs) {
133
192
  return new Promise((resolve, reject) => {
@@ -144,6 +203,7 @@ export class WebBrotherQLPrinter {
144
203
  });
145
204
  }
146
205
  startReadLoop() {
206
+ /* v8 ignore next -- defensive: startReadLoop is only ever called once, from the constructor, where readLoopStarted is still false; the re-entry guard can never be true */
147
207
  if (this.readLoopStarted)
148
208
  return;
149
209
  this.readLoopStarted = true;
@@ -183,6 +243,7 @@ export class WebBrotherQLPrinter {
183
243
  for (const cb of snapshot) {
184
244
  try {
185
245
  cb(status);
246
+ /* v8 ignore next 4 -- defensive: the only registrant of statusListeners is nextStatusFrame's internal handler (clearTimeout + delete + resolve), which cannot throw; kept for future persistent-listener callers */
186
247
  }
187
248
  catch (err) {
188
249
  // eslint-disable-next-line no-console -- driver-level diagnostic
@@ -206,16 +267,46 @@ export const DEFAULT_FILTERS = Object.values(DEVICES)
206
267
  *
207
268
  * Requires a user gesture. Opens the device and claims interface 0 via
208
269
  * `WebUsbTransport.fromDevice()`.
270
+ *
271
+ * Single-instance entry point — preserved for back-compat with existing
272
+ * consumers (CLIs, ad-hoc scripts). For the symmetric driver-web shape
273
+ * (1-key map keyed by engine role) call `requestPrinters()` instead;
274
+ * the harness shell uses that path.
275
+ *
276
+ * @deprecated Use `requestPrinters({ transport: 'usb' })` from
277
+ * `./request-printers.ts`. Removed once consumers migrate (plan 11).
209
278
  */
210
279
  export async function requestPrinter(options = {}) {
211
280
  const filters = options.filters ?? DEFAULT_FILTERS;
212
281
  const usbDevice = await navigator.usb.requestDevice({ filters });
282
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- legacy alias chain; the deprecation guidance is aimed at external callers, not internal usage
213
283
  return fromUSBDevice(usbDevice);
214
284
  }
285
+ /**
286
+ * Show the browser's USB picker and return one `PrinterAdapter` per
287
+ * drivable engine on the selected device, keyed by engine role.
288
+ *
289
+ * Brother QL devices are always single-engine — this returns a 1-key
290
+ * record keyed by the device's `engines[0].role` (typically `'primary'`).
291
+ *
292
+ * @deprecated Use the generic `requestPrinters({ transport: 'usb' })`
293
+ * from `./request-printers.ts` — the legacy USB-only name is preserved
294
+ * as `requestPrintersUsbLegacy` for back-compat. Removed once
295
+ * consumers migrate (plan 11).
296
+ */
297
+ export async function requestPrintersUsbLegacy(options = {}) {
298
+ const filters = options.filters ?? DEFAULT_FILTERS;
299
+ const usbDevice = await navigator.usb.requestDevice({ filters });
300
+ // eslint-disable-next-line @typescript-eslint/no-deprecated -- legacy alias chain
301
+ return fromUSBDeviceAll(usbDevice);
302
+ }
215
303
  /**
216
304
  * Wrap an already-selected `USBDevice`.
217
305
  *
218
306
  * @throws when the VID/PID is not in the Brother QL registry.
307
+ *
308
+ * @deprecated Use `requestPrinters({ transport: 'usb' })` from
309
+ * `./request-printers.ts`. Removed once consumers migrate (plan 11).
219
310
  */
220
311
  export async function fromUSBDevice(usbDevice) {
221
312
  const descriptor = findDevice(usbDevice.vendorId, usbDevice.productId);
@@ -225,4 +316,29 @@ export async function fromUSBDevice(usbDevice) {
225
316
  const transport = await WebUsbTransport.fromDevice(usbDevice);
226
317
  return new WebBrotherQLPrinter(descriptor, transport);
227
318
  }
319
+ /**
320
+ * Wrap an already-selected `USBDevice` and return a 1-key adapter map
321
+ * keyed by the device's `engines[0].role`. Public surface for
322
+ * `requestPrinters()`; exported so harnesses that already hold a
323
+ * `USBDevice` (e.g. picked-up via `navigator.usb.getDevices()` on a
324
+ * returning visit) can skip the picker.
325
+ *
326
+ * Brother QL is single-engine and single-interface (IF 0).
327
+ *
328
+ * @deprecated Use `requestPrinters({ transport: 'usb' })` from
329
+ * `./request-printers.ts`. Removed once consumers migrate (plan 11).
330
+ */
331
+ export async function fromUSBDeviceAll(usbDevice) {
332
+ const descriptor = findDevice(usbDevice.vendorId, usbDevice.productId);
333
+ if (!descriptor) {
334
+ throw new Error(`Unsupported USB device: VID=0x${usbDevice.vendorId.toString(16)} PID=0x${usbDevice.productId.toString(16)}`);
335
+ }
336
+ const engine = descriptor.engines[0];
337
+ /* v8 ignore next 3 -- defensive: every brother-ql registry entry declares at least one engine (data invariant); guard kept against a malformed future registry edit */
338
+ if (!engine) {
339
+ throw new Error(`Device ${descriptor.key} has no engines.`);
340
+ }
341
+ const transport = await WebUsbTransport.fromDevice(usbDevice);
342
+ return { [engine.role]: new WebBrotherQLPrinter(descriptor, transport) };
343
+ }
228
344
  //# sourceMappingURL=printer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"printer.js","sourceRoot":"","sources":["../src/printer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"printer.js","sourceRoot":"","sources":["../src/printer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type ConnectOptions, type DeviceEntry, type PrinterAdapterMap, type TransportType } from '@thermal-label/contracts';
2
+ /**
3
+ * Unified browser-picker factory for the brother-ql driver family.
4
+ *
5
+ * Dispatches on `opts.transport`:
6
+ *
7
+ * - `'usb'` — opens `navigator.usb` picker. Auto-identifies via
8
+ * `usbDevice.vendorId/productId` against the registry. Throws
9
+ * `DeviceIdentificationRequiredError` only if the picked device's
10
+ * VID/PID is not in the brother-ql registry.
11
+ * - `'bluetooth-spp'` — always-ask (Web Serial has no BT name
12
+ * surface). `opts.deviceKey` required; if omitted, throws
13
+ * `DeviceIdentificationRequiredError` with the BT-SPP-capable
14
+ * subset of `DEVICES` (e.g. QL_820NWBc, PT_P910BT).
15
+ * `continueWith(deviceKey)` opens the Web Serial picker for the
16
+ * chosen device.
17
+ * - `'serial'` — not declared in the brother-ql registry today;
18
+ * throws unconditionally.
19
+ * - `'bluetooth-gatt'` — not declared in the brother-ql registry today;
20
+ * throws unconditionally.
21
+ *
22
+ * Returns a 1-key `PrinterAdapterMap` keyed by the device's primary
23
+ * engine role.
24
+ */
25
+ export declare function requestPrinters(opts: ConnectOptions): Promise<PrinterAdapterMap>;
26
+ /**
27
+ * Filter the registry to entries declaring `transport`. Used to
28
+ * populate `DeviceIdentificationRequiredError.candidates`.
29
+ */
30
+ export declare function devicesForTransport(transport: TransportType): readonly DeviceEntry[];
31
+ //# sourceMappingURL=request-printers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-printers.d.ts","sourceRoot":"","sources":["../src/request-printers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EAEtB,KAAK,aAAa,EACnB,MAAM,0BAA0B,CAAC;AAKlC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAWtF;AAgFD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,aAAa,GAAG,SAAS,WAAW,EAAE,CAEpF"}
@@ -0,0 +1,109 @@
1
+ import { DeviceIdentificationRequiredError, } from '@thermal-label/contracts';
2
+ import { DEVICES, findDevice } from '@thermal-label/brother-ql-core';
3
+ import { WebSerialTransport, WebUsbTransport } from '@thermal-label/transport/web';
4
+ import { DEFAULT_FILTERS, WebBrotherQLPrinter } from './printer.js';
5
+ /**
6
+ * Unified browser-picker factory for the brother-ql driver family.
7
+ *
8
+ * Dispatches on `opts.transport`:
9
+ *
10
+ * - `'usb'` — opens `navigator.usb` picker. Auto-identifies via
11
+ * `usbDevice.vendorId/productId` against the registry. Throws
12
+ * `DeviceIdentificationRequiredError` only if the picked device's
13
+ * VID/PID is not in the brother-ql registry.
14
+ * - `'bluetooth-spp'` — always-ask (Web Serial has no BT name
15
+ * surface). `opts.deviceKey` required; if omitted, throws
16
+ * `DeviceIdentificationRequiredError` with the BT-SPP-capable
17
+ * subset of `DEVICES` (e.g. QL_820NWBc, PT_P910BT).
18
+ * `continueWith(deviceKey)` opens the Web Serial picker for the
19
+ * chosen device.
20
+ * - `'serial'` — not declared in the brother-ql registry today;
21
+ * throws unconditionally.
22
+ * - `'bluetooth-gatt'` — not declared in the brother-ql registry today;
23
+ * throws unconditionally.
24
+ *
25
+ * Returns a 1-key `PrinterAdapterMap` keyed by the device's primary
26
+ * engine role.
27
+ */
28
+ export async function requestPrinters(opts) {
29
+ switch (opts.transport) {
30
+ case 'usb':
31
+ return requestPrintersUsb(opts);
32
+ case 'bluetooth-spp':
33
+ return requestPrintersBluetoothSpp(opts);
34
+ case 'serial':
35
+ throw new Error('brother-ql: serial transport not declared in the registry');
36
+ case 'bluetooth-gatt':
37
+ throw new Error('brother-ql: bluetooth-gatt transport not declared in the registry');
38
+ }
39
+ }
40
+ async function requestPrintersUsb(opts) {
41
+ const filters = DEFAULT_FILTERS;
42
+ const usbDevice = await navigator.usb.requestDevice({ filters });
43
+ if (opts.deviceKey !== undefined) {
44
+ const entry = entryByKey(opts.deviceKey);
45
+ if (!entry) {
46
+ throw new Error(`requestPrinters(usb): unknown deviceKey "${opts.deviceKey}"`);
47
+ }
48
+ const transport = await WebUsbTransport.fromDevice(usbDevice);
49
+ return adapterMap(entry, transport);
50
+ }
51
+ const entry = findDevice(usbDevice.vendorId, usbDevice.productId);
52
+ if (entry) {
53
+ const transport = await WebUsbTransport.fromDevice(usbDevice);
54
+ return adapterMap(entry, transport);
55
+ }
56
+ // No registry match — let the caller pick from the USB-capable
57
+ // candidates and keep the same USBDevice across the
58
+ // `continueWith` resume.
59
+ throw new DeviceIdentificationRequiredError(devicesForTransport('usb'), async (deviceKey) => {
60
+ const chosen = entryByKey(deviceKey);
61
+ if (!chosen) {
62
+ throw new Error(`continueWith: unknown deviceKey "${deviceKey}"`);
63
+ }
64
+ const transport = await WebUsbTransport.fromDevice(usbDevice);
65
+ return adapterMap(chosen, transport);
66
+ });
67
+ }
68
+ function requestPrintersBluetoothSpp(opts) {
69
+ if (opts.deviceKey === undefined) {
70
+ return Promise.reject(new DeviceIdentificationRequiredError(devicesForTransport('bluetooth-spp'), deviceKey => openBluetoothSpp(deviceKey, opts.baudRate)));
71
+ }
72
+ return openBluetoothSpp(opts.deviceKey, opts.baudRate);
73
+ }
74
+ async function openBluetoothSpp(deviceKey, baudRate) {
75
+ const entry = entryByKey(deviceKey);
76
+ if (!entry) {
77
+ throw new Error(`requestPrinters(bluetooth-spp): unknown deviceKey "${deviceKey}"`);
78
+ }
79
+ if (!entry.transports['bluetooth-spp']) {
80
+ throw new Error(`requestPrinters(bluetooth-spp): ${deviceKey} does not declare bluetooth-spp transport`);
81
+ }
82
+ // SPP baud is negotiated on the link; default to 9600 when not
83
+ // specified.
84
+ const transport = await WebSerialTransport.request(undefined, baudRate ?? 9600);
85
+ return adapterMap(entry, transport);
86
+ }
87
+ function adapterMap(entry, transport) {
88
+ const engine = entry.engines[0];
89
+ /* v8 ignore next -- defensive: every brother-ql registry entry declares at least one engine (data invariant); guard kept against a malformed future registry edit */
90
+ if (!engine)
91
+ throw new Error(`Device ${entry.key} has no engines.`);
92
+ // WebBrotherQLPrinter accepts a generic Transport — the encoder is
93
+ // transport-agnostic, so the BT-SPP path is just the same printer
94
+ // class wrapped around a WebSerialTransport. Bench-confirmed on
95
+ // QL-820NWBc.
96
+ const printer = new WebBrotherQLPrinter(entry, transport);
97
+ return { [engine.role]: printer };
98
+ }
99
+ /**
100
+ * Filter the registry to entries declaring `transport`. Used to
101
+ * populate `DeviceIdentificationRequiredError.candidates`.
102
+ */
103
+ export function devicesForTransport(transport) {
104
+ return Object.values(DEVICES).filter(d => transport in d.transports);
105
+ }
106
+ function entryByKey(key) {
107
+ return DEVICES[key];
108
+ }
109
+ //# sourceMappingURL=request-printers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-printers.js","sourceRoot":"","sources":["../src/request-printers.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thermal-label/brother-ql-web",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "WebUSB browser driver for Brother QL label printers",
5
5
  "keywords": [
6
6
  "brother",
@@ -13,7 +13,7 @@
13
13
  "type": "module",
14
14
  "author": "Mannes Brak",
15
15
  "license": "MIT",
16
- "homepage": "https://thermal-label.github.io/brother-ql/",
16
+ "homepage": "https://thermal-label.github.io/brother-ql/web",
17
17
  "repository": {
18
18
  "type": "git",
19
19
  "url": "https://github.com/thermal-label/brother-ql.git",
@@ -52,9 +52,9 @@
52
52
  }
53
53
  },
54
54
  "dependencies": {
55
- "@thermal-label/contracts": "^0.5.0",
56
- "@thermal-label/transport": "^0.5.0",
57
- "@thermal-label/brother-ql-core": "0.5.0"
55
+ "@thermal-label/contracts": "^0.6.0",
56
+ "@thermal-label/transport": "^0.6.0",
57
+ "@thermal-label/brother-ql-core": "0.6.1"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "typescript": ">=5.0"