@thermal-label/brother-ql-node 0.0.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +76 -0
  3. package/dist/__tests__/discovery.test.d.ts +2 -0
  4. package/dist/__tests__/discovery.test.d.ts.map +1 -0
  5. package/dist/__tests__/discovery.test.js +77 -0
  6. package/dist/__tests__/discovery.test.js.map +1 -0
  7. package/dist/__tests__/errors.test.d.ts +2 -0
  8. package/dist/__tests__/errors.test.d.ts.map +1 -0
  9. package/dist/__tests__/errors.test.js +20 -0
  10. package/dist/__tests__/errors.test.js.map +1 -0
  11. package/dist/__tests__/integration/print-image.test.d.ts +2 -0
  12. package/dist/__tests__/integration/print-image.test.d.ts.map +1 -0
  13. package/dist/__tests__/integration/print-image.test.js +22 -0
  14. package/dist/__tests__/integration/print-image.test.js.map +1 -0
  15. package/dist/__tests__/integration/print-text.test.d.ts +2 -0
  16. package/dist/__tests__/integration/print-text.test.d.ts.map +1 -0
  17. package/dist/__tests__/integration/print-text.test.js +25 -0
  18. package/dist/__tests__/integration/print-text.test.js.map +1 -0
  19. package/dist/__tests__/integration/print-two-color.test.d.ts +2 -0
  20. package/dist/__tests__/integration/print-two-color.test.d.ts.map +1 -0
  21. package/dist/__tests__/integration/print-two-color.test.js +28 -0
  22. package/dist/__tests__/integration/print-two-color.test.js.map +1 -0
  23. package/dist/__tests__/integration/tcp.test.d.ts +2 -0
  24. package/dist/__tests__/integration/tcp.test.d.ts.map +1 -0
  25. package/dist/__tests__/integration/tcp.test.js +20 -0
  26. package/dist/__tests__/integration/tcp.test.js.map +1 -0
  27. package/dist/__tests__/printer.test.d.ts +2 -0
  28. package/dist/__tests__/printer.test.d.ts.map +1 -0
  29. package/dist/__tests__/printer.test.js +216 -0
  30. package/dist/__tests__/printer.test.js.map +1 -0
  31. package/dist/__tests__/tcp-transport.test.d.ts +2 -0
  32. package/dist/__tests__/tcp-transport.test.d.ts.map +1 -0
  33. package/dist/__tests__/tcp-transport.test.js +115 -0
  34. package/dist/__tests__/tcp-transport.test.js.map +1 -0
  35. package/dist/__tests__/usb-transport.test.d.ts +2 -0
  36. package/dist/__tests__/usb-transport.test.d.ts.map +1 -0
  37. package/dist/__tests__/usb-transport.test.js +99 -0
  38. package/dist/__tests__/usb-transport.test.js.map +1 -0
  39. package/dist/discovery.d.ts +5 -0
  40. package/dist/discovery.d.ts.map +1 -0
  41. package/dist/discovery.js +31 -0
  42. package/dist/discovery.js.map +1 -0
  43. package/dist/errors.d.ts +8 -0
  44. package/dist/errors.d.ts.map +1 -0
  45. package/dist/errors.js +15 -0
  46. package/dist/errors.js.map +1 -0
  47. package/dist/index.d.ts +9 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +7 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/printer.d.ts +18 -0
  52. package/dist/printer.d.ts.map +1 -0
  53. package/dist/printer.js +167 -0
  54. package/dist/printer.js.map +1 -0
  55. package/dist/status.d.ts +2 -0
  56. package/dist/status.d.ts.map +1 -0
  57. package/dist/status.js +2 -0
  58. package/dist/status.js.map +1 -0
  59. package/dist/transport.d.ts +32 -0
  60. package/dist/transport.d.ts.map +1 -0
  61. package/dist/transport.js +120 -0
  62. package/dist/transport.js.map +1 -0
  63. package/dist/types.d.ts +13 -0
  64. package/dist/types.d.ts.map +1 -0
  65. package/dist/types.js +2 -0
  66. package/dist/types.js.map +1 -0
  67. package/package.json +76 -0
@@ -0,0 +1,120 @@
1
+ import net from 'node:net';
2
+ import usb from 'usb';
3
+ export class UsbTransport {
4
+ outEndpoint;
5
+ inEndpoint;
6
+ iface;
7
+ device;
8
+ constructor(device) {
9
+ this.device = device;
10
+ device.open();
11
+ const iface = device.interface(0);
12
+ // On Linux the usblp kernel driver claims printer-class interfaces
13
+ // automatically — detach it before claiming with libusb.
14
+ if (process.platform === 'linux' && iface.isKernelDriverActive()) {
15
+ iface.detachKernelDriver();
16
+ }
17
+ iface.claim();
18
+ this.iface = iface;
19
+ const outEp = iface.endpoints.find((e) => e.direction === 'out');
20
+ const inEp = iface.endpoints.find((e) => e.direction === 'in');
21
+ if (!outEp)
22
+ throw new Error('USB device has no bulk OUT endpoint');
23
+ if (!inEp)
24
+ throw new Error('USB device has no bulk IN endpoint');
25
+ this.outEndpoint = outEp;
26
+ this.inEndpoint = inEp;
27
+ }
28
+ static open(vid, pid) {
29
+ const device = usb
30
+ .getDeviceList()
31
+ .find(d => d.deviceDescriptor.idVendor === vid && d.deviceDescriptor.idProduct === pid);
32
+ if (!device)
33
+ return Promise.reject(new Error(`USB device ${vid.toString(16)}:${pid.toString(16)} not found`));
34
+ return Promise.resolve(new UsbTransport(device));
35
+ }
36
+ async write(data) {
37
+ await this.outEndpoint.transferAsync(Buffer.from(data));
38
+ }
39
+ async read(byteCount) {
40
+ const buf = await this.inEndpoint.transferAsync(byteCount);
41
+ return buf ? new Uint8Array(buf) : new Uint8Array(0);
42
+ }
43
+ async close() {
44
+ await this.iface.releaseAsync();
45
+ this.device.close();
46
+ }
47
+ }
48
+ export class TcpTransport {
49
+ socket;
50
+ chunks = [];
51
+ resolveRead = null;
52
+ needed = 0;
53
+ constructor(socket) {
54
+ this.socket = socket;
55
+ socket.on('data', (chunk) => {
56
+ this.chunks.push(chunk);
57
+ this.tryResolveRead();
58
+ });
59
+ }
60
+ static async connect(host, port = 9100) {
61
+ return new Promise((resolve, reject) => {
62
+ const socket = new net.Socket();
63
+ socket.once('error', reject);
64
+ socket.connect(port, host, () => {
65
+ socket.removeListener('error', reject);
66
+ resolve(new TcpTransport(socket));
67
+ });
68
+ });
69
+ }
70
+ buffered() {
71
+ return this.chunks.reduce((sum, c) => sum + c.length, 0);
72
+ }
73
+ tryResolveRead() {
74
+ if (this.resolveRead && this.buffered() >= this.needed) {
75
+ const combined = Buffer.concat(this.chunks);
76
+ this.chunks.length = 0;
77
+ const result = combined.subarray(0, this.needed);
78
+ const remainder = combined.subarray(this.needed);
79
+ if (remainder.length > 0)
80
+ this.chunks.push(Buffer.from(remainder));
81
+ const resolve = this.resolveRead;
82
+ this.resolveRead = null;
83
+ this.needed = 0;
84
+ resolve(new Uint8Array(result));
85
+ }
86
+ }
87
+ async write(data) {
88
+ return new Promise((resolve, reject) => {
89
+ this.socket.write(Buffer.from(data), err => {
90
+ if (err)
91
+ reject(err);
92
+ else
93
+ resolve();
94
+ });
95
+ });
96
+ }
97
+ async read(byteCount) {
98
+ if (this.buffered() >= byteCount) {
99
+ const combined = Buffer.concat(this.chunks);
100
+ this.chunks.length = 0;
101
+ const result = combined.subarray(0, byteCount);
102
+ const remainder = combined.subarray(byteCount);
103
+ if (remainder.length > 0)
104
+ this.chunks.push(Buffer.from(remainder));
105
+ return new Uint8Array(result);
106
+ }
107
+ return new Promise(resolve => {
108
+ this.resolveRead = resolve;
109
+ this.needed = byteCount;
110
+ });
111
+ }
112
+ async close() {
113
+ return new Promise(resolve => {
114
+ this.socket.end(() => {
115
+ resolve();
116
+ });
117
+ });
118
+ }
119
+ }
120
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type DeviceDescriptor } from '@thermal-label/brother-ql-core';
2
+ export interface OpenOptions {
3
+ vid?: number;
4
+ pid?: number;
5
+ serialNumber?: string;
6
+ }
7
+ export interface PrinterInfo {
8
+ device: DeviceDescriptor;
9
+ serialNumber: string | undefined;
10
+ path: string;
11
+ transport: 'usb';
12
+ }
13
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAEvE,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;CAClB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ import {} from '@thermal-label/brother-ql-core';
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,MAAM,gCAAgC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@thermal-label/brother-ql-node",
3
+ "version": "0.0.1",
4
+ "description": "Node.js USB and TCP driver for Brother QL label printers",
5
+ "keywords": [
6
+ "brother",
7
+ "brother-ql",
8
+ "label-printer",
9
+ "thermal-label",
10
+ "usb",
11
+ "tcp",
12
+ "node"
13
+ ],
14
+ "type": "module",
15
+ "author": "Mannes Brak",
16
+ "license": "MIT",
17
+ "homepage": "https://thermal-label.github.io/brother-ql/",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/thermal-label/brother-ql.git",
21
+ "directory": "packages/node"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/thermal-label/brother-ql/issues"
25
+ },
26
+ "funding": [
27
+ {
28
+ "type": "github",
29
+ "url": "https://github.com/sponsors/mannes"
30
+ },
31
+ {
32
+ "type": "ko-fi",
33
+ "url": "https://ko-fi.com/mannes"
34
+ }
35
+ ],
36
+ "files": [
37
+ "dist",
38
+ "README.md"
39
+ ],
40
+ "engines": {
41
+ "node": ">=24.0.0"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "sideEffects": false,
47
+ "main": "./dist/index.js",
48
+ "types": "./src/index.ts",
49
+ "exports": {
50
+ ".": {
51
+ "import": "./dist/index.js",
52
+ "types": "./src/index.ts"
53
+ }
54
+ },
55
+ "dependencies": {
56
+ "@mbtech-nl/bitmap": "^0.1.0",
57
+ "usb": "^2.0.0",
58
+ "@thermal-label/brother-ql-core": "0.0.1"
59
+ },
60
+ "optionalDependencies": {
61
+ "@napi-rs/canvas": "^0.1.0"
62
+ },
63
+ "devDependencies": {
64
+ "@mbtech-nl/tsconfig": "^1.0.0",
65
+ "@types/node": "^22.0.0",
66
+ "@vitest/coverage-v8": "^2.1.9",
67
+ "typescript": "~5.5.0",
68
+ "vitest": "^2.0.0"
69
+ },
70
+ "scripts": {
71
+ "build": "tsc -p tsconfig.json",
72
+ "typecheck": "tsc -p tsconfig.json --noEmit",
73
+ "test": "vitest run",
74
+ "test:coverage": "vitest run --coverage"
75
+ }
76
+ }