@risleylima/escpos 0.0.13 → 0.1.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.
- package/CHANGELOG.md +60 -0
- package/README.md +798 -8
- package/docs/COVERAGE_ANALYSIS.md +98 -0
- package/docs/DEPENDENCIES_REVIEW.md +127 -0
- package/docs/JSDOC_REVIEW.md +122 -0
- package/docs/LIBRARY_OVERVIEW.md +383 -0
- package/docs/PRE_PUBLISH_CHECKLIST.md +331 -0
- package/docs/PUBLIC_API_ANALYSIS.md +224 -0
- package/docs/README.md +34 -0
- package/docs/SERIALPORT_V13_MIGRATION_COMPLETE.md +127 -0
- package/docs/TESTS_IMPLEMENTED.md +129 -0
- package/docs/USB_V2_REVIEW.md +148 -0
- package/docs/VERIFICATION_RESULTS.md +172 -0
- package/jest.config.js +16 -0
- package/package.json +12 -7
- package/src/adapter/index.js +37 -0
- package/src/printer/commands.js +6 -4
- package/src/printer/image.js +28 -7
- package/src/printer/index.js +7 -2
- package/src/printer/utils.js +21 -14
- package/src/serial-adapter/index.js +133 -84
- package/src/usb-adapter/index.js +157 -43
- package/tests/README.md +67 -0
- package/tests/integration/printer-flow.test.js +128 -0
- package/tests/unit/adapters/adapter.test.js +49 -0
- package/tests/unit/adapters/serial-adapter.test.js +224 -0
- package/tests/unit/adapters/usb-adapter.test.js +319 -0
- package/tests/unit/image/image.test.js +157 -0
- package/tests/unit/printer/buffer.test.js +60 -0
- package/tests/unit/printer/commands.test.js +109 -0
- package/tests/unit/printer/printer.test.js +405 -0
- package/tests/unit/utils/utils.test.js +96 -0
package/README.md
CHANGED
|
@@ -1,18 +1,785 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @risleylima/escpos
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@risleylima/escpos)
|
|
4
|
+
[](https://nodejs.org/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
A modern, well-tested Node.js library for generating ESC/POS commands and communicating with thermal printers via USB or Serial ports.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
## Features
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
- 🖨️ **Full ESC/POS Support**: Complete implementation of ESC/POS commands
|
|
12
|
+
- 🔌 **Multiple Adapters**: USB and Serial port support
|
|
13
|
+
- 📝 **Fluent API**: Method chaining for easy command composition
|
|
14
|
+
- 🖼️ **Image Printing**: Convert and print images on thermal printers
|
|
15
|
+
- 📊 **Barcode Generation**: Support for multiple barcode formats (EAN13, EAN8, CODE128, CODE39, etc.)
|
|
16
|
+
- 🌐 **Encoding Support**: Multiple character encodings (GB18030, UTF-8, ASCII, etc.)
|
|
17
|
+
- 📦 **Modern JavaScript**: Promise-based async/await, ES6+
|
|
18
|
+
- ✅ **Well Tested**: 100% test coverage with 145+ tests
|
|
19
|
+
- 📚 **Fully Documented**: Complete JSDoc documentation
|
|
20
|
+
- 🔄 **Event-Driven**: EventEmitter-based architecture for connection events
|
|
10
21
|
|
|
11
|
-
|
|
22
|
+
## Installation
|
|
12
23
|
|
|
13
|
-
|
|
24
|
+
### Via NPM
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @risleylima/escpos
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Via Yarn
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
yarn add @risleylima/escpos
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Requirements
|
|
37
|
+
|
|
38
|
+
- **Node.js**: >= 18.0.0
|
|
39
|
+
- **Operating System**: Linux, macOS, or Windows
|
|
40
|
+
|
|
41
|
+
### Platform-Specific Requirements
|
|
42
|
+
|
|
43
|
+
#### Linux
|
|
44
|
+
- For USB: `libusb` development libraries
|
|
45
|
+
```bash
|
|
46
|
+
sudo apt-get install libusb-1.0-0-dev # Debian/Ubuntu
|
|
47
|
+
sudo yum install libusb-devel # CentOS/RHEL
|
|
48
|
+
```
|
|
49
|
+
- For Serial: Usually built-in, may need permissions
|
|
50
|
+
```bash
|
|
51
|
+
sudo usermod -a -G dialout $USER # Add user to dialout group
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### macOS
|
|
55
|
+
- For USB: Usually works out of the box
|
|
56
|
+
- For Serial: Usually works out of the box
|
|
57
|
+
|
|
58
|
+
#### Windows
|
|
59
|
+
- For USB: Usually works out of the box
|
|
60
|
+
- For Serial: Usually works out of the box
|
|
61
|
+
|
|
62
|
+
## Quick Start
|
|
63
|
+
|
|
64
|
+
### USB Printer Example
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
const { USB, Printer } = require('@risleylima/escpos');
|
|
68
|
+
|
|
69
|
+
(async () => {
|
|
70
|
+
try {
|
|
71
|
+
// Connect to USB printer (VID and PID)
|
|
72
|
+
await USB.connect(1046, 20497);
|
|
73
|
+
await USB.open();
|
|
74
|
+
|
|
75
|
+
// Create printer instance
|
|
76
|
+
const printer = new Printer(USB);
|
|
77
|
+
|
|
78
|
+
// Print a receipt
|
|
79
|
+
printer
|
|
80
|
+
.hardware('init')
|
|
81
|
+
.align('ct')
|
|
82
|
+
.size(2, 2)
|
|
83
|
+
.textln('RECEIPT')
|
|
84
|
+
.size(1, 1)
|
|
85
|
+
.align('lt')
|
|
86
|
+
.textln('Item 1: $10.00')
|
|
87
|
+
.textln('Item 2: $20.00')
|
|
88
|
+
.align('rt')
|
|
89
|
+
.textln('Total: $30.00')
|
|
90
|
+
.cut(true);
|
|
91
|
+
|
|
92
|
+
// Send to printer
|
|
93
|
+
await printer.flush();
|
|
94
|
+
|
|
95
|
+
// Close connection
|
|
96
|
+
await USB.close();
|
|
97
|
+
await USB.disconnect();
|
|
98
|
+
} catch (error) {
|
|
99
|
+
console.error('Error:', error);
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Serial Printer Example
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
const { Serial, Printer } = require('@risleylima/escpos');
|
|
108
|
+
|
|
109
|
+
(async () => {
|
|
110
|
+
try {
|
|
111
|
+
// Connect to serial printer
|
|
112
|
+
await Serial.connect('/dev/ttyUSB0');
|
|
113
|
+
await Serial.open();
|
|
114
|
+
|
|
115
|
+
// Create printer instance
|
|
116
|
+
const printer = new Printer(Serial);
|
|
117
|
+
|
|
118
|
+
// Print text
|
|
119
|
+
printer
|
|
120
|
+
.hardware('init')
|
|
121
|
+
.textln('Hello, World!')
|
|
122
|
+
.cut(true);
|
|
123
|
+
|
|
124
|
+
// Send to printer
|
|
125
|
+
await printer.flush();
|
|
126
|
+
|
|
127
|
+
// Close connection
|
|
128
|
+
await Serial.close();
|
|
129
|
+
await Serial.disconnect();
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error('Error:', error);
|
|
132
|
+
}
|
|
133
|
+
})();
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## API Documentation
|
|
137
|
+
|
|
138
|
+
### Exports
|
|
139
|
+
|
|
140
|
+
The library exports the following modules:
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
const { USB, Serial, Printer, Adapter, Image } = require('@risleylima/escpos');
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
- **`USB`**: USB adapter instance (EventEmitter)
|
|
147
|
+
- **`Serial`**: Serial port adapter instance (EventEmitter)
|
|
148
|
+
- **`Printer`**: ESC/POS command generator class
|
|
149
|
+
- **`Adapter`**: Base adapter class
|
|
150
|
+
- **`Image`**: Image processing utilities
|
|
151
|
+
|
|
152
|
+
### USB Adapter
|
|
153
|
+
|
|
154
|
+
#### Methods
|
|
155
|
+
|
|
156
|
+
##### `USB.listUSB()`
|
|
157
|
+
List all available USB printer devices.
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
const devices = await USB.listUSB();
|
|
161
|
+
console.log(devices); // Array of USB devices with manufacturer and product info
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
##### `USB.connect(vid, pid)`
|
|
165
|
+
Connect to a USB printer by Vendor ID and Product ID.
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
await USB.connect(1046, 20497); // Connect to specific device
|
|
169
|
+
// OR
|
|
170
|
+
await USB.connect(); // Connect to first available printer
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Events:**
|
|
174
|
+
- `connect` - Emitted when device connects
|
|
175
|
+
- `detach` - Emitted when device is unplugged
|
|
176
|
+
|
|
177
|
+
##### `USB.open()`
|
|
178
|
+
Open the USB device and claim the printer interface.
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
await USB.open();
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Events:**
|
|
185
|
+
- `connect` - Emitted when device is opened
|
|
186
|
+
|
|
187
|
+
##### `USB.write(data)`
|
|
188
|
+
Write data buffer to the printer.
|
|
189
|
+
|
|
190
|
+
```javascript
|
|
191
|
+
await USB.write(Buffer.from('Hello', 'ascii'));
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
##### `USB.close()`
|
|
195
|
+
Close the USB device connection.
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
await USB.close();
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Events:**
|
|
202
|
+
- `close` - Emitted when device closes
|
|
203
|
+
|
|
204
|
+
##### `USB.disconnect()`
|
|
205
|
+
Disconnect from the USB device (calls `close` internally).
|
|
206
|
+
|
|
207
|
+
```javascript
|
|
208
|
+
await USB.disconnect();
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Events:**
|
|
212
|
+
- `disconnect` - Emitted when device disconnects
|
|
213
|
+
|
|
214
|
+
### Serial Adapter
|
|
215
|
+
|
|
216
|
+
#### Methods
|
|
217
|
+
|
|
218
|
+
##### `Serial.connect(port, options)`
|
|
219
|
+
Connect to a serial port printer.
|
|
220
|
+
|
|
221
|
+
```javascript
|
|
222
|
+
await Serial.connect('/dev/ttyUSB0');
|
|
223
|
+
// OR with options
|
|
224
|
+
await Serial.connect('/dev/ttyUSB0', {
|
|
225
|
+
baudRate: 9600,
|
|
226
|
+
dataBits: 8,
|
|
227
|
+
stopBits: 1,
|
|
228
|
+
parity: 'none'
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Events:**
|
|
233
|
+
- `connect` - Emitted when port connects
|
|
234
|
+
- `close` - Emitted when reconnecting (closing previous connection)
|
|
235
|
+
|
|
236
|
+
##### `Serial.open()`
|
|
237
|
+
Open the serial port if it's closed.
|
|
238
|
+
|
|
239
|
+
```javascript
|
|
240
|
+
await Serial.open();
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
##### `Serial.write(data)`
|
|
244
|
+
Write data buffer to the printer.
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
await Serial.write(Buffer.from('Hello', 'ascii'));
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
##### `Serial.read()`
|
|
251
|
+
Read data from the serial port.
|
|
252
|
+
|
|
253
|
+
```javascript
|
|
254
|
+
const data = await Serial.read();
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
##### `Serial.close(timeout)`
|
|
258
|
+
Close the serial port connection.
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
await Serial.close(); // Default timeout: 50ms
|
|
262
|
+
await Serial.close(100); // Custom timeout: 100ms
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Events:**
|
|
266
|
+
- `close` - Emitted when port closes
|
|
267
|
+
|
|
268
|
+
##### `Serial.disconnect(timeout)`
|
|
269
|
+
Disconnect from the serial port (calls `close` internally).
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
await Serial.disconnect();
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Events:**
|
|
276
|
+
- `disconnect` - Emitted when port disconnects
|
|
277
|
+
|
|
278
|
+
### Printer Class
|
|
279
|
+
|
|
280
|
+
#### Constructor
|
|
281
|
+
|
|
282
|
+
```javascript
|
|
283
|
+
const printer = new Printer(adapter, options);
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Parameters:**
|
|
287
|
+
- `adapter` (Adapter): USB or Serial adapter instance
|
|
288
|
+
- `options` (Object, optional):
|
|
289
|
+
- `encoding` (String): Character encoding (default: 'GB18030')
|
|
290
|
+
- `width` (Number): Paper width in columns (default: 48)
|
|
291
|
+
|
|
292
|
+
#### Text Operations
|
|
293
|
+
|
|
294
|
+
##### `printer.print(content)`
|
|
295
|
+
Print raw text without encoding.
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
printer.print('Hello');
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
##### `printer.println(content)`
|
|
302
|
+
Print text with line break.
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
printer.println('Hello');
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
##### `printer.text(content, encoding)`
|
|
309
|
+
Print text with encoding.
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
printer.text('Hello', 'UTF-8');
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
##### `printer.textln(content, encoding)`
|
|
316
|
+
Print text with encoding and line break.
|
|
317
|
+
|
|
318
|
+
```javascript
|
|
319
|
+
printer.textln('Hello', 'UTF-8');
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
##### `printer.newLine()`
|
|
323
|
+
Send end of line command.
|
|
324
|
+
|
|
325
|
+
```javascript
|
|
326
|
+
printer.newLine();
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
#### Formatting
|
|
330
|
+
|
|
331
|
+
##### `printer.align(position)`
|
|
332
|
+
Set text alignment.
|
|
333
|
+
|
|
334
|
+
```javascript
|
|
335
|
+
printer.align('lt'); // Left
|
|
336
|
+
printer.align('ct'); // Center
|
|
337
|
+
printer.align('rt'); // Right
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
##### `printer.size(width, height)`
|
|
341
|
+
Set text size (1-8 for both width and height).
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
printer.size(2, 2); // Double width and height
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
##### `printer.style(type)`
|
|
348
|
+
Set text style.
|
|
349
|
+
|
|
350
|
+
```javascript
|
|
351
|
+
printer.style('B'); // Bold
|
|
352
|
+
printer.style('I'); // Italic
|
|
353
|
+
printer.style('U'); // Underline
|
|
354
|
+
printer.style('NORMAL'); // Normal
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
##### `printer.font(family)`
|
|
358
|
+
Set font family.
|
|
359
|
+
|
|
360
|
+
```javascript
|
|
361
|
+
printer.font('A'); // Font A (42 columns)
|
|
362
|
+
printer.font('B'); // Font B (56 columns)
|
|
363
|
+
printer.font('C'); // Font C
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
##### `printer.encode(encoding)`
|
|
367
|
+
Set character encoding.
|
|
368
|
+
|
|
369
|
+
```javascript
|
|
370
|
+
printer.encode('UTF-8');
|
|
371
|
+
printer.encode('GB18030');
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
#### Hardware Control
|
|
375
|
+
|
|
376
|
+
##### `printer.hardware(command)`
|
|
377
|
+
Send hardware commands.
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
printer.hardware('init'); // Initialize printer
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
##### `printer.cut(partial, feed)`
|
|
384
|
+
Cut paper.
|
|
385
|
+
|
|
386
|
+
```javascript
|
|
387
|
+
printer.cut(true); // Partial cut
|
|
388
|
+
printer.cut(false); // Full cut
|
|
389
|
+
printer.cut(true, 5); // Partial cut with 5 line feeds
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
##### `printer.beep(count, time)`
|
|
393
|
+
Beep buzzer.
|
|
394
|
+
|
|
395
|
+
```javascript
|
|
396
|
+
printer.beep(2, 1); // Beep 2 times, 100ms each
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
##### `printer.cashdraw(pin)`
|
|
400
|
+
Open cash drawer.
|
|
401
|
+
|
|
402
|
+
```javascript
|
|
403
|
+
printer.cashdraw(2); // Pulse pin 2
|
|
404
|
+
printer.cashdraw(5); // Pulse pin 5
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
#### Barcode
|
|
408
|
+
|
|
409
|
+
##### `printer.barcode(code, type, options)`
|
|
410
|
+
Print barcode.
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
// EAN13 barcode
|
|
414
|
+
printer.barcode('123456789012', 'EAN13');
|
|
415
|
+
|
|
416
|
+
// CODE128 with options
|
|
417
|
+
printer.barcode('ABC123', 'CODE128', {
|
|
418
|
+
width: 2,
|
|
419
|
+
height: 100,
|
|
420
|
+
position: 'BLW', // Below: 'OFF', 'ABV', 'BLW', 'BTH'
|
|
421
|
+
font: 'A',
|
|
422
|
+
includeParity: true
|
|
423
|
+
});
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Supported Types:**
|
|
427
|
+
- `EAN13`, `EAN8`, `UPC-A`, `UPC-E`
|
|
428
|
+
- `CODE39`, `CODE93`, `CODE128`
|
|
429
|
+
- `ITF`, `NW7`
|
|
430
|
+
|
|
431
|
+
#### Image Printing
|
|
432
|
+
|
|
433
|
+
##### `printer.image(image, density)`
|
|
434
|
+
Print image in bitmap mode.
|
|
435
|
+
|
|
436
|
+
```javascript
|
|
437
|
+
const { Image } = require('@risleylima/escpos');
|
|
438
|
+
|
|
439
|
+
// Load image
|
|
440
|
+
const image = await Image.load('/path/to/image.png', 'image/png');
|
|
441
|
+
|
|
442
|
+
// Print image
|
|
443
|
+
printer.image(image, 'd24'); // Density: 'd8', 's8', 'd24', 's24'
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
##### `printer.raster(image, mode)`
|
|
447
|
+
Print image in raster mode.
|
|
448
|
+
|
|
449
|
+
```javascript
|
|
450
|
+
const image = await Image.load('/path/to/image.png', 'image/png');
|
|
451
|
+
printer.raster(image, 'normal'); // Mode: 'normal', 'dw', 'dh', 'dwdh'
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
#### Control Methods
|
|
455
|
+
|
|
456
|
+
##### `printer.flush()`
|
|
457
|
+
Send buffered data to printer.
|
|
458
|
+
|
|
459
|
+
```javascript
|
|
460
|
+
await printer.flush();
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
##### `printer.close(options)`
|
|
464
|
+
Close connection and flush buffer.
|
|
465
|
+
|
|
466
|
+
```javascript
|
|
467
|
+
await printer.close();
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
#### Utility Methods
|
|
471
|
+
|
|
472
|
+
##### `printer.drawLine(character)`
|
|
473
|
+
Draw a line with specified character.
|
|
474
|
+
|
|
475
|
+
```javascript
|
|
476
|
+
printer.drawLine('-'); // Draw line with dashes
|
|
477
|
+
printer.drawLine('='); // Draw line with equals
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
##### `printer.feed(n)`
|
|
481
|
+
Feed paper n lines.
|
|
482
|
+
|
|
483
|
+
```javascript
|
|
484
|
+
printer.feed(3); // Feed 3 lines
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
##### `printer.color(color)`
|
|
488
|
+
Set print color (if printer supports it).
|
|
489
|
+
|
|
490
|
+
```javascript
|
|
491
|
+
printer.color(0); // Black
|
|
492
|
+
printer.color(1); // Red
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
##### `printer.setReverseColors(bool)`
|
|
496
|
+
Reverse colors (if printer supports it).
|
|
497
|
+
|
|
498
|
+
```javascript
|
|
499
|
+
printer.setReverseColors(true); // White text on black background
|
|
500
|
+
printer.setReverseColors(false); // Normal
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
##### `printer.raw(data)`
|
|
504
|
+
Write raw ESC/POS commands.
|
|
505
|
+
|
|
506
|
+
```javascript
|
|
507
|
+
// Hex string
|
|
508
|
+
printer.raw('1B40'); // Initialize
|
|
509
|
+
|
|
510
|
+
// Buffer
|
|
511
|
+
printer.raw(Buffer.from('1B40', 'hex'));
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Advanced Examples
|
|
515
|
+
|
|
516
|
+
### Complete Receipt
|
|
517
|
+
|
|
518
|
+
```javascript
|
|
519
|
+
const { USB, Printer } = require('@risleylima/escpos');
|
|
520
|
+
|
|
521
|
+
(async () => {
|
|
522
|
+
await USB.connect(1046, 20497);
|
|
523
|
+
await USB.open();
|
|
524
|
+
|
|
525
|
+
const printer = new Printer(USB, {
|
|
526
|
+
encoding: 'UTF-8',
|
|
527
|
+
width: 48
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
printer
|
|
531
|
+
.hardware('init')
|
|
532
|
+
.beep(1, 1)
|
|
533
|
+
.align('ct')
|
|
534
|
+
.size(2, 2)
|
|
535
|
+
.textln('MY STORE')
|
|
536
|
+
.size(1, 1)
|
|
537
|
+
.textln('123 Main Street')
|
|
538
|
+
.textln('City, State 12345')
|
|
539
|
+
.textln('Phone: (555) 123-4567')
|
|
540
|
+
.drawLine()
|
|
541
|
+
.align('lt')
|
|
542
|
+
.textln('Date: ' + new Date().toLocaleString())
|
|
543
|
+
.textln('Receipt #: 001234')
|
|
544
|
+
.drawLine()
|
|
545
|
+
.textln('Item 1 $10.00')
|
|
546
|
+
.textln('Item 2 $20.00')
|
|
547
|
+
.textln('Item 3 $15.00')
|
|
548
|
+
.drawLine()
|
|
549
|
+
.align('rt')
|
|
550
|
+
.textln('Subtotal: $45.00')
|
|
551
|
+
.textln('Tax: $4.50')
|
|
552
|
+
.size(2, 1)
|
|
553
|
+
.textln('Total: $49.50')
|
|
554
|
+
.size(1, 1)
|
|
555
|
+
.drawLine()
|
|
556
|
+
.align('ct')
|
|
557
|
+
.textln('Thank you for your purchase!')
|
|
558
|
+
.feed(3)
|
|
559
|
+
.cut(true);
|
|
560
|
+
|
|
561
|
+
await printer.flush();
|
|
562
|
+
await USB.close();
|
|
563
|
+
await USB.disconnect();
|
|
564
|
+
})();
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### Barcode Example
|
|
568
|
+
|
|
569
|
+
```javascript
|
|
570
|
+
const { USB, Printer } = require('@risleylima/escpos');
|
|
571
|
+
|
|
572
|
+
(async () => {
|
|
573
|
+
await USB.connect(1046, 20497);
|
|
574
|
+
await USB.open();
|
|
575
|
+
|
|
576
|
+
const printer = new Printer(USB);
|
|
577
|
+
|
|
578
|
+
printer
|
|
579
|
+
.hardware('init')
|
|
580
|
+
.align('ct')
|
|
581
|
+
.textln('PRODUCT CODE')
|
|
582
|
+
.barcode('123456789012', 'EAN13', {
|
|
583
|
+
width: 2,
|
|
584
|
+
height: 100,
|
|
585
|
+
position: 'BLW',
|
|
586
|
+
font: 'A'
|
|
587
|
+
})
|
|
588
|
+
.feed(2)
|
|
589
|
+
.cut(true);
|
|
590
|
+
|
|
591
|
+
await printer.flush();
|
|
592
|
+
await USB.close();
|
|
593
|
+
await USB.disconnect();
|
|
594
|
+
})();
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
### Image Printing Example
|
|
598
|
+
|
|
599
|
+
```javascript
|
|
600
|
+
const { USB, Printer, Image } = require('@risleylima/escpos');
|
|
601
|
+
|
|
602
|
+
(async () => {
|
|
603
|
+
await USB.connect(1046, 20497);
|
|
604
|
+
await USB.open();
|
|
605
|
+
|
|
606
|
+
const printer = new Printer(USB);
|
|
607
|
+
|
|
608
|
+
// Load and print image
|
|
609
|
+
const image = await Image.load('/path/to/logo.png', 'image/png');
|
|
610
|
+
|
|
611
|
+
printer
|
|
612
|
+
.hardware('init')
|
|
613
|
+
.align('ct')
|
|
614
|
+
.image(image, 'd24')
|
|
615
|
+
.feed(2)
|
|
616
|
+
.textln('Company Logo')
|
|
617
|
+
.cut(true);
|
|
618
|
+
|
|
619
|
+
await printer.flush();
|
|
620
|
+
await USB.close();
|
|
621
|
+
await USB.disconnect();
|
|
622
|
+
})();
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### Event Handling
|
|
626
|
+
|
|
627
|
+
```javascript
|
|
628
|
+
const { USB, Printer } = require('@risleylima/escpos');
|
|
629
|
+
|
|
630
|
+
USB.on('connect', (device) => {
|
|
631
|
+
console.log('Device connected:', device);
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
USB.on('disconnect', (device) => {
|
|
635
|
+
console.log('Device disconnected:', device);
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
USB.on('close', (device) => {
|
|
639
|
+
console.log('Device closed:', device);
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
USB.on('detach', () => {
|
|
643
|
+
console.log('Device unplugged!');
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
(async () => {
|
|
647
|
+
await USB.connect(1046, 20497);
|
|
648
|
+
await USB.open();
|
|
649
|
+
|
|
650
|
+
const printer = new Printer(USB);
|
|
651
|
+
printer.textln('Hello, World!');
|
|
652
|
+
await printer.flush();
|
|
653
|
+
|
|
654
|
+
await USB.close();
|
|
655
|
+
await USB.disconnect();
|
|
656
|
+
})();
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### Finding USB Printers
|
|
660
|
+
|
|
661
|
+
```javascript
|
|
662
|
+
const { USB } = require('@risleylima/escpos');
|
|
663
|
+
|
|
664
|
+
(async () => {
|
|
665
|
+
// List all USB printers
|
|
666
|
+
const devices = await USB.listUSB();
|
|
667
|
+
|
|
668
|
+
console.log('Found printers:');
|
|
669
|
+
devices.forEach((device, index) => {
|
|
670
|
+
console.log(`${index + 1}. ${device.manufacturer} - ${device.product}`);
|
|
671
|
+
console.log(` VID: ${device.deviceDescriptor.idVendor}`);
|
|
672
|
+
console.log(` PID: ${device.deviceDescriptor.idProduct}`);
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
// Connect to first printer
|
|
676
|
+
if (devices.length > 0) {
|
|
677
|
+
await USB.connect();
|
|
678
|
+
await USB.open();
|
|
679
|
+
// ... use printer
|
|
680
|
+
}
|
|
681
|
+
})();
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
## Method Chaining
|
|
685
|
+
|
|
686
|
+
The Printer class supports method chaining for fluent API:
|
|
687
|
+
|
|
688
|
+
```javascript
|
|
689
|
+
printer
|
|
690
|
+
.hardware('init')
|
|
691
|
+
.align('ct')
|
|
692
|
+
.size(2, 2)
|
|
693
|
+
.textln('TITLE')
|
|
694
|
+
.size(1, 1)
|
|
695
|
+
.align('lt')
|
|
696
|
+
.textln('Content here')
|
|
697
|
+
.cut(true);
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
## Error Handling
|
|
701
|
+
|
|
702
|
+
Always wrap printer operations in try-catch blocks:
|
|
703
|
+
|
|
704
|
+
```javascript
|
|
705
|
+
try {
|
|
706
|
+
await USB.connect(1046, 20497);
|
|
707
|
+
await USB.open();
|
|
708
|
+
|
|
709
|
+
const printer = new Printer(USB);
|
|
710
|
+
printer.textln('Hello');
|
|
711
|
+
await printer.flush();
|
|
712
|
+
|
|
713
|
+
await USB.close();
|
|
714
|
+
await USB.disconnect();
|
|
715
|
+
} catch (error) {
|
|
716
|
+
console.error('Printer error:', error);
|
|
717
|
+
// Handle error appropriately
|
|
718
|
+
}
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
## Testing
|
|
722
|
+
|
|
723
|
+
The library includes comprehensive tests:
|
|
724
|
+
|
|
725
|
+
```bash
|
|
726
|
+
# Run all tests
|
|
727
|
+
npm test
|
|
728
|
+
|
|
729
|
+
# Run tests in watch mode
|
|
730
|
+
npm run test:watch
|
|
731
|
+
|
|
732
|
+
# Run tests with coverage
|
|
733
|
+
npm run test:coverage
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
**Test Coverage: 100%** ✅
|
|
737
|
+
- 145+ tests
|
|
738
|
+
- Unit and integration tests
|
|
739
|
+
- All edge cases covered
|
|
740
|
+
|
|
741
|
+
## Documentation
|
|
742
|
+
|
|
743
|
+
Additional documentation is available in the `docs/` folder:
|
|
744
|
+
|
|
745
|
+
- [Library Overview](./docs/LIBRARY_OVERVIEW.md) - Complete library overview
|
|
746
|
+
- [JSDoc Review](./docs/JSDOC_REVIEW.md) - JSDoc documentation review
|
|
747
|
+
- [Test Coverage](./docs/COVERAGE_ANALYSIS.md) - Test coverage analysis
|
|
748
|
+
- [Dependencies Review](./docs/DEPENDENCIES_REVIEW.md) - Dependencies status
|
|
749
|
+
- [USB v2 Migration](./docs/USB_V2_MIGRATION.md) - USB library migration guide
|
|
750
|
+
- [SerialPort v13 Migration](./docs/SERIALPORT_V13_MIGRATION_COMPLETE.md) - SerialPort migration guide
|
|
751
|
+
|
|
752
|
+
## Contributing
|
|
753
|
+
|
|
754
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
755
|
+
|
|
756
|
+
1. Fork the repository
|
|
757
|
+
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
|
|
758
|
+
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
|
759
|
+
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
|
760
|
+
5. Open a Pull Request
|
|
761
|
+
|
|
762
|
+
### Development Setup
|
|
763
|
+
|
|
764
|
+
```bash
|
|
765
|
+
# Clone repository
|
|
766
|
+
git clone https://github.com/risleylima/escpos.git
|
|
767
|
+
cd escpos
|
|
768
|
+
|
|
769
|
+
# Install dependencies
|
|
770
|
+
npm install
|
|
771
|
+
# or
|
|
772
|
+
yarn install
|
|
773
|
+
|
|
774
|
+
# Run tests
|
|
775
|
+
npm test
|
|
776
|
+
|
|
777
|
+
# Run tests with coverage
|
|
778
|
+
npm run test:coverage
|
|
779
|
+
```
|
|
780
|
+
|
|
781
|
+
## License
|
|
14
782
|
|
|
15
|
-
----
|
|
16
783
|
MIT License
|
|
17
784
|
|
|
18
785
|
Copyright (c) 2021 Risley Lima risley@rlimainfo.com.br
|
|
@@ -34,3 +801,26 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
34
801
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
35
802
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
36
803
|
SOFTWARE.
|
|
804
|
+
|
|
805
|
+
## Acknowledgments
|
|
806
|
+
|
|
807
|
+
This library is a refactoring/rewrite of [node-escpos](https://github.com/song940/node-escpos) by Lsong, with improvements and modern JavaScript patterns.
|
|
808
|
+
|
|
809
|
+
## Support
|
|
810
|
+
|
|
811
|
+
- **Issues**: [GitHub Issues](https://github.com/risleylima/escpos/issues)
|
|
812
|
+
- **Email**: risley@rlimainfo.com.br
|
|
813
|
+
|
|
814
|
+
## Changelog
|
|
815
|
+
|
|
816
|
+
### v0.0.14
|
|
817
|
+
- ✅ Updated all dependencies to latest versions
|
|
818
|
+
- ✅ Migrated USB library from v1 to v2 (Promise-based)
|
|
819
|
+
- ✅ Migrated SerialPort from v12 to v13 (Promise-based)
|
|
820
|
+
- ✅ 100% test coverage (145+ tests)
|
|
821
|
+
- ✅ Complete JSDoc documentation
|
|
822
|
+
- ✅ Architecture improvements and bug fixes
|
|
823
|
+
|
|
824
|
+
---
|
|
825
|
+
|
|
826
|
+
**Made with ❤️ by [Rlima Info](https://github.com/risleylima)**
|