@sincpro/printer-expo 0.1.2 → 1.0.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 (74) hide show
  1. package/README.md +589 -415
  2. package/android/.editorconfig +20 -0
  3. package/android/README.md +103 -0
  4. package/android/build.gradle +36 -34
  5. package/android/libs/pdf/Bixolon_pdf.aar +0 -0
  6. package/android/libs/{jniLibs/x86_64/libbxl_common.so → sincpro-printer-sdk.aar} +0 -0
  7. package/android/src/main/java/sincpro/expo/printer/entrypoint/PrinterModule.kt +387 -0
  8. package/build/SincproPrinter.d.ts +191 -0
  9. package/build/SincproPrinter.d.ts.map +1 -0
  10. package/build/SincproPrinter.js +120 -0
  11. package/build/SincproPrinter.js.map +1 -0
  12. package/build/index.d.ts +11 -3
  13. package/build/index.d.ts.map +1 -1
  14. package/build/index.js +13 -3
  15. package/build/index.js.map +1 -1
  16. package/build/types/bluetooth.types.d.ts +19 -0
  17. package/build/types/bluetooth.types.d.ts.map +1 -0
  18. package/build/types/bluetooth.types.js +5 -0
  19. package/build/types/bluetooth.types.js.map +1 -0
  20. package/build/types/index.d.ts +7 -0
  21. package/build/types/index.d.ts.map +1 -0
  22. package/build/types/index.js +7 -0
  23. package/build/types/index.js.map +1 -0
  24. package/build/types/printer.types.d.ts +118 -0
  25. package/build/types/printer.types.d.ts.map +1 -0
  26. package/build/types/printer.types.js +5 -0
  27. package/build/types/printer.types.js.map +1 -0
  28. package/build/types/receipt.types.d.ts +96 -0
  29. package/build/types/receipt.types.d.ts.map +1 -0
  30. package/build/types/receipt.types.js +5 -0
  31. package/build/types/receipt.types.js.map +1 -0
  32. package/expo-module.config.json +2 -5
  33. package/package.json +6 -5
  34. package/src/SincproPrinter.ts +208 -0
  35. package/src/index.ts +15 -3
  36. package/src/types/bluetooth.types.ts +20 -0
  37. package/src/types/index.ts +7 -0
  38. package/src/types/printer.types.ts +141 -0
  39. package/src/types/receipt.types.ts +115 -0
  40. package/android/libs/BixolonLabelPrinterLibrary_V2.0.9.jar +0 -0
  41. package/android/libs/jniLibs/arm64-v8a/libbxl_common.so +0 -0
  42. package/android/libs/jniLibs/armeabi-v7a/libbxl_common.so +0 -0
  43. package/android/libs/jniLibs/x86/libbxl_common.so +0 -0
  44. package/android/libs/libcommon_V1.4.0.jar +0 -0
  45. package/android/src/main/java/expo/sincpro/ExpoBixolonModule.kt +0 -271
  46. package/android/src/main/java/expo/sincpro/bixolon/BixolonQRPrinter.kt +0 -423
  47. package/android/src/main/java/expo/sincpro/managers/BluetoothManager.kt +0 -139
  48. package/android/src/main/java/expo/sincpro/managers/ConnectionManager.kt +0 -124
  49. package/android/src/main/java/expo/sincpro/managers/PermissionManager.kt +0 -122
  50. package/android/src/main/java/expo/sincpro/managers/PrinterManager.kt +0 -396
  51. package/android/src/main/jniLibs/arm64-v8a/libbxl_common.so +0 -0
  52. package/android/src/main/jniLibs/armeabi-v7a/libbxl_common.so +0 -0
  53. package/android/src/main/jniLibs/x86/libbxl_common.so +0 -0
  54. package/android/src/main/jniLibs/x86_64/libbxl_common.so +0 -0
  55. package/build/BixolonPrinter.d.ts +0 -4
  56. package/build/BixolonPrinter.d.ts.map +0 -1
  57. package/build/BixolonPrinter.js +0 -12
  58. package/build/BixolonPrinter.js.map +0 -1
  59. package/build/ExpoBixolon.types.d.ts +0 -45
  60. package/build/ExpoBixolon.types.d.ts.map +0 -1
  61. package/build/ExpoBixolon.types.js +0 -2
  62. package/build/ExpoBixolon.types.js.map +0 -1
  63. package/build/ExpoBixolonModule.d.ts +0 -24
  64. package/build/ExpoBixolonModule.d.ts.map +0 -1
  65. package/build/ExpoBixolonModule.js +0 -3
  66. package/build/ExpoBixolonModule.js.map +0 -1
  67. package/build/QrCodePrinter.d.ts +0 -45
  68. package/build/QrCodePrinter.d.ts.map +0 -1
  69. package/build/QrCodePrinter.js +0 -118
  70. package/build/QrCodePrinter.js.map +0 -1
  71. package/src/BixolonPrinter.ts +0 -16
  72. package/src/ExpoBixolon.types.ts +0 -60
  73. package/src/ExpoBixolonModule.ts +0 -38
  74. package/src/QrCodePrinter.ts +0 -201
package/README.md CHANGED
@@ -1,101 +1,46 @@
1
- # Expo Bixolon Module
1
+ # @sincpro/printer-expo
2
2
 
3
- [![npm version](https://badge.fury.io/js/expo-bixolon.svg)](https://badge.fury.io/js/expo-bixolon)
3
+ [![npm version](https://badge.fury.io/js/@sincpro/printer-expo.svg)](https://badge.fury.io/js/@sincpro/printer-expo)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
  [![Expo](https://img.shields.io/badge/Expo-000000.svg?style=flat&logo=expo&logoColor=white)](https://expo.dev)
6
6
 
7
- A powerful React Native module for controlling Bixolon thermal printers in Expo applications. This module provides comprehensive Bluetooth connectivity, advanced printing functionality, and seamless integration with Bixolon's official SDK.
7
+ A powerful React Native module for controlling thermal printers in Expo applications. Built with **Clean Architecture** and **Hexagonal Architecture** (Ports & Adapters) for maximum flexibility and maintainability.
8
8
 
9
9
  ## ✨ Features
10
10
 
11
- - 🔗 **Bluetooth Connectivity**: Full Bluetooth device discovery and connection management
12
- - 📱 **Permission Management**: Automatic handling of Bluetooth and location permissions
13
- - 🖨️ **Advanced Printing**: Text, invoices, and formatted document printing
14
- - 📋 **QR Code Printing**: Multiple QR code formats (URL, Contact, WiFi, Payment)
15
- - 🔌 **Multiple Interfaces**: Support for Bluetooth, WiFi, and USB connections
16
- - 📚 **Official SDK**: Integration with BixolonLabelPrinter library
17
- - 📝 **TypeScript**: Complete TypeScript definitions and type safety
18
- - 🔄 **Event-Driven**: Real-time events for device discovery and connection status
19
- - 🛠️ **Easy Setup**: Simple installation and configuration
20
- - 📱 **Cross-Platform**: Works on both Android and iOS (Android focus)
11
+ - 🔗 **Bluetooth Connectivity**: Full device discovery and connection management
12
+ - 📱 **Permission Management**: Smart handling of Android Bluetooth permissions
13
+ - 🖨️ **Advanced Printing**: Receipt printing with flexible line types
14
+ - 📋 **QR Code Support**: Print QR codes with customizable sizes
15
+ - 🏗️ **Clean Architecture**: SOLID principles, testable, swappable adapters
16
+ - 📚 **Official SDK**: Integration with Bixolon SDK (extensible to other brands)
17
+ - 📝 **TypeScript**: 100% type-safe API with comprehensive definitions
18
+ - 🛠️ **Easy Setup**: Simple installation and minimal configuration
19
+ - 📱 **Android Focus**: Optimized for Android thermal printers
21
20
 
22
21
  ## 📦 Installation
23
22
 
24
- ### Method 1: Install from NPM (when published)
25
-
26
23
  ```bash
27
- npm install expo-bixolon
24
+ npm install @sincpro/printer-expo
28
25
  # or
29
- yarn add expo-bixolon
30
- ```
31
-
32
- ### Method 2: Install from Local Tarball
33
-
34
- If you have the module locally or want to use a specific version:
35
-
36
- ```bash
37
- # First, create a tarball from the module directory
38
- cd /path/to/expo-bixolon
39
- npm pack
40
-
41
- # Then install in your app
42
- cd /path/to/your-app
43
- npm install /path/to/expo-bixolon-0.1.0.tgz
44
- ```
45
-
46
- ### Method 3: Install as Local Development Dependency
47
-
48
- For development or testing purposes:
49
-
50
- ```bash
51
- # In your app directory
52
- npm install /absolute/path/to/expo-bixolon
26
+ yarn add @sincpro/printer-expo
53
27
  ```
54
28
 
55
- ### Post-Installation Setup
56
-
57
- After installation, run these commands in your app directory:
29
+ ### Post-Installation
58
30
 
59
31
  ```bash
60
- # Install native dependencies
61
- npx expo install
62
-
63
- # Generate native code
64
- npx expo prebuild
32
+ # Rebuild native modules
33
+ npx expo prebuild --clean
65
34
 
66
- # For development builds
35
+ # Run on device
67
36
  npx expo run:android
68
- # or
69
- npx expo run:ios
70
37
  ```
71
38
 
72
39
  ## ⚙️ Configuration
73
40
 
74
- ### 1. Add Plugin to app.json
41
+ ### Android Permissions
75
42
 
76
- ```json
77
- {
78
- "expo": {
79
- "plugins": [
80
- [
81
- "expo-bixolon",
82
- {
83
- "bluetoothPermissions": [
84
- "android.permission.BLUETOOTH",
85
- "android.permission.BLUETOOTH_ADMIN",
86
- "android.permission.BLUETOOTH_SCAN",
87
- "android.permission.BLUETOOTH_CONNECT",
88
- "android.permission.ACCESS_FINE_LOCATION",
89
- "android.permission.ACCESS_COARSE_LOCATION"
90
- ]
91
- }
92
- ]
93
- ]
94
- }
95
- }
96
- ```
97
-
98
- ### 2. Android Permissions (app.json)
43
+ The module requires Bluetooth permissions. Add to your `app.json`:
99
44
 
100
45
  ```json
101
46
  {
@@ -114,72 +59,95 @@ npx expo run:ios
114
59
  }
115
60
  ```
116
61
 
62
+ **Note**: The module automatically handles runtime permission requests on Android 12+.
63
+
64
+ ````
65
+
117
66
  ## 🚀 Quick Start
118
67
 
119
- ### Basic Setup
68
+ ### Basic Example
120
69
 
121
70
  ```typescript
122
- import BixolonPrinter, { BluetoothDevice } from 'expo-bixolon';
71
+ import Printer, { BluetoothDevice } from '@sincpro/printer-expo';
123
72
 
124
- // Initialize the printer
125
- const initializePrinter = async () => {
126
- try {
127
- const success = await BixolonPrinter.initializePrinter();
128
- if (success) {
129
- console.log('✅ Printer initialized successfully');
130
- }
131
- } catch (error) {
132
- console.error('❌ Error initializing printer:', error);
133
- }
134
- };
135
- ```
73
+ // 1. Check Bluetooth status
74
+ const isEnabled = await Printer.bluetooth.isEnabled();
75
+ const isSupported = await Printer.bluetooth.isSupported();
136
76
 
137
- ### Complete Example
77
+ // 2. Check permissions
78
+ const permStatus = Printer.permission.getStatus();
79
+ if (!permStatus.allGranted) {
80
+ console.log('Missing permissions:', permStatus.deniedPermissions);
81
+ }
82
+
83
+ // 3. Get paired devices
84
+ const devices = await Printer.bluetooth.getPairedDevices();
85
+ const printers = devices.filter(d => d.isPrinter);
86
+
87
+ // 4. Connect to printer
88
+ await Printer.connection.connect(printers[0].address);
89
+
90
+ // 5. Print receipt
91
+ await Printer.print.receipt({
92
+ header: [
93
+ { type: 'text', content: 'MY STORE', fontSize: 'large', alignment: 'center', bold: true },
94
+ { type: 'separator' },
95
+ ],
96
+ details: [
97
+ { type: 'keyValue', key: 'Product', value: '$10.00' },
98
+ { type: 'keyValue', key: 'Tax', value: '$1.00' },
99
+ ],
100
+ footer: [
101
+ { type: 'separator' },
102
+ { type: 'keyValue', key: 'TOTAL', value: '$11.00', bold: true },
103
+ { type: 'space', lines: 2 },
104
+ ],
105
+ });
106
+ ````
107
+
108
+ ### Complete React Component
138
109
 
139
110
  ```typescript
140
111
  import React, { useState, useEffect } from 'react';
141
- import { View, Button, Alert } from 'react-native';
142
- import BixolonPrinter, { BluetoothDevice } from 'expo-bixolon';
112
+ import { View, Button, FlatList, Text, Alert } from 'react-native';
113
+ import Printer, { BluetoothDevice } from '@sincpro/printer-expo';
143
114
 
144
- export default function PrinterApp() {
115
+ export default function PrinterScreen() {
145
116
  const [devices, setDevices] = useState<BluetoothDevice[]>([]);
146
- const [isConnected, setIsConnected] = useState(false);
117
+ const [connected, setConnected] = useState(false);
147
118
 
148
119
  useEffect(() => {
149
- initializePrinter();
150
120
  checkPermissions();
151
121
  }, []);
152
122
 
153
- const initializePrinter = async () => {
154
- try {
155
- await BixolonPrinter.initializePrinter();
156
- console.log('Printer initialized');
157
- } catch (error) {
158
- console.error('Initialization failed:', error);
159
- }
160
- };
123
+ const checkPermissions = () => {
124
+ const status = Printer.permission.getStatus();
161
125
 
162
- const checkPermissions = async () => {
163
- const permissions = await BixolonPrinter.checkBluetoothPermissions();
164
- console.log('Permissions:', permissions);
126
+ if (!status.allGranted) {
127
+ Alert.alert('Permissions Required', `Missing: ${status.deniedPermissions.join(', ')}`);
128
+ }
165
129
  };
166
130
 
167
- const discoverDevices = async () => {
131
+ const scanDevices = async () => {
168
132
  try {
169
- const foundDevices = await BixolonPrinter.discoverBluetoothDevices();
170
- setDevices(foundDevices);
133
+ const isEnabled = await Printer.bluetooth.isEnabled();
134
+ if (!isEnabled) {
135
+ Alert.alert('Error', 'Please enable Bluetooth');
136
+ return;
137
+ }
138
+
139
+ const foundDevices = await Printer.bluetooth.getPairedDevices();
140
+ setDevices(foundDevices.filter((d) => d.isPrinter));
171
141
  } catch (error) {
172
- Alert.alert('Error', 'Failed to discover devices');
142
+ Alert.alert('Error', error.message);
173
143
  }
174
144
  };
175
145
 
176
- const connectToDevice = async (device: BluetoothDevice) => {
146
+ const connectDevice = async (device: BluetoothDevice) => {
177
147
  try {
178
- const success = await BixolonPrinter.connectPrinter('BLUETOOTH', device.address, 1);
179
- if (success) {
180
- setIsConnected(true);
181
- Alert.alert('Success', 'Connected to printer');
182
- }
148
+ await Printer.connection.connect(device.address);
149
+ setConnected(true);
150
+ Alert.alert('Success', `Connected to ${device.name}`);
183
151
  } catch (error) {
184
152
  Alert.alert('Error', 'Connection failed');
185
153
  }
@@ -187,25 +155,39 @@ export default function PrinterApp() {
187
155
 
188
156
  const printTest = async () => {
189
157
  try {
190
- const success = await BixolonPrinter.testPlainText('Hello from Expo!');
191
- if (success) {
192
- Alert.alert('Success', 'Text printed successfully');
193
- }
158
+ await Printer.print.receipt({
159
+ header: [
160
+ { type: 'text', content: 'Test Receipt', fontSize: 'large', alignment: 'center' },
161
+ { type: 'separator' },
162
+ ],
163
+ details: [{ type: 'text', content: 'This is a test print' }],
164
+ footer: [{ type: 'space', lines: 2 }],
165
+ });
166
+ Alert.alert('Success', 'Receipt printed');
194
167
  } catch (error) {
195
- Alert.alert('Error', 'Print failed');
168
+ Alert.alert('Error', error.message);
196
169
  }
197
170
  };
198
171
 
199
172
  return (
200
173
  <View style={{ padding: 20 }}>
201
- <Button title="Discover Devices" onPress={discoverDevices} />
202
- <Button title="Print Test" onPress={printTest} disabled={!isConnected} />
203
- {/* Render device list */}
174
+ <Button title="Scan Devices" onPress={scanDevices} />
175
+ <Button title="Print Test" onPress={printTest} disabled={!connected} />
176
+
177
+ <FlatList
178
+ data={devices}
179
+ keyExtractor={(item) => item.address}
180
+ renderItem={({ item }) => (
181
+ <Button title={`${item.name} (${item.address})`} onPress={() => connectDevice(item)} />
182
+ )}
183
+ />
204
184
  </View>
205
185
  );
206
186
  }
207
187
  ```
208
188
 
189
+ ````
190
+
209
191
  ## 📱 Detailed Usage
210
192
 
211
193
  ### Bluetooth Device Discovery
@@ -264,7 +246,7 @@ const discoverDevices = async () => {
264
246
  await BixolonPrinter.stopBluetoothDiscovery();
265
247
  }
266
248
  };
267
- ```
249
+ ````
268
250
 
269
251
  ### Connecting to a Printer
270
252
 
@@ -450,468 +432,660 @@ npx expo run:ios
450
432
 
451
433
  ## 📚 API Reference
452
434
 
453
- ### Core Methods
435
+ ### Namespaces
454
436
 
455
- #### `initializePrinter(): Promise<boolean>`
437
+ The API is organized into four main namespaces:
456
438
 
457
- Initializes the printer module. Must be called before any other operations.
439
+ ```typescript
440
+ import Printer from '@sincpro/printer-expo';
458
441
 
459
- **Returns:** `Promise<boolean>` - `true` if initialization successful
442
+ Printer.bluetooth; // Bluetooth operations
443
+ Printer.permission; // Permission management
444
+ Printer.connection; // Connection control
445
+ Printer.print; // Printing operations
446
+ ```
460
447
 
461
- **Example:**
448
+ ---
449
+
450
+ ### Bluetooth API
451
+
452
+ #### `bluetooth.isEnabled(): Promise<boolean>`
453
+
454
+ Check if Bluetooth is enabled on the device.
462
455
 
463
456
  ```typescript
464
- const success = await BixolonPrinter.initializePrinter();
457
+ const enabled = await Printer.bluetooth.isEnabled();
465
458
  ```
466
459
 
467
- #### `connectPrinter(interfaceType: string, address: string, port: number): Promise<boolean>`
468
-
469
- Connects to a printer using the specified interface type, address, and port.
460
+ #### `bluetooth.isSupported(): Promise<boolean>`
470
461
 
471
- **Parameters:**
462
+ Check if Bluetooth is supported on the device.
472
463
 
473
- - `interfaceType`: `'BLUETOOTH' | 'WIFI' | 'USB'`
474
- - `address`: Device MAC address (Bluetooth) or IP address (WiFi)
475
- - `port`: Port number (usually 1 for Bluetooth, 9100 for WiFi)
464
+ ```typescript
465
+ const supported = await Printer.bluetooth.isSupported();
466
+ ```
476
467
 
477
- **Returns:** `Promise<boolean>` - `true` if connection successful
468
+ #### `bluetooth.getPairedDevices(): Promise<BluetoothDevice[]>`
478
469
 
479
- **Example:**
470
+ Get list of paired/bonded Bluetooth devices.
480
471
 
481
472
  ```typescript
482
- const success = await BixolonPrinter.connectPrinter('BLUETOOTH', '00:11:22:33:44:55', 1);
473
+ const devices = await Printer.bluetooth.getPairedDevices();
474
+ const printers = devices.filter((d) => d.isPrinter);
483
475
  ```
484
476
 
485
- #### `disconnectPrinter(): Promise<boolean>`
477
+ #### `bluetooth.startDiscovery(): Promise<boolean>`
486
478
 
487
- Disconnects from the currently connected printer.
479
+ Start Bluetooth discovery to find nearby devices.
488
480
 
489
- **Returns:** `Promise<boolean>` - `true` if disconnection successful
481
+ ```typescript
482
+ await Printer.bluetooth.startDiscovery();
483
+ ```
490
484
 
491
- #### `executeCommand(command: string): Promise<boolean>`
485
+ #### `bluetooth.stopDiscovery(): Promise<boolean>`
492
486
 
493
- Executes a raw command on the printer.
487
+ Stop Bluetooth discovery.
494
488
 
495
- **Parameters:**
489
+ ```typescript
490
+ await Printer.bluetooth.stopDiscovery();
491
+ ```
496
492
 
497
- - `command`: Raw command string to send to printer
493
+ ---
498
494
 
499
- ### Printing Methods
495
+ ### Permission API
500
496
 
501
- #### `testPlainText(text: string): Promise<boolean>`
497
+ #### `permission.hasBluetoothPermissions(): boolean`
502
498
 
503
- Prints plain text to the connected printer.
499
+ Check if all required Bluetooth permissions are granted (synchronous).
504
500
 
505
- **Parameters:**
501
+ ```typescript
502
+ const hasAll = Printer.permission.hasBluetoothPermissions();
503
+ ```
506
504
 
507
- - `text`: Text content to print
505
+ #### `permission.getRequiredPermissions(): string[]`
508
506
 
509
- #### `printFormattedText(text: string, fontSize?: number): Promise<boolean>`
507
+ Get list of required permissions for the current Android version.
510
508
 
511
- Prints formatted text with optional font size.
509
+ ```typescript
510
+ const required = Printer.permission.getRequiredPermissions();
511
+ // Returns: ['android.permission.BLUETOOTH_SCAN', 'android.permission.BLUETOOTH_CONNECT', ...]
512
+ ```
512
513
 
513
- **Parameters:**
514
+ #### `permission.getMissingPermissions(): string[]`
515
+
516
+ Get list of missing/denied permissions.
517
+
518
+ ```typescript
519
+ const missing = Printer.permission.getMissingPermissions();
520
+ console.log('Need to request:', missing);
521
+ ```
514
522
 
515
- - `text`: Formatted text content
516
- - `fontSize`: Optional font size (default: 10)
523
+ #### `permission.getStatus(): PermissionStatus`
517
524
 
518
- #### `printTextSimple(text: string): Promise<boolean>`
525
+ Get detailed permission status.
519
526
 
520
- Prints text using simple formatting (line-by-line).
527
+ ```typescript
528
+ const status = Printer.permission.getStatus();
529
+ console.log('All granted:', status.allGranted);
530
+ console.log('Granted:', status.grantedPermissions);
531
+ console.log('Denied:', status.deniedPermissions);
532
+ console.log('Android version:', status.androidVersion);
533
+ ```
521
534
 
522
- #### `printTextInPages(text: string): Promise<boolean>`
535
+ ---
523
536
 
524
- Prints long text split into multiple pages.
537
+ ### Connection API
525
538
 
526
- #### `printInvoice(invoiceText: string): Promise<boolean>`
539
+ #### `connection.connect(address: string, port?: number): Promise<boolean>`
527
540
 
528
- Prints a complete invoice from formatted text.
541
+ Connect to a printer via Bluetooth.
529
542
 
530
543
  **Parameters:**
531
544
 
532
- - `invoiceText`: Complete invoice text with formatting
545
+ - `address`: MAC address of the printer (e.g., `"00:11:22:AA:BB:CC"`)
546
+ - `port`: TCP port (default: `9100`)
547
+
548
+ ```typescript
549
+ await Printer.connection.connect('00:11:22:AA:BB:CC');
550
+ ```
533
551
 
534
- ### Bluetooth Methods
552
+ #### `connection.disconnect(): Promise<boolean>`
535
553
 
536
- #### `requestBluetoothPermissions(): Promise<boolean>`
554
+ Disconnect from the current printer.
537
555
 
538
- Requests necessary Bluetooth and location permissions.
556
+ ```typescript
557
+ await Printer.connection.disconnect();
558
+ ```
539
559
 
540
- **Returns:** `Promise<boolean>` - `true` if permissions granted
560
+ #### `connection.getStatus(): Promise<ConnectionInfo>`
541
561
 
542
- #### `checkBluetoothPermissions(): Promise<BluetoothPermissions>`
562
+ Get current connection status and details.
543
563
 
544
- Returns the current status of Bluetooth and location permissions.
564
+ ```typescript
565
+ const info = await Printer.connection.getStatus();
566
+ console.log('Address:', info.address);
567
+ console.log('Type:', info.type); // 'BLUETOOTH' | 'WIFI' | 'USB'
568
+ console.log('Status:', info.status); // 'CONNECTED' | 'CONNECTING' | 'DISCONNECTED' | 'ERROR'
569
+ ```
545
570
 
546
- **Returns:** `Promise<BluetoothPermissions>` - Object with permission status
571
+ #### `connection.isConnected(): boolean`
547
572
 
548
- #### `discoverBluetoothDevices(): Promise<BluetoothDevice[]>`
573
+ Check if currently connected (synchronous).
549
574
 
550
- Discovers available Bluetooth devices.
575
+ ```typescript
576
+ const connected = Printer.connection.isConnected();
577
+ ```
551
578
 
552
- **Returns:** `Promise<BluetoothDevice[]>` - Array of discovered devices
579
+ ---
553
580
 
554
- #### `startBluetoothDiscovery(): Promise<boolean>`
581
+ ### Print API
555
582
 
556
- Starts the Bluetooth device discovery process.
583
+ #### `print.receipt(receipt: Receipt): Promise<void>`
557
584
 
558
- #### `stopBluetoothDiscovery(): Promise<boolean>`
585
+ Print a complete receipt with header, details, and footer sections.
559
586
 
560
- Stops the Bluetooth device discovery process.
587
+ **Parameters:**
561
588
 
562
- #### `isBluetoothEnabled(): Promise<boolean>`
589
+ - `receipt`: Receipt object with sections and configuration
563
590
 
564
- Checks if Bluetooth is enabled on the device.
591
+ ```typescript
592
+ await Printer.print.receipt({
593
+ header: [
594
+ { type: 'text', content: 'STORE NAME', fontSize: 'large', alignment: 'center', bold: true },
595
+ { type: 'text', content: '123 Main St', alignment: 'center' },
596
+ { type: 'separator' },
597
+ ],
598
+ details: [
599
+ { type: 'keyValue', key: 'Product A', value: '$10.00' },
600
+ { type: 'keyValue', key: 'Product B', value: '$15.00' },
601
+ { type: 'keyValue', key: 'Tax (10%)', value: '$2.50' },
602
+ ],
603
+ footer: [
604
+ { type: 'separator' },
605
+ { type: 'keyValue', key: 'TOTAL', value: '$27.50', bold: true, fontSize: 'large' },
606
+ { type: 'qrCode', data: 'https://mystore.com/receipt/12345', size: 5, alignment: 'center' },
607
+ { type: 'space', lines: 2 },
608
+ ],
609
+ copies: 1,
610
+ });
611
+ ```
565
612
 
566
- ## Types
613
+ #### `print.lines(lines: ReceiptLine[]): Promise<void>`
567
614
 
568
- ### BluetoothDevice
615
+ Print a list of receipt lines without sections.
569
616
 
570
617
  ```typescript
571
- interface BluetoothDevice {
572
- name: string;
573
- address: string;
574
- type: 'CLASSIC' | 'LE' | 'DUAL' | 'UNKNOWN';
575
- isPrinter: boolean;
576
- }
618
+ await Printer.print.lines([
619
+ { type: 'text', content: 'Quick Receipt', alignment: 'center' },
620
+ { type: 'separator' },
621
+ { type: 'keyValue', key: 'Item', value: '$5.00' },
622
+ { type: 'space', lines: 1 },
623
+ ]);
577
624
  ```
578
625
 
579
- ### BluetoothPermissions
626
+ #### `print.qrCode(data: string, size?: number): Promise<void>`
627
+
628
+ Print a standalone QR code.
629
+
630
+ **Parameters:**
631
+
632
+ - `data`: QR code content (URL, text, etc.)
633
+ - `size`: QR code size 1-10 (default: `5`)
580
634
 
581
635
  ```typescript
582
- interface BluetoothPermissions {
583
- ACCESS_FINE_LOCATION: boolean;
584
- ACCESS_COARSE_LOCATION: boolean;
585
- BLUETOOTH_SCAN?: boolean;
586
- BLUETOOTH_CONNECT?: boolean;
587
- }
636
+ await Printer.print.qrCode('https://example.com', 7);
588
637
  ```
589
638
 
590
- ### InvoiceItem
639
+ ---
640
+
641
+ ## 🎨 Receipt Line Types
642
+
643
+ ### TextLine
644
+
645
+ Print formatted text with customizable style.
591
646
 
592
647
  ```typescript
593
- interface InvoiceItem {
594
- description: string;
595
- quantity: number;
596
- price: number;
648
+ {
649
+ type: 'text',
650
+ content: string,
651
+ fontSize?: 'small' | 'medium' | 'large' | 'xlarge',
652
+ bold?: boolean,
653
+ alignment?: 'left' | 'center' | 'right'
597
654
  }
598
655
  ```
599
656
 
600
- ## QR Code Printing
657
+ **Example:**
601
658
 
602
- The module now includes comprehensive QR code printing functionality using the official Bixolon libraries.
659
+ ```typescript
660
+ { type: 'text', content: 'INVOICE', fontSize: 'xlarge', alignment: 'center', bold: true }
661
+ ```
603
662
 
604
- ### Basic QR Code Printing
663
+ ### KeyValueLine
664
+
665
+ Print key-value pairs (common in receipts).
605
666
 
606
667
  ```typescript
607
- import QrCodePrinter from 'expo-bixolon/src/QrCodePrinter';
668
+ {
669
+ type: 'keyValue',
670
+ key: string,
671
+ value: string,
672
+ fontSize?: FontSize,
673
+ bold?: boolean
674
+ }
675
+ ```
608
676
 
609
- // Get the QR printer instance
610
- const qrPrinter = QrCodePrinter.getInstance();
677
+ **Example:**
611
678
 
612
- // Print a simple QR code
613
- await qrPrinter.printSimpleQRCode('Hello World!', 9);
679
+ ```typescript
680
+ { type: 'keyValue', key: 'Subtotal', value: '$25.00' }
681
+ { type: 'keyValue', key: 'TOTAL', value: '$27.50', bold: true }
614
682
  ```
615
683
 
616
- ### Advanced QR Code Options
684
+ ### QRCodeLine
685
+
686
+ Embed QR codes in receipts.
617
687
 
618
688
  ```typescript
619
- import { QRCodeOptions } from 'expo-bixolon/src/QrCodePrinter';
689
+ {
690
+ type: 'qrCode',
691
+ data: string,
692
+ size?: number, // 1-10, default: 5
693
+ alignment?: Alignment
694
+ }
695
+ ```
620
696
 
621
- const options: QRCodeOptions = {
622
- data: 'https://www.example.com',
623
- horizontalPosition: 200,
624
- verticalPosition: 100,
625
- model: 'MODEL2',
626
- eccLevel: 'ECC_LEVEL_15',
627
- size: 9,
628
- rotation: 'NONE',
629
- };
697
+ **Example:**
630
698
 
631
- await qrPrinter.printQRCode(options);
699
+ ```typescript
700
+ { type: 'qrCode', data: 'https://store.com/receipt/12345', size: 6, alignment: 'center' }
632
701
  ```
633
702
 
634
- ### Specialized QR Code Types
703
+ ### SeparatorLine
635
704
 
636
- #### URL QR Code
705
+ Print horizontal separator lines.
637
706
 
638
707
  ```typescript
639
- await qrPrinter.printURLQRCode('www.example.com', 9);
708
+ {
709
+ type: 'separator',
710
+ char?: string, // Character to repeat, default: '-'
711
+ length?: number // Line length, default: 48
712
+ }
640
713
  ```
641
714
 
642
- #### Contact QR Code (vCard)
715
+ **Example:**
643
716
 
644
717
  ```typescript
645
- const contact = {
646
- name: 'John Doe',
647
- phone: '+1234567890',
648
- email: 'john.doe@example.com',
649
- company: 'Example Corp',
650
- title: 'Software Engineer',
651
- };
652
-
653
- await qrPrinter.printContactQRCode(contact, 9);
718
+ { type: 'separator' }
719
+ { type: 'separator', char: '=', length: 32 }
654
720
  ```
655
721
 
656
- #### WiFi QR Code
722
+ ### SpaceLine
723
+
724
+ Add blank lines for spacing.
657
725
 
658
726
  ```typescript
659
- await qrPrinter.printWiFiQRCode('MyWiFiNetwork', 'password123', 'WPA', 9);
727
+ {
728
+ type: 'space',
729
+ lines?: number // Number of blank lines, default: 1
730
+ }
660
731
  ```
661
732
 
662
- #### Payment QR Code
733
+ **Example:**
663
734
 
664
735
  ```typescript
665
- const paymentData = {
666
- amount: 99.99,
667
- currency: 'USD',
668
- description: 'Product purchase',
669
- merchantName: 'Example Store',
670
- };
736
+ { type: 'space', lines: 2 }
737
+ ```
738
+
739
+ ---
740
+
741
+ ## 📦 TypeScript Types
671
742
 
672
- await qrPrinter.printPaymentQRCode(paymentData, 9);
743
+ ### BluetoothDevice
744
+
745
+ ```typescript
746
+ interface BluetoothDevice {
747
+ name: string;
748
+ address: string;
749
+ type: 'CLASSIC' | 'LE' | 'DUAL' | 'UNKNOWN';
750
+ isPrinter: boolean;
751
+ }
673
752
  ```
674
753
 
675
- ### QR Code Configuration
754
+ ### PermissionStatus
676
755
 
677
- - **Models**: MODEL1 (original) or MODEL2 (enhanced, recommended)
678
- - **Error Correction**: ECC_LEVEL_7, ECC_LEVEL_15, ECC_LEVEL_25, ECC_LEVEL_30
679
- - **Size**: 1-10 (recommended: 7-9)
680
- - **Rotation**: NONE, ROTATION_90_DEGREES, ROTATION_180_DEGREES, ROTATION_270_DEGREES
756
+ ```typescript
757
+ interface PermissionStatus {
758
+ allGranted: boolean;
759
+ grantedPermissions: string[];
760
+ deniedPermissions: string[];
761
+ androidVersion: number;
762
+ }
763
+ ```
681
764
 
682
- For detailed QR code printing documentation, see [QR_PRINTING_README.md](./QR_PRINTING_README.md).
765
+ ### ConnectionInfo
683
766
 
684
- ## Events
767
+ ```typescript
768
+ interface ConnectionInfo {
769
+ address: string;
770
+ port: number;
771
+ type: 'BLUETOOTH' | 'WIFI' | 'USB' | 'UNKNOWN';
772
+ status: 'DISCONNECTED' | 'CONNECTING' | 'CONNECTED' | 'ERROR';
773
+ }
774
+ ```
685
775
 
686
- The module emits the following events:
776
+ ### Receipt
687
777
 
688
- - `onBluetoothDeviceDiscovered`: Fired when a new Bluetooth device is discovered
689
- - `onBluetoothDiscoveryStarted`: Fired when Bluetooth discovery starts
690
- - `onBluetoothDiscoveryStopped`: Fired when Bluetooth discovery stops
691
- - `onPrinterConnected`: Fired when successfully connected to a printer
692
- - `onPrinterDisconnected`: Fired when disconnected from a printer
693
- - `onPrintComplete`: Fired when a print operation completes
778
+ ```typescript
779
+ interface Receipt {
780
+ header?: ReceiptLine[];
781
+ details?: ReceiptLine[];
782
+ footer?: ReceiptLine[];
783
+ mediaConfig?: MediaConfig;
784
+ copies?: number;
785
+ }
786
+ ```
694
787
 
695
- ## Example
788
+ ### MediaConfig
696
789
 
697
- See the `example` directory for a complete working example that demonstrates:
790
+ ```typescript
791
+ interface MediaConfig {
792
+ type: 'continuous' | 'labelGap' | 'labelBlackMark';
793
+ width: number;
794
+ height: number;
795
+ offset?: number;
796
+ gap?: number;
797
+ }
798
+ ```
698
799
 
699
- - Bluetooth device discovery
700
- - Permission management
701
- - Printer connection
702
- - Text and invoice printing
703
- - Event handling
800
+ ---
704
801
 
705
- ## 🔧 Requirements
802
+ ## 🎯 Advanced Examples
706
803
 
707
- - **React Native**: 0.79+
708
- - **Expo SDK**: 53+
709
- - **Android**: API level 21+ (Android 5.0+)
710
- - **iOS**: 13+ (limited support)
711
- - **Node.js**: 18+
712
- - **TypeScript**: 4.9+ (optional but recommended)
804
+ ### Complete Receipt with All Line Types
713
805
 
714
- ## 🖨️ Supported Printers
806
+ ```typescript
807
+ const fullReceipt: Receipt = {
808
+ header: [
809
+ {
810
+ type: 'text',
811
+ content: '🏪 MY RETAIL STORE',
812
+ fontSize: 'xlarge',
813
+ alignment: 'center',
814
+ bold: true,
815
+ },
816
+ { type: 'text', content: '123 Commerce Street', alignment: 'center' },
817
+ { type: 'text', content: 'Phone: (555) 123-4567', alignment: 'center' },
818
+ { type: 'separator', char: '=' },
819
+ { type: 'text', content: 'SALES RECEIPT', fontSize: 'large', alignment: 'center' },
820
+ { type: 'separator', char: '=' },
821
+ { type: 'space' },
822
+ ],
823
+ details: [
824
+ { type: 'keyValue', key: 'Date', value: new Date().toLocaleDateString() },
825
+ { type: 'keyValue', key: 'Receipt #', value: '00123' },
826
+ { type: 'keyValue', key: 'Cashier', value: 'John Doe' },
827
+ { type: 'space' },
828
+ { type: 'separator' },
829
+ { type: 'text', content: 'ITEMS', bold: true },
830
+ { type: 'separator' },
831
+ { type: 'keyValue', key: 'Coffee (x2)', value: '$9.00' },
832
+ { type: 'keyValue', key: 'Croissant (x1)', value: '$3.50' },
833
+ { type: 'keyValue', key: 'Orange Juice (x1)', value: '$4.00' },
834
+ { type: 'space' },
835
+ { type: 'separator' },
836
+ { type: 'keyValue', key: 'Subtotal', value: '$16.50' },
837
+ { type: 'keyValue', key: 'Tax (8%)', value: '$1.32' },
838
+ ],
839
+ footer: [
840
+ { type: 'separator', char: '=' },
841
+ { type: 'keyValue', key: 'TOTAL', value: '$17.82', fontSize: 'large', bold: true },
842
+ { type: 'separator', char: '=' },
843
+ { type: 'space', lines: 2 },
844
+ { type: 'text', content: 'Thank you for your purchase!', alignment: 'center' },
845
+ { type: 'text', content: 'Visit us at www.mystore.com', alignment: 'center' },
846
+ { type: 'space' },
847
+ { type: 'qrCode', data: 'https://mystore.com/receipt/00123', size: 6, alignment: 'center' },
848
+ { type: 'space', lines: 3 },
849
+ ],
850
+ copies: 1,
851
+ };
715
852
 
716
- ### Bixolon Thermal Printers
853
+ await Printer.print.receipt(fullReceipt);
854
+ ```
717
855
 
718
- - **SPP-L310** (Primary target)
719
- - **SPP-R200III** ✅
720
- - **SPP-R300** ✅
721
- - **SPP-R400** ✅
722
- - **SPP-L410** ✅
723
- - **SPP-L420** ✅
856
+ ### Error Handling Pattern
724
857
 
725
- ### Connection Types
858
+ ```typescript
859
+ const safePrint = async (receipt: Receipt) => {
860
+ try {
861
+ // Check connection
862
+ if (!Printer.connection.isConnected()) {
863
+ throw new Error('Printer not connected');
864
+ }
726
865
 
727
- - **Bluetooth** ✅ (Primary)
728
- - **WiFi** (Limited support)
729
- - **USB** ⚠️ (Experimental)
866
+ // Check status
867
+ const status = await Printer.connection.getStatus();
868
+ if (status.status !== 'CONNECTED') {
869
+ throw new Error(`Connection ${status.status.toLowerCase()}`);
870
+ }
730
871
 
731
- ## 🐛 Troubleshooting
872
+ // Print
873
+ await Printer.print.receipt(receipt);
874
+ console.log('✅ Print successful');
875
+ } catch (error) {
876
+ console.error('❌ Print failed:', error.message);
732
877
 
733
- ### Common Issues
878
+ // Show user-friendly message
879
+ Alert.alert('Print Error', error.message || 'Could not print receipt', [{ text: 'OK' }]);
880
+ }
881
+ };
882
+ ```
734
883
 
735
- #### 1. Bluetooth Permissions Not Granted
884
+ ### Custom Hook for Printer Management
736
885
 
737
886
  ```typescript
738
- // Always check permissions first
739
- const permissions = await BixolonPrinter.checkBluetoothPermissions();
740
- console.log('Permissions:', permissions);
887
+ import { useState, useEffect } from 'react';
888
+ import Printer, { BluetoothDevice, ConnectionInfo } from '@sincpro/printer-expo';
741
889
 
742
- // Request if needed
743
- if (!permissions.ACCESS_FINE_LOCATION) {
744
- await BixolonPrinter.requestBluetoothPermissions();
745
- }
746
- ```
890
+ export function usePrinter() {
891
+ const [devices, setDevices] = useState<BluetoothDevice[]>([]);
892
+ const [connected, setConnected] = useState(false);
893
+ const [connectionInfo, setConnectionInfo] = useState<ConnectionInfo | null>(null);
747
894
 
748
- #### 2. Device Not Found
895
+ useEffect(() => {
896
+ checkConnection();
897
+ }, []);
749
898
 
750
- - Ensure Bluetooth is enabled on both devices
751
- - Make sure the printer is in pairing mode
752
- - Check if the device is already paired in system settings
753
- - Try restarting Bluetooth discovery
899
+ const checkConnection = () => {
900
+ const isConnected = Printer.connection.isConnected();
901
+ setConnected(isConnected);
902
+ };
754
903
 
755
- #### 3. Connection Fails
904
+ const scanDevices = async () => {
905
+ try {
906
+ const isEnabled = await Printer.bluetooth.isEnabled();
907
+ if (!isEnabled) {
908
+ throw new Error('Bluetooth is disabled');
909
+ }
756
910
 
757
- - Verify the device MAC address is correct
758
- - Ensure the printer is compatible with the module
759
- - Check if another app is connected to the printer
760
- - Try disconnecting and reconnecting
911
+ const foundDevices = await Printer.bluetooth.getPairedDevices();
912
+ setDevices(foundDevices.filter((d) => d.isPrinter));
761
913
 
762
- #### 4. Print Jobs Not Completing
914
+ return foundDevices;
915
+ } catch (error) {
916
+ console.error('Scan failed:', error);
917
+ throw error;
918
+ }
919
+ };
763
920
 
764
- - Check if the printer has paper
765
- - Verify the printer is not in error state
766
- - Try printing a simple test first
767
- - Check printer logs for error messages
921
+ const connect = async (address: string) => {
922
+ try {
923
+ await Printer.connection.connect(address);
924
+ setConnected(true);
768
925
 
769
- #### 5. Module Not Found Error
926
+ const info = await Printer.connection.getStatus();
927
+ setConnectionInfo(info);
770
928
 
771
- ```bash
772
- # Make sure to run prebuild after installation
773
- npx expo prebuild
929
+ return true;
930
+ } catch (error) {
931
+ console.error('Connection failed:', error);
932
+ throw error;
933
+ }
934
+ };
774
935
 
775
- # Clear cache if needed
776
- npx expo start --clear
777
- ```
936
+ const disconnect = async () => {
937
+ try {
938
+ await Printer.connection.disconnect();
939
+ setConnected(false);
940
+ setConnectionInfo(null);
941
+ return true;
942
+ } catch (error) {
943
+ console.error('Disconnection failed:', error);
944
+ throw error;
945
+ }
946
+ };
947
+
948
+ const printReceipt = async (receipt: Receipt) => {
949
+ if (!connected) {
950
+ throw new Error('Not connected to printer');
951
+ }
778
952
 
779
- ### Debug Mode
953
+ await Printer.print.receipt(receipt);
954
+ };
780
955
 
781
- Enable debug logging for detailed information:
956
+ return {
957
+ devices,
958
+ connected,
959
+ connectionInfo,
960
+ scanDevices,
961
+ connect,
962
+ disconnect,
963
+ printReceipt,
964
+ };
965
+ }
782
966
 
783
- ```bash
784
- # Set environment variable
785
- export EXPO_DEBUG=true
967
+ // Usage
968
+ function MyComponent() {
969
+ const printer = usePrinter();
786
970
 
787
- # Or in your app
788
- process.env.EXPO_DEBUG = 'true';
971
+ return (
972
+ <View>
973
+ <Button title="Scan" onPress={printer.scanDevices} />
974
+ <Button
975
+ title="Print"
976
+ onPress={() => printer.printReceipt(myReceipt)}
977
+ disabled={!printer.connected}
978
+ />
979
+ </View>
980
+ );
981
+ }
789
982
  ```
790
983
 
791
- ### Performance Tips
984
+ ---
792
985
 
793
- 1. **Initialize once**: Call `initializePrinter()` only once per app session
794
- 2. **Reuse connections**: Keep connections alive when possible
795
- 3. **Batch operations**: Group multiple print operations together
796
- 4. **Error handling**: Always wrap print operations in try-catch blocks
986
+ ## 🏗️ Architecture
797
987
 
798
- ### Getting Help
988
+ This module follows **Clean Architecture** with **Hexagonal Architecture** (Ports & Adapters) principles:
799
989
 
800
- If you encounter issues:
990
+ ```
991
+ TypeScript (React Native)
992
+
993
+ ENTRYPOINT - Expo Modules API bridge
994
+
995
+ SERVICE - Use cases & orchestration
996
+
997
+ DOMAIN - Business entities & rules
998
+
999
+ ADAPTER - Printer implementations (Bixolon, Zebra, etc.)
1000
+
1001
+ INFRASTRUCTURE - Android APIs & SDKs
1002
+ ```
801
1003
 
802
- 1. Check the [example app](./example) for working code
803
- 2. Enable debug mode and check logs
804
- 3. Verify your printer model is supported
805
- 4. Test with a simple print operation first
1004
+ **Benefits:**
806
1005
 
807
- ## 🤝 Contributing
1006
+ - **Testable**: Mock adapters and services
1007
+ - ✅ **Maintainable**: Clear separation of concerns
1008
+ - ✅ **Extensible**: Easy to add new printer brands
1009
+ - ✅ **Swappable**: Change implementations without affecting business logic
808
1010
 
809
- We welcome contributions! Here's how you can help:
1011
+ See [ARCHITECTURE.md](ARCHITECTURE.md) for details.
810
1012
 
811
- ### Development Setup
1013
+ ---
812
1014
 
813
- ```bash
814
- # Clone the repository
815
- git clone https://github.com/your-username/expo-bixolon.git
816
- cd expo-bixolon
1015
+ ## 🛠️ Troubleshooting
817
1016
 
818
- # Install dependencies
819
- npm install
1017
+ ### Bluetooth Permissions
820
1018
 
821
- # Build the module
822
- npm run build
1019
+ **Problem**: "Permission denied" errors
823
1020
 
824
- # Run the example app
825
- cd example
826
- npm install
827
- npx expo run:android
828
- ```
1021
+ **Solution**: Check permission status and request if needed
829
1022
 
830
- ### Making Changes
831
-
832
- 1. **Fork the repository**
833
- 2. **Create a feature branch**: `git checkout -b feature/amazing-feature`
834
- 3. **Make your changes** and test thoroughly
835
- 4. **Add tests** if applicable
836
- 5. **Update documentation** as needed
837
- 6. **Submit a pull request**
1023
+ ```typescript
1024
+ const status = Printer.permission.getStatus();
1025
+ if (!status.allGranted) {
1026
+ console.log('Missing:', status.deniedPermissions);
1027
+ // Guide user to app settings to grant permissions
1028
+ }
1029
+ ```
838
1030
 
839
- ### Publishing to NPM
1031
+ ### Connection Issues
840
1032
 
841
- El paquete se publica automáticamente a NPM cuando se crea un release en GitHub:
1033
+ **Problem**: Connection fails or times out
842
1034
 
843
- 1. **Update version**: `make update-version VERSION=x.y.z`
844
- 2. **Commit**: `git add . && git commit -m "chore: bump version to x.y.z"`
845
- 3. **Push**: `git push origin main`
846
- 4. **Create GitHub Release**: El CI/CD publicará automáticamente a NPM
847
- - Requiere secret `NPM_TOKEN` configurado en GitHub
1035
+ **Solutions**:
848
1036
 
849
- **Comandos de desarrollo**:
1037
+ 1. Verify Bluetooth is enabled: `await Printer.bluetooth.isEnabled()`
1038
+ 2. Check device is paired: `await Printer.bluetooth.getPairedDevices()`
1039
+ 3. Ensure printer is powered on and in range
1040
+ 4. Try reconnecting: `await Printer.connection.connect(address)`
850
1041
 
851
- - `make build` - Construye el módulo
852
- - `make test` - Ejecuta tests
853
- - `make format` - Formatea código
854
- - `make verify-format` - Verifica formato (usado en CI)
855
- - `make publish-dry-run` - Simula publicación
856
- - `make publish` - Publica manualmente (requiere `npm login`)
1042
+ ### Print Failures
857
1043
 
858
- ### Code Style
1044
+ **Problem**: Print command succeeds but nothing prints
859
1045
 
860
- - Use TypeScript for all new code
861
- - Follow existing code patterns
862
- - Add proper error handling
863
- - Include JSDoc comments for public APIs
864
- - Test on real Bixolon printers when possible
1046
+ **Solutions**:
865
1047
 
866
- ## 📄 License
1048
+ 1. Check printer status (paper, errors)
1049
+ 2. Verify connection: `Printer.connection.isConnected()`
1050
+ 3. Try smaller test print first
1051
+ 4. Check printer-specific requirements (media config)
867
1052
 
868
- MIT License - see [LICENSE](./LICENSE) file for details.
1053
+ ---
869
1054
 
870
- ## 🆘 Support
1055
+ ## 📖 Resources
871
1056
 
872
- ### Getting Help
1057
+ - **Architecture**: [ARCHITECTURE.md](ARCHITECTURE.md) - Detailed architecture guide
1058
+ - **Contributing**: [CONTRIBUTING.md](CONTRIBUTING.md) - Development guidelines
1059
+ - **Copilot**: [.github/copilot-instructions.md](.github/copilot-instructions.md) - AI coding assistant rules
1060
+ - **Expo Modules**: [Official Documentation](https://docs.expo.dev/modules/overview/)
1061
+ - **Bixolon SDK**: [Official Documentation](https://www.bixolon.com/)
873
1062
 
874
- - 📖 **Documentation**: Check this README and the example app
875
- - 🐛 **Bug Reports**: Open an issue with detailed information
876
- - 💡 **Feature Requests**: Open an issue with use case description
877
- - 💬 **Discussions**: Use GitHub Discussions for questions
1063
+ ---
878
1064
 
879
- ### Issue Template
1065
+ ## 🤝 Contributing
880
1066
 
881
- When reporting issues, please include:
1067
+ We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for:
882
1068
 
883
- ```markdown
884
- **Printer Model**: SPP-L310
885
- **Android Version**: 12
886
- **Expo SDK Version**: 53
887
- **Steps to Reproduce**:
1069
+ - Development setup
1070
+ - Code standards (ktlint, Prettier)
1071
+ - Architecture guidelines
1072
+ - Git workflow
1073
+ - Pull request process
888
1074
 
889
- 1. Initialize printer
890
- 2. Connect to device
891
- 3. Print text
892
- **Expected Behavior**: Text should print
893
- **Actual Behavior**: Connection fails
894
- **Logs**: [Include relevant logs]
895
- ```
1075
+ ---
896
1076
 
897
- ## 🎯 Roadmap
1077
+ ## 📄 License
898
1078
 
899
- ### Planned Features
1079
+ MIT License - see [LICENSE](LICENSE) file for details.
900
1080
 
901
- - [ ] **Enhanced WiFi Support**: Full WiFi printing capabilities
902
- - [ ] **Image Printing**: Support for printing images and logos
903
- - [ ] **Barcode Printing**: Various barcode formats
904
- - [ ] **iOS Support**: Full iOS implementation
905
- - [ ] **Web Support**: Web-based printing interface
906
- - [ ] **Cloud Printing**: Remote printing capabilities
1081
+ ---
907
1082
 
908
- ### Recent Updates
1083
+ ## 🙏 Acknowledgments
909
1084
 
910
- - **v0.1.0**: Initial release with Bluetooth support
911
- - **QR Code Printing**: Advanced QR code functionality
912
- - **TypeScript Support**: Complete type definitions
913
- - ✅ **Local Installation**: Support for local package distribution
1085
+ - Bixolon for the official printer SDK
1086
+ - Expo team for the Modules API
1087
+ - Contributors and testers
914
1088
 
915
1089
  ---
916
1090
 
917
- **Made with ❤️ for the Expo and Bixolon communities**
1091
+ **Made with ❤️ by Sincpro SRL**