@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/README.md CHANGED
@@ -1,18 +1,785 @@
1
- # EscPos (NodeJS)
1
+ # @risleylima/escpos
2
2
 
3
- Library to manage EscPos commands in Buffer (NodeJS), then use an adapter to send the resulting data to the printer.
3
+ [![npm version](https://img.shields.io/npm/v/@risleylima/escpos.svg)](https://www.npmjs.com/package/@risleylima/escpos)
4
+ [![Node.js](https://img.shields.io/node/v/@risleylima/escpos.svg)](https://nodejs.org/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
6
 
5
- This Library is a refactoring/rewrite of another Node Escpos Library made by Lsong: [node-escpos](https://github.com/song940/node-escpos)
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
- (Hopefully you will find some improvements)
9
+ ## Features
8
10
 
9
- Check the [printTest.js](https://github.com/risleylima/escpos/blob/main/examples/printTest.js) file on examples folder to get an ideia for how to use this library.
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
- THIS README ISN`T READY YET.
22
+ ## Installation
12
23
 
13
- Any support will be welcome!
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)**