react-native-telpo 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.
- package/README.md +300 -0
- package/lib/commonjs/index.js +40 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/nfc/index.js +322 -0
- package/lib/commonjs/nfc/index.js.map +1 -0
- package/lib/commonjs/printer/index.js +379 -0
- package/lib/commonjs/printer/index.js.map +1 -0
- package/lib/commonjs/scanner/index.js +301 -0
- package/lib/commonjs/scanner/index.js.map +1 -0
- package/lib/commonjs/types/index.js +37 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/module/index.js +27 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/nfc/index.js +317 -0
- package/lib/module/nfc/index.js.map +1 -0
- package/lib/module/printer/index.js +374 -0
- package/lib/module/printer/index.js.map +1 -0
- package/lib/module/scanner/index.js +294 -0
- package/lib/module/scanner/index.js.map +1 -0
- package/lib/module/types/index.js +38 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/typescript/index.d.ts +21 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/nfc/index.d.ts +83 -0
- package/lib/typescript/nfc/index.d.ts.map +1 -0
- package/lib/typescript/printer/index.d.ts +91 -0
- package/lib/typescript/printer/index.d.ts.map +1 -0
- package/lib/typescript/scanner/index.d.ts +81 -0
- package/lib/typescript/scanner/index.d.ts.map +1 -0
- package/lib/typescript/types/index.d.ts +114 -0
- package/lib/typescript/types/index.d.ts.map +1 -0
- package/package.json +104 -0
- package/src/index.ts +55 -0
- package/src/nfc/index.ts +362 -0
- package/src/printer/index.ts +432 -0
- package/src/scanner/index.tsx +397 -0
- package/src/types/index.ts +161 -0
package/README.md
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# react-native-telpo
|
|
2
|
+
|
|
3
|
+
Production-ready React Native SDK for **Telpo** POS and ticket validation devices.
|
|
4
|
+
|
|
5
|
+
| Module | Feature | Devices |
|
|
6
|
+
|---|---|---|
|
|
7
|
+
| `TelpoPrinter` | Thermal receipt & ticket printing | M1, TPS320 |
|
|
8
|
+
| `TelpoNfc` | NFC / contactless card UID reading | T20, TPS320 |
|
|
9
|
+
| `TelpoScanner` | QR code & barcode scanning | T20, M1, TPS320 |
|
|
10
|
+
|
|
11
|
+
> **Android only.** Telpo devices run Android. iOS is not supported for printing or NFC.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npm install react-native-telpo
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Required peer dependencies
|
|
22
|
+
|
|
23
|
+
Install all three — only the modules you use will actually load at runtime:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
npm install \
|
|
27
|
+
@haroldtran/react-native-thermal-printer \
|
|
28
|
+
react-native-nfc-manager \
|
|
29
|
+
react-native-vision-camera
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Android Setup
|
|
35
|
+
|
|
36
|
+
### 1. `android/build.gradle` — Add JitPack
|
|
37
|
+
|
|
38
|
+
```groovy
|
|
39
|
+
allprojects {
|
|
40
|
+
repositories {
|
|
41
|
+
// ...
|
|
42
|
+
maven { url "https://jitpack.io" }
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. `android/app/build.gradle` — Min SDK
|
|
48
|
+
|
|
49
|
+
```groovy
|
|
50
|
+
android {
|
|
51
|
+
defaultConfig {
|
|
52
|
+
minSdkVersion 21 // Required by vision-camera
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 3. `android/app/src/main/AndroidManifest.xml` — Permissions
|
|
58
|
+
|
|
59
|
+
```xml
|
|
60
|
+
<!-- USB printer (M1 / TPS320 internal printer) -->
|
|
61
|
+
<uses-feature android:name="android.hardware.usb.host" />
|
|
62
|
+
|
|
63
|
+
<!-- NFC (T20 / TPS320) -->
|
|
64
|
+
<uses-permission android:name="android.permission.NFC" />
|
|
65
|
+
<uses-feature android:name="android.hardware.nfc" android:required="false" />
|
|
66
|
+
|
|
67
|
+
<!-- Camera (scanner) -->
|
|
68
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
69
|
+
|
|
70
|
+
<!-- Bluetooth printer (optional) -->
|
|
71
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
72
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
73
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Usage
|
|
79
|
+
|
|
80
|
+
### Printer — Telpo M1 / TPS320
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { TelpoPrinter } from 'react-native-telpo';
|
|
84
|
+
|
|
85
|
+
// 1. Initialise (once, e.g. in useEffect or app start)
|
|
86
|
+
const initResult = await TelpoPrinter.init();
|
|
87
|
+
if (!initResult.success) {
|
|
88
|
+
console.error(initResult.error.message);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 2. Connect (USB = internal printer, default)
|
|
93
|
+
const connectResult = await TelpoPrinter.connect(); // connectionType: 'USB' by default
|
|
94
|
+
if (!connectResult.success) {
|
|
95
|
+
console.error(connectResult.error.message);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 3. Print a bus ticket
|
|
100
|
+
const printResult = await TelpoPrinter.printTicket({
|
|
101
|
+
operatorName: 'City Bus Services',
|
|
102
|
+
route: 'Route 42 — City Centre → Airport',
|
|
103
|
+
passenger: 'John Doe',
|
|
104
|
+
ticketId: 'TKT-001234',
|
|
105
|
+
fare: 'SLE 5.00',
|
|
106
|
+
dateTime: '2025-06-06 14:30:00', // optional, defaults to now
|
|
107
|
+
extras: { 'Bus No': 'BUS-007' },
|
|
108
|
+
footer: 'Thank you for travelling!',
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// 4. Disconnect when done
|
|
112
|
+
await TelpoPrinter.disconnect();
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Print custom lines
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
await TelpoPrinter.printLines([
|
|
119
|
+
{ text: 'CITY BUS', alignment: 'CENTER', bold: true, fontSize: 'LARGE' },
|
|
120
|
+
{ text: '================================', alignment: 'CENTER' },
|
|
121
|
+
{ text: 'Ticket: TKT-001234', alignment: 'LEFT' },
|
|
122
|
+
{ text: 'Fare: SLE 5.00', alignment: 'LEFT' },
|
|
123
|
+
]);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### Bluetooth printer
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
await TelpoPrinter.connect({
|
|
130
|
+
connectionType: 'BLUETOOTH',
|
|
131
|
+
bluetoothAddress: 'AA:BB:CC:DD:EE:FF',
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### NFC — Telpo T20 / TPS320
|
|
138
|
+
|
|
139
|
+
#### Single tap (one-shot read)
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { TelpoNfc } from 'react-native-telpo';
|
|
143
|
+
|
|
144
|
+
// Initialise once
|
|
145
|
+
await TelpoNfc.init();
|
|
146
|
+
|
|
147
|
+
// Wait for a card tap — resolves when card is detected
|
|
148
|
+
const result = await TelpoNfc.readTag();
|
|
149
|
+
|
|
150
|
+
if (result.success) {
|
|
151
|
+
const { uid, technology } = result.data;
|
|
152
|
+
console.log('Card UID:', uid); // "04:AB:12:CD:EF:01:23"
|
|
153
|
+
console.log('Technology:', technology); // "NfcA" | "IsoDep" | ...
|
|
154
|
+
// → now do YOUR validation logic with uid
|
|
155
|
+
} else {
|
|
156
|
+
console.error(result.error.message);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### Continuous listening (validation gate)
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
import { TelpoNfc } from 'react-native-telpo';
|
|
164
|
+
|
|
165
|
+
// Start listening — fires callback on every tap
|
|
166
|
+
TelpoNfc.startListening((result) => {
|
|
167
|
+
if (result.success) {
|
|
168
|
+
const uid = result.data.uid;
|
|
169
|
+
// → call your API, update state, play sound, etc.
|
|
170
|
+
console.log('Card tapped:', uid);
|
|
171
|
+
} else {
|
|
172
|
+
console.error('NFC error:', result.error.message);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Later, when unmounting:
|
|
177
|
+
await TelpoNfc.stopListening();
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### With timeout
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
// Auto-cancel if no card tapped within 10 seconds
|
|
184
|
+
const result = await TelpoNfc.readTag({}, 10_000);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
### Scanner — QR / Barcode
|
|
190
|
+
|
|
191
|
+
#### Hook + View (recommended)
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { useTelpoScanner, TelpoScannerView } from 'react-native-telpo';
|
|
195
|
+
import type { ScanResult } from 'react-native-telpo';
|
|
196
|
+
|
|
197
|
+
function ValidatorScreen() {
|
|
198
|
+
const scanner = useTelpoScanner({
|
|
199
|
+
onResult: (result) => {
|
|
200
|
+
if (result.success) {
|
|
201
|
+
const { value, format, timestamp } = result.data;
|
|
202
|
+
console.log('Scanned:', value);
|
|
203
|
+
// → value is the raw ticket ID / QR content
|
|
204
|
+
// → do YOUR lookup logic here
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
options: {
|
|
208
|
+
formats: ['QR_CODE', 'CODE_128'], // filter to specific formats
|
|
209
|
+
deduplicateMs: 1500, // ignore same code for 1.5s
|
|
210
|
+
},
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<TelpoScannerView
|
|
215
|
+
scanner={scanner}
|
|
216
|
+
style={{ flex: 1 }}
|
|
217
|
+
showOverlay={true}
|
|
218
|
+
overlayColor="#00FF88"
|
|
219
|
+
/>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Result Pattern
|
|
227
|
+
|
|
228
|
+
Every async method returns `TelpoResult<T>`:
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
type TelpoResult<T> =
|
|
232
|
+
| { success: true; data: T }
|
|
233
|
+
| { success: false; error: { code: TelpoErrorCode; message: string } };
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Always check `result.success` before accessing `result.data`:
|
|
237
|
+
|
|
238
|
+
```typescript
|
|
239
|
+
const result = await TelpoPrinter.printTicket({ ticketId: 'TKT-001' });
|
|
240
|
+
|
|
241
|
+
if (result.success) {
|
|
242
|
+
// result.data is void for print methods
|
|
243
|
+
console.log('Printed!');
|
|
244
|
+
} else {
|
|
245
|
+
// result.error.code is a TelpoErrorCode enum value
|
|
246
|
+
switch (result.error.code) {
|
|
247
|
+
case 'PRINTER_NO_PAPER':
|
|
248
|
+
alert('Out of paper!');
|
|
249
|
+
break;
|
|
250
|
+
case 'PRINTER_NOT_CONNECTED':
|
|
251
|
+
alert('Printer not connected!');
|
|
252
|
+
break;
|
|
253
|
+
default:
|
|
254
|
+
console.error(result.error.message);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## Error Codes
|
|
262
|
+
|
|
263
|
+
| Code | Module | Meaning |
|
|
264
|
+
|---|---|---|
|
|
265
|
+
| `PRINTER_NOT_CONNECTED` | Printer | connect() not called or failed |
|
|
266
|
+
| `PRINTER_NO_PAPER` | Printer | Paper out |
|
|
267
|
+
| `PRINTER_INIT_FAILED` | Printer | init() failed or iOS |
|
|
268
|
+
| `PRINTER_PRINT_FAILED` | Printer | Print job failed |
|
|
269
|
+
| `PRINTER_PERMISSION_DENIED` | Printer | USB permission denied |
|
|
270
|
+
| `NFC_NOT_SUPPORTED` | NFC | Device has no NFC chip |
|
|
271
|
+
| `NFC_DISABLED` | NFC | NFC is off in settings |
|
|
272
|
+
| `NFC_SCAN_CANCELLED` | NFC | User/timeout cancelled |
|
|
273
|
+
| `NFC_READ_FAILED` | NFC | Tag read error |
|
|
274
|
+
| `NFC_ALREADY_LISTENING` | NFC | startListening() already active |
|
|
275
|
+
| `SCANNER_CAMERA_PERMISSION_DENIED` | Scanner | Camera access denied |
|
|
276
|
+
| `SCANNER_NOT_ACTIVE` | Scanner | Library not loaded |
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## TypeScript
|
|
281
|
+
|
|
282
|
+
The SDK is fully typed. Import types from the root:
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import type {
|
|
286
|
+
TelpoResult,
|
|
287
|
+
TelpoError,
|
|
288
|
+
TelpoErrorCode,
|
|
289
|
+
PrintTicket,
|
|
290
|
+
PrintLine,
|
|
291
|
+
NfcTag,
|
|
292
|
+
ScanResult,
|
|
293
|
+
} from 'react-native-telpo';
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## License
|
|
299
|
+
|
|
300
|
+
MIT
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "ErrorCode", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _types.TelpoErrorCode;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "TelpoNfc", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _nfc.TelpoNfc;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "TelpoPrinter", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _printer.TelpoPrinter;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "TelpoScannerView", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _scanner.TelpoScannerView;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "useTelpoScanner", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _scanner.useTelpoScanner;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
var _printer = require("./printer");
|
|
37
|
+
var _nfc = require("./nfc");
|
|
38
|
+
var _scanner = require("./scanner");
|
|
39
|
+
var _types = require("./types");
|
|
40
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_printer","require","_nfc","_scanner","_types"],"sourceRoot":"..\\..\\src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiBA,IAAAA,QAAA,GAAAC,OAAA;AACA,IAAAC,IAAA,GAAAD,OAAA;AACA,IAAAE,QAAA,GAAAF,OAAA;AAmCA,IAAAG,MAAA,GAAAH,OAAA","ignoreList":[]}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TelpoNfc = void 0;
|
|
7
|
+
var _types = require("../types");
|
|
8
|
+
/**
|
|
9
|
+
* TelpoNfc
|
|
10
|
+
*
|
|
11
|
+
* Wraps react-native-nfc-manager to provide a clean, typed API
|
|
12
|
+
* for reading NFC/contactless card UIDs on Telpo T20 and TPS320.
|
|
13
|
+
*
|
|
14
|
+
* Supports: ISO 14443-A/B (NfcA, NfcB), IsoDep, Mifare Classic,
|
|
15
|
+
* Mifare Ultralight, and NDEF tags.
|
|
16
|
+
*
|
|
17
|
+
* Returns the raw card UID as a hex string — you handle validation.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// Lazy-loaded to prevent crash if peer dep is missing
|
|
21
|
+
let NfcManager;
|
|
22
|
+
let NfcTechEnum;
|
|
23
|
+
let NfcEvents;
|
|
24
|
+
function loadNfcLib() {
|
|
25
|
+
try {
|
|
26
|
+
const lib = require('react-native-nfc-manager');
|
|
27
|
+
NfcManager = lib.default;
|
|
28
|
+
NfcTechEnum = lib.NfcTech;
|
|
29
|
+
NfcEvents = lib.NfcEvents;
|
|
30
|
+
} catch {
|
|
31
|
+
throw buildError(_types.TelpoErrorCode.NFC_NOT_SUPPORTED, 'Peer dependency react-native-nfc-manager is not installed. Run: npm install react-native-nfc-manager');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
function buildError(code, message, raw) {
|
|
38
|
+
return {
|
|
39
|
+
code,
|
|
40
|
+
message,
|
|
41
|
+
raw
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function wrapSuccess(data) {
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
data
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function wrapError(error) {
|
|
51
|
+
return {
|
|
52
|
+
success: false,
|
|
53
|
+
error
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Convert a byte array to a colon-separated hex string.
|
|
59
|
+
* e.g. [0x04, 0xAB, 0x12] → "04:AB:12"
|
|
60
|
+
*/
|
|
61
|
+
function bytesToHex(bytes) {
|
|
62
|
+
return bytes.map(b => b.toString(16).padStart(2, '0').toUpperCase()).join(':');
|
|
63
|
+
}
|
|
64
|
+
function mapTech(tech) {
|
|
65
|
+
// Map our type to the NfcTech enum values from the library
|
|
66
|
+
const map = {
|
|
67
|
+
NfcA: 'NfcA',
|
|
68
|
+
NfcB: 'NfcB',
|
|
69
|
+
IsoDep: 'IsoDep',
|
|
70
|
+
MifareClassic: 'MifareClassic',
|
|
71
|
+
MifareUltralight: 'MifareUltralight',
|
|
72
|
+
Ndef: 'Ndef'
|
|
73
|
+
};
|
|
74
|
+
return map[tech];
|
|
75
|
+
}
|
|
76
|
+
function detectTechnology(tag) {
|
|
77
|
+
if (tag.techTypes?.includes('android.nfc.tech.MifareClassic')) return 'MifareClassic';
|
|
78
|
+
if (tag.techTypes?.includes('android.nfc.tech.MifareUltralight')) return 'MifareUltralight';
|
|
79
|
+
if (tag.techTypes?.includes('android.nfc.tech.IsoDep')) return 'IsoDep';
|
|
80
|
+
if (tag.techTypes?.includes('android.nfc.tech.NfcB')) return 'NfcB';
|
|
81
|
+
if (tag.techTypes?.includes('android.nfc.tech.Ndef')) return 'Ndef';
|
|
82
|
+
return 'NfcA';
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ── State ─────────────────────────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
let _started = false;
|
|
88
|
+
let _listening = false;
|
|
89
|
+
|
|
90
|
+
// ── Module ────────────────────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* TelpoNfc
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* // One-time setup (call in your app root or screen init)
|
|
97
|
+
* await TelpoNfc.init();
|
|
98
|
+
*
|
|
99
|
+
* // Start listening for a card tap — resolves immediately on tap
|
|
100
|
+
* const result = await TelpoNfc.readTag();
|
|
101
|
+
* if (result.success) {
|
|
102
|
+
* console.log(result.data.uid); // "04:AB:12:CD:EF:01:23"
|
|
103
|
+
* }
|
|
104
|
+
*
|
|
105
|
+
* // For continuous listening (e.g. validator gate)
|
|
106
|
+
* TelpoNfc.startListening((result) => {
|
|
107
|
+
* if (result.success) {
|
|
108
|
+
* handleCard(result.data.uid);
|
|
109
|
+
* }
|
|
110
|
+
* });
|
|
111
|
+
* // Later:
|
|
112
|
+
* TelpoNfc.stopListening();
|
|
113
|
+
*/
|
|
114
|
+
const TelpoNfc = exports.TelpoNfc = {
|
|
115
|
+
get _started() {
|
|
116
|
+
return _started;
|
|
117
|
+
},
|
|
118
|
+
set _started(value) {
|
|
119
|
+
_started = value;
|
|
120
|
+
},
|
|
121
|
+
get _listening() {
|
|
122
|
+
return _listening;
|
|
123
|
+
},
|
|
124
|
+
set _listening(value) {
|
|
125
|
+
_listening = value;
|
|
126
|
+
},
|
|
127
|
+
/**
|
|
128
|
+
* Initialise NFC and verify it is supported and enabled on the device.
|
|
129
|
+
* Call once on app start or screen mount.
|
|
130
|
+
*/
|
|
131
|
+
async init() {
|
|
132
|
+
try {
|
|
133
|
+
loadNfcLib();
|
|
134
|
+
} catch (e) {
|
|
135
|
+
return wrapError(e);
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const supported = await NfcManager.isSupported();
|
|
139
|
+
if (!supported) {
|
|
140
|
+
return wrapError(buildError(_types.TelpoErrorCode.NFC_NOT_SUPPORTED, 'NFC is not supported on this device.'));
|
|
141
|
+
}
|
|
142
|
+
if (!_started) {
|
|
143
|
+
await NfcManager.start();
|
|
144
|
+
_started = true;
|
|
145
|
+
}
|
|
146
|
+
const enabled = await NfcManager.isEnabled();
|
|
147
|
+
if (!enabled) {
|
|
148
|
+
return wrapError(buildError(_types.TelpoErrorCode.NFC_DISABLED, 'NFC is disabled. Please enable NFC in device settings.'));
|
|
149
|
+
}
|
|
150
|
+
return wrapSuccess(undefined);
|
|
151
|
+
} catch (e) {
|
|
152
|
+
return wrapError(buildError(_types.TelpoErrorCode.NFC_NOT_SUPPORTED, 'Failed to initialise NFC', e));
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
/**
|
|
156
|
+
* Wait for a single NFC tag tap and resolve with its UID.
|
|
157
|
+
* Rejects if cancelled or an error occurs.
|
|
158
|
+
*
|
|
159
|
+
* This is the recommended approach for a "tap once" validation flow.
|
|
160
|
+
*
|
|
161
|
+
* @param options.technologies NFC technologies to accept (default: all)
|
|
162
|
+
* @param timeoutMs Auto-cancel after N ms (default: no timeout)
|
|
163
|
+
*/
|
|
164
|
+
async readTag(options = {}, timeoutMs) {
|
|
165
|
+
if (!_started) {
|
|
166
|
+
const initResult = await TelpoNfc.init();
|
|
167
|
+
if (!initResult.success) return initResult;
|
|
168
|
+
}
|
|
169
|
+
if (_listening) {
|
|
170
|
+
return wrapError(buildError(_types.TelpoErrorCode.NFC_ALREADY_LISTENING, 'NFC is already in continuous-listen mode. Call stopListening() first.'));
|
|
171
|
+
}
|
|
172
|
+
const techs = (options.technologies ?? ['NfcA', 'NfcB', 'IsoDep', 'MifareClassic', 'MifareUltralight', 'Ndef']).map(mapTech).map(t => NfcTechEnum[t]).filter(Boolean);
|
|
173
|
+
let timeoutHandle = null;
|
|
174
|
+
try {
|
|
175
|
+
const tagPromise = new Promise(async (resolve, reject) => {
|
|
176
|
+
try {
|
|
177
|
+
await NfcManager.requestTechnology(techs);
|
|
178
|
+
const rawTag = await NfcManager.getTag();
|
|
179
|
+
if (!rawTag) {
|
|
180
|
+
reject(buildError(_types.TelpoErrorCode.NFC_READ_FAILED, 'No tag data returned.'));
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const uid = rawTag.id ? bytesToHex(rawTag.id) : 'UNKNOWN';
|
|
184
|
+
const technology = detectTechnology(rawTag);
|
|
185
|
+
resolve({
|
|
186
|
+
uid,
|
|
187
|
+
technology,
|
|
188
|
+
raw: rawTag
|
|
189
|
+
});
|
|
190
|
+
} catch (e) {
|
|
191
|
+
if (e?.message?.includes('Cancel') || e?.message?.includes('cancel')) {
|
|
192
|
+
reject(buildError(_types.TelpoErrorCode.NFC_SCAN_CANCELLED, 'NFC scan was cancelled.'));
|
|
193
|
+
} else {
|
|
194
|
+
reject(buildError(_types.TelpoErrorCode.NFC_READ_FAILED, 'Failed to read NFC tag', e));
|
|
195
|
+
}
|
|
196
|
+
} finally {
|
|
197
|
+
await NfcManager.cancelTechnologyRequest().catch(() => null);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
let tag;
|
|
201
|
+
if (timeoutMs) {
|
|
202
|
+
tag = await Promise.race([tagPromise, new Promise((_, reject) => {
|
|
203
|
+
timeoutHandle = setTimeout(() => {
|
|
204
|
+
NfcManager.cancelTechnologyRequest().catch(() => null);
|
|
205
|
+
reject(buildError(_types.TelpoErrorCode.NFC_SCAN_CANCELLED, `NFC scan timed out after ${timeoutMs}ms.`));
|
|
206
|
+
}, timeoutMs);
|
|
207
|
+
})]);
|
|
208
|
+
} else {
|
|
209
|
+
tag = await tagPromise;
|
|
210
|
+
}
|
|
211
|
+
return wrapSuccess(tag);
|
|
212
|
+
} catch (e) {
|
|
213
|
+
const err = e;
|
|
214
|
+
if (err.code) return wrapError(err);
|
|
215
|
+
return wrapError(buildError(_types.TelpoErrorCode.NFC_READ_FAILED, 'Unexpected NFC error', e));
|
|
216
|
+
} finally {
|
|
217
|
+
if (timeoutHandle !== null) clearTimeout(timeoutHandle);
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
/**
|
|
221
|
+
* Start continuous NFC listening — ideal for a validation gate that
|
|
222
|
+
* must handle many card taps without user interaction.
|
|
223
|
+
*
|
|
224
|
+
* The callback fires every time a card is tapped.
|
|
225
|
+
* Call `stopListening()` to end the session.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* TelpoNfc.startListening((result) => {
|
|
229
|
+
* if (result.success) {
|
|
230
|
+
* console.log('Card UID:', result.data.uid);
|
|
231
|
+
* }
|
|
232
|
+
* }, { technologies: ['NfcA', 'IsoDep'] });
|
|
233
|
+
*/
|
|
234
|
+
startListening(onTag, options = {}) {
|
|
235
|
+
if (!_started) {
|
|
236
|
+
// Auto-init in background; errors surface via callback
|
|
237
|
+
TelpoNfc.init().then(initResult => {
|
|
238
|
+
if (!initResult.success) {
|
|
239
|
+
onTag(initResult);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
_startEventLoop(onTag, options);
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
_startEventLoop(onTag, options);
|
|
247
|
+
},
|
|
248
|
+
/**
|
|
249
|
+
* Stop continuous NFC listening started by `startListening()`.
|
|
250
|
+
*/
|
|
251
|
+
async stopListening() {
|
|
252
|
+
_listening = false;
|
|
253
|
+
if (!NfcManager) return;
|
|
254
|
+
NfcManager.setEventListener(NfcEvents.DiscoverTag, null);
|
|
255
|
+
NfcManager.setEventListener(NfcEvents.SessionClosed, null);
|
|
256
|
+
try {
|
|
257
|
+
await NfcManager.unregisterTagEvent();
|
|
258
|
+
} catch {
|
|
259
|
+
// Ignore — may already be unregistered
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
/**
|
|
263
|
+
* Whether NFC is supported and enabled on this device.
|
|
264
|
+
* Returns false if not initialised yet.
|
|
265
|
+
*/
|
|
266
|
+
async isAvailable() {
|
|
267
|
+
try {
|
|
268
|
+
loadNfcLib();
|
|
269
|
+
const supported = await NfcManager.isSupported();
|
|
270
|
+
if (!supported) return false;
|
|
271
|
+
return await NfcManager.isEnabled();
|
|
272
|
+
} catch {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
/** Whether the continuous listener is currently active. */
|
|
277
|
+
isListening() {
|
|
278
|
+
return _listening;
|
|
279
|
+
},
|
|
280
|
+
/** Whether NfcManager has been started. */
|
|
281
|
+
isStarted() {
|
|
282
|
+
return _started;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// ── Internal event loop for startListening ───────────────────────────────────
|
|
287
|
+
|
|
288
|
+
function _startEventLoop(onTag, _options) {
|
|
289
|
+
if (_listening) {
|
|
290
|
+
onTag(wrapError(buildError(_types.TelpoErrorCode.NFC_ALREADY_LISTENING, 'NFC listener is already active.')));
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
_listening = true;
|
|
294
|
+
const _handleTag = rawTag => {
|
|
295
|
+
if (!rawTag) {
|
|
296
|
+
onTag(wrapError(buildError(_types.TelpoErrorCode.NFC_READ_FAILED, 'Empty tag received.')));
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const uid = rawTag.id ? bytesToHex(rawTag.id) : 'UNKNOWN';
|
|
300
|
+
const technology = detectTechnology(rawTag);
|
|
301
|
+
onTag(wrapSuccess({
|
|
302
|
+
uid,
|
|
303
|
+
technology,
|
|
304
|
+
raw: rawTag
|
|
305
|
+
}));
|
|
306
|
+
};
|
|
307
|
+
const _handleClose = () => {
|
|
308
|
+
if (_listening) {
|
|
309
|
+
// Session closed unexpectedly — restart
|
|
310
|
+
NfcManager.registerTagEvent().catch(() => {
|
|
311
|
+
_listening = false;
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
NfcManager.setEventListener(NfcEvents.DiscoverTag, _handleTag);
|
|
316
|
+
NfcManager.setEventListener(NfcEvents.SessionClosed, _handleClose);
|
|
317
|
+
NfcManager.registerTagEvent().catch(e => {
|
|
318
|
+
_listening = false;
|
|
319
|
+
onTag(wrapError(buildError(_types.TelpoErrorCode.NFC_READ_FAILED, 'Failed to register NFC tag event', e)));
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_types","require","NfcManager","NfcTechEnum","NfcEvents","loadNfcLib","lib","default","NfcTech","buildError","TelpoErrorCode","NFC_NOT_SUPPORTED","code","message","raw","wrapSuccess","data","success","wrapError","error","bytesToHex","bytes","map","b","toString","padStart","toUpperCase","join","mapTech","tech","NfcA","NfcB","IsoDep","MifareClassic","MifareUltralight","Ndef","detectTechnology","tag","techTypes","includes","_started","_listening","TelpoNfc","exports","value","init","e","supported","isSupported","start","enabled","isEnabled","NFC_DISABLED","undefined","readTag","options","timeoutMs","initResult","NFC_ALREADY_LISTENING","techs","technologies","t","filter","Boolean","timeoutHandle","tagPromise","Promise","resolve","reject","requestTechnology","rawTag","getTag","NFC_READ_FAILED","uid","id","technology","NFC_SCAN_CANCELLED","cancelTechnologyRequest","catch","race","_","setTimeout","err","clearTimeout","startListening","onTag","then","_startEventLoop","stopListening","setEventListener","DiscoverTag","SessionClosed","unregisterTagEvent","isAvailable","isListening","isStarted","_options","_handleTag","_handleClose","registerTagEvent"],"sourceRoot":"..\\..\\..\\src","sources":["nfc/index.ts"],"mappings":"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","ignoreList":[]}
|