@spencerls/react-native-nfc 1.0.7 → 1.0.9

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/dist/index.mjs CHANGED
@@ -4,28 +4,161 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
- // src/nfc/a/index.ts
8
- var a_exports = {};
9
- __export(a_exports, {
10
- operations: () => operations,
11
- utils: () => utils
7
+ // src/nfc/ndef/builder.ts
8
+ import {
9
+ Ndef
10
+ } from "react-native-nfc-manager";
11
+ var mimeTypes = {
12
+ TEXT: "text/plain",
13
+ JSON: "application/json"
14
+ };
15
+ var Builder = class _Builder {
16
+ static records(b) {
17
+ return b(_Builder);
18
+ }
19
+ static message(b) {
20
+ return Ndef.encodeMessage(b(_Builder));
21
+ }
22
+ static record(init) {
23
+ const { tnf, type, id = [], payload = [] } = init;
24
+ const toBytes = (v) => typeof v === "string" ? Array.from(Buffer.from(v, "utf8")) : v;
25
+ return {
26
+ tnf,
27
+ type: toBytes(type),
28
+ id: toBytes(id),
29
+ payload: toBytes(payload)
30
+ };
31
+ }
32
+ static textRecord(text, lang = "en", encoding = "utf8", id) {
33
+ const record = Ndef.textRecord(text, lang, encoding);
34
+ if (id) record.id = Array.from(Buffer.from(id, "utf8"));
35
+ return record;
36
+ }
37
+ static uriRecord(uri, id) {
38
+ return Ndef.uriRecord(uri, id);
39
+ }
40
+ static jsonRecord(payload, id) {
41
+ return _Builder.mimeRecord(mimeTypes.JSON, payload, id);
42
+ }
43
+ static mimeRecord(mimeType, payload, id) {
44
+ const payloadBytes = typeof payload === "string" ? Array.from(Buffer.from(payload, "utf8")) : payload instanceof Uint8Array ? Array.from(payload) : payload;
45
+ const idBytes = id ? Array.from(Buffer.from(id, "utf8")) : [];
46
+ return _Builder.record({
47
+ tnf: Ndef.TNF_MIME_MEDIA,
48
+ type: mimeType,
49
+ id: idBytes,
50
+ payload: payloadBytes
51
+ });
52
+ }
53
+ static externalRecord(domain, type, payload, id) {
54
+ const recordType = `${domain}:${type}`;
55
+ const payloadBytes = typeof payload === "string" ? Array.from(Buffer.from(payload, "utf8")) : payload instanceof Uint8Array ? Array.from(payload) : payload;
56
+ const idBytes = id ? Array.from(Buffer.from(id, "utf8")) : [];
57
+ return _Builder.record({
58
+ tnf: Ndef.TNF_EXTERNAL_TYPE,
59
+ type: recordType,
60
+ id: idBytes,
61
+ payload: payloadBytes
62
+ });
63
+ }
64
+ static createEmpty() {
65
+ return _Builder.record({
66
+ tnf: Ndef.TNF_EMPTY,
67
+ type: [],
68
+ id: [],
69
+ payload: []
70
+ });
71
+ }
72
+ };
73
+
74
+ // src/nfc/ndef/internal/operations.ts
75
+ var operations_exports = {};
76
+ __export(operations_exports, {
77
+ readMessage: () => readMessage,
78
+ write: () => write
12
79
  });
80
+ import nfcManager, { Ndef as Ndef2 } from "react-native-nfc-manager";
13
81
 
14
- // src/nfc/a/operations.ts
15
- import NfcManager2, { NfcTech } from "react-native-nfc-manager";
82
+ // src/nfc/ndef/error.ts
83
+ var NdefError = class extends Error {
84
+ constructor(message) {
85
+ super(`[NDEF] ${message}`);
86
+ }
87
+ };
16
88
 
17
- // src/nfc/service.ts
89
+ // src/nfc/ndef/internal/operations.ts
90
+ function assertMessage(msg) {
91
+ if (!msg.ndefMessage || msg.ndefMessage.length === 0) {
92
+ throw new NdefError("NDEF message contains no NDEF records");
93
+ }
94
+ }
95
+ async function readMessage() {
96
+ const msg = await nfcManager.ndefHandler.getNdefMessage();
97
+ if (!msg) throw new NdefError("No NDEF message detected");
98
+ assertMessage(msg);
99
+ return msg;
100
+ }
101
+ async function write(records) {
102
+ if (records.length === 0) {
103
+ throw new NdefError("Cannot write an empty records array");
104
+ }
105
+ const bytes = Ndef2.encodeMessage(records);
106
+ await nfcManager.ndefHandler.writeNdefMessage(bytes);
107
+ }
108
+
109
+ // src/nfc/ndef/internal/tech.ts
18
110
  import { Platform } from "react-native";
19
- import NfcManager, {
111
+ import { NfcTech } from "react-native-nfc-manager";
112
+ var tech = Platform.OS === "android" ? [NfcTech.Ndef, NfcTech.NfcA] : [NfcTech.Ndef];
113
+
114
+ // src/nfc/ndef/internal/index.ts
115
+ var nfcNdefTag = {
116
+ ...operations_exports,
117
+ tech
118
+ };
119
+
120
+ // src/nfc/ndef/operations.ts
121
+ var operations_exports4 = {};
122
+ __export(operations_exports4, {
123
+ getStatus: () => getStatus,
124
+ makeReadOnly: () => makeReadOnly,
125
+ readFull: () => readFull,
126
+ readMessage: () => readMessage2,
127
+ write: () => write2,
128
+ writeExternal: () => writeExternal,
129
+ writeJson: () => writeJson,
130
+ writeMime: () => writeMime,
131
+ writeText: () => writeText,
132
+ writeUri: () => writeUri
133
+ });
134
+ import nfcManager4 from "react-native-nfc-manager";
135
+
136
+ // src/nfc/service.ts
137
+ import { Platform as Platform2 } from "react-native";
138
+ import nfcManager2, {
20
139
  NfcEvents
21
140
  } from "react-native-nfc-manager";
141
+
142
+ // src/nfc/error.ts
143
+ var NfcError = class extends Error {
144
+ constructor(message) {
145
+ super(`[NFC] ${message}`);
146
+ }
147
+ };
148
+
149
+ // src/nfc/service.ts
22
150
  var NfcService = class {
23
151
  constructor() {
24
152
  this.state = { mode: "idle", tag: null };
25
153
  this.listeners = /* @__PURE__ */ new Set();
26
154
  this.isProcessingTag = false;
27
155
  this.currentCooldownMs = 1500;
28
- NfcManager.start();
156
+ this.readerModeFlags_ANDROID = null;
157
+ nfcManager2.start();
158
+ }
159
+ enableReaderMode_ANDROID(flags) {
160
+ if (Platform2.OS !== "android") return;
161
+ this.readerModeFlags_ANDROID = flags;
29
162
  }
30
163
  // -----------------------------
31
164
  // Internal state management
@@ -47,7 +180,7 @@ var NfcService = class {
47
180
  // -----------------------------
48
181
  // START READER (Soft Continuous Mode)
49
182
  // -----------------------------
50
- async startReader(readerModeFlags, onTag, options) {
183
+ async startReader(onTag, options) {
51
184
  var _a;
52
185
  if (this.state.mode !== "idle") {
53
186
  console.warn(`[NFC] Cannot start reader while ${this.state.mode}`);
@@ -57,7 +190,7 @@ var NfcService = class {
57
190
  this.currentCooldownMs = (_a = options == null ? void 0 : options.cooldownMs) != null ? _a : 1500;
58
191
  this.isProcessingTag = false;
59
192
  this.setState({ mode: "starting", tag: null });
60
- NfcManager.setEventListener(
193
+ nfcManager2.setEventListener(
61
194
  NfcEvents.DiscoverTag,
62
195
  async (tag) => {
63
196
  var _a2;
@@ -71,18 +204,26 @@ var NfcService = class {
71
204
  console.warn("[NFC] onTag handler error:", err);
72
205
  } finally {
73
206
  const cooldown = this.currentCooldownMs;
74
- setTimeout(() => {
207
+ if (this.cooldownTimer) {
208
+ clearTimeout(this.cooldownTimer);
209
+ }
210
+ this.cooldownTimer = setTimeout(() => {
75
211
  this.isProcessingTag = false;
76
- this.setState({ tag: null, mode: "active" });
212
+ this.setState({ tag: null });
213
+ this.cooldownTimer = void 0;
77
214
  }, cooldown);
78
215
  }
79
216
  }
80
217
  );
81
218
  try {
82
- await NfcManager.registerTagEvent({
83
- isReaderModeEnabled: true,
84
- readerModeFlags
85
- });
219
+ if (this.readerModeFlags_ANDROID) {
220
+ await nfcManager2.registerTagEvent({
221
+ isReaderModeEnabled: true,
222
+ readerModeFlags: this.readerModeFlags_ANDROID
223
+ });
224
+ } else {
225
+ await nfcManager2.registerTagEvent();
226
+ }
86
227
  if (this.state.mode === "starting") {
87
228
  this.setState({ mode: "active" });
88
229
  }
@@ -97,14 +238,24 @@ var NfcService = class {
97
238
  async stopReader() {
98
239
  if (["idle", "stopping"].includes(this.state.mode)) return;
99
240
  this.setState({ mode: "stopping" });
241
+ nfcManager2.setEventListener(NfcEvents.DiscoverTag, () => {
242
+ });
243
+ if (this.cooldownTimer) {
244
+ clearTimeout(this.cooldownTimer);
245
+ this.cooldownTimer = void 0;
246
+ }
100
247
  try {
101
- await NfcManager.unregisterTagEvent();
248
+ await nfcManager2.unregisterTagEvent();
102
249
  } catch (err) {
103
250
  console.warn("[NFC] unregisterTagEvent error:", err);
104
251
  }
105
252
  this._resetReaderState();
106
253
  }
107
254
  _resetReaderState() {
255
+ if (this.cooldownTimer) {
256
+ clearTimeout(this.cooldownTimer);
257
+ this.cooldownTimer = void 0;
258
+ }
108
259
  this.setState({ mode: "idle", tag: null });
109
260
  this.currentOnTag = void 0;
110
261
  this.isProcessingTag = false;
@@ -112,318 +263,431 @@ var NfcService = class {
112
263
  // -----------------------------
113
264
  // Technology sessions (NDEF, NfcV, etc.)
114
265
  // -----------------------------
115
- async withTechnology(tech, handler) {
266
+ async withTechnology(tech3, handler) {
116
267
  if (this.state.mode === "technology") {
117
- throw new Error("[NFC] Technology is already in use!");
268
+ throw new NfcError("Technology is already in use!");
118
269
  }
119
- if (["starting", "active", "stopping"].includes(this.state.mode)) {
270
+ if (this.readerModeFlags_ANDROID) {
271
+ return this.withTechnologyReaderMode_ANDROID(
272
+ tech3,
273
+ handler,
274
+ this.readerModeFlags_ANDROID
275
+ );
276
+ }
277
+ const readerWasActive = ["starting", "active", "stopping"].includes(
278
+ this.state.mode
279
+ );
280
+ const savedOnTag = this.currentOnTag;
281
+ const savedCooldown = this.currentCooldownMs;
282
+ if (readerWasActive) {
120
283
  await this.stopReader();
121
284
  }
122
285
  if (this.state.mode !== "idle") {
123
- throw new Error(
124
- `[NFC] Cannot start technology session in mode ${this.state.mode}`
286
+ throw new NfcError(
287
+ `Cannot start technology session in mode ${this.state.mode}`
125
288
  );
126
289
  }
127
- this.setState({ mode: "technology", tag: null });
290
+ this.setState({ mode: "technology" });
128
291
  try {
129
- await NfcManager.requestTechnology(tech, {
292
+ await nfcManager2.requestTechnology(tech3, {
130
293
  alertMessage: "Hold near NFC tag"
131
294
  });
132
295
  const result = await handler();
133
- if (Platform.OS === "ios") {
134
- await NfcManager.setAlertMessageIOS("Success!");
296
+ if (Platform2.OS === "ios") {
297
+ await nfcManager2.setAlertMessageIOS("Success!");
135
298
  }
136
299
  return result;
137
300
  } catch (err) {
138
301
  const message = typeof err === "string" ? err : (err == null ? void 0 : err.message) || "Unknown NFC error";
139
- throw new Error(`[NFC] withTechnology error: ${message}`);
302
+ throw new NfcError(`withTechnology error: ${message}`);
140
303
  } finally {
141
304
  try {
142
- await NfcManager.cancelTechnologyRequest();
305
+ await nfcManager2.cancelTechnologyRequest();
143
306
  } catch {
144
307
  }
145
308
  this.setState({ mode: "idle", tag: null });
309
+ if (readerWasActive) {
310
+ try {
311
+ await this.startReader(savedOnTag, { cooldownMs: savedCooldown });
312
+ } catch (err) {
313
+ console.warn(
314
+ "[NFC] Failed to restart reader after tech session",
315
+ err
316
+ );
317
+ }
318
+ }
319
+ }
320
+ }
321
+ async withTechnologyReaderMode_ANDROID(tech3, handler, flags) {
322
+ const readerWasActive = ["starting", "active", "stopping"].includes(
323
+ this.state.mode
324
+ );
325
+ this.isProcessingTag = true;
326
+ this.setState({ mode: "technology" });
327
+ try {
328
+ await nfcManager2.requestTechnology(tech3, {
329
+ isReaderModeEnabled: true,
330
+ readerModeFlags: flags
331
+ });
332
+ return await handler();
333
+ } catch (err) {
334
+ const message = typeof err === "string" ? err : (err == null ? void 0 : err.message) || "Unknown NFC error";
335
+ throw new NfcError(`withTechnologyReaderMode_ANDROID error: ${message}`);
336
+ } finally {
337
+ try {
338
+ await nfcManager2.cancelTechnologyRequest();
339
+ } catch {
340
+ }
341
+ this.isProcessingTag = false;
342
+ this.setState({ mode: readerWasActive ? "active" : "idle" });
146
343
  }
147
344
  }
148
345
  };
149
346
  var nfcService = new NfcService();
150
347
 
151
- // src/nfc/a/operations.ts
152
- var operations = {
153
- async transceive(data) {
154
- return nfcService.withTechnology(NfcTech.NfcA, async () => {
155
- return await NfcManager2.transceive(data);
156
- });
157
- }
158
- };
348
+ // src/nfc/tag/internal/operations.ts
349
+ var operations_exports2 = {};
350
+ __export(operations_exports2, {
351
+ getTag: () => getTag
352
+ });
353
+ import nfcManager3 from "react-native-nfc-manager";
354
+ async function getTag() {
355
+ const tagEvent = await nfcManager3.getTag();
356
+ if (!tagEvent) throw new Error("No tag detected");
357
+ return tagEvent;
358
+ }
159
359
 
160
- // src/nfc/a/utils.ts
161
- var utils = {};
360
+ // src/nfc/tag/internal/index.ts
361
+ var nfcTag = {
362
+ ...operations_exports2
363
+ };
162
364
 
163
- // src/nfc/v/index.ts
164
- var v_exports = {};
165
- __export(v_exports, {
166
- operations: () => operations2,
167
- utils: () => utils2
365
+ // src/nfc/tag/operations.ts
366
+ var operations_exports3 = {};
367
+ __export(operations_exports3, {
368
+ getTag: () => getTag2
168
369
  });
370
+ async function getTag2(tech3) {
371
+ return nfcService.withTechnology(tech3, nfcTag.getTag);
372
+ }
169
373
 
170
- // src/nfc/v/operations.ts
171
- import NfcManager4 from "react-native-nfc-manager";
374
+ // src/nfc/ndef/operations.ts
375
+ async function getStatus() {
376
+ return await nfcManager4.ndefHandler.getNdefStatus();
377
+ }
378
+ async function readMessage2() {
379
+ return await nfcService.withTechnology(
380
+ nfcNdefTag.tech,
381
+ nfcNdefTag.readMessage
382
+ );
383
+ }
384
+ async function readFull() {
385
+ return await nfcService.withTechnology(nfcNdefTag.tech, async () => {
386
+ const tag = await nfcTag.getTag();
387
+ const message = await nfcNdefTag.readMessage();
388
+ return { message, tag };
389
+ });
390
+ }
391
+ async function write2(records) {
392
+ if (!records || records.length === 0) {
393
+ throw new NdefError("write: no NDEF records provided");
394
+ }
395
+ await nfcService.withTechnology(
396
+ nfcNdefTag.tech,
397
+ async () => await nfcNdefTag.write(records)
398
+ );
399
+ }
400
+ async function writeText(text, lang, encoding, id) {
401
+ const rec = Builder.textRecord(text, lang, encoding, id);
402
+ await write2([rec]);
403
+ }
404
+ async function writeUri(uri, id) {
405
+ const rec = Builder.uriRecord(uri, id);
406
+ await write2([rec]);
407
+ }
408
+ async function writeJson(data, id) {
409
+ let json;
410
+ try {
411
+ json = JSON.stringify(data);
412
+ } catch (e) {
413
+ throw new NdefError(`writeJson: value is not JSON serializable: ${e}`);
414
+ }
415
+ const rec = Builder.jsonRecord(json, id);
416
+ await write2([rec]);
417
+ }
418
+ async function writeMime(mimeType, payload, id) {
419
+ if (!mimeType || typeof mimeType !== "string") {
420
+ throw new NdefError("writeMime: mimeType must be a non-empty string");
421
+ }
422
+ const rec = Builder.mimeRecord(mimeType, payload, id);
423
+ await write2([rec]);
424
+ }
425
+ async function writeExternal(domain, type, payload, id) {
426
+ if (!domain || typeof domain !== "string") {
427
+ throw new NdefError("writeExternal: domain must be a non-empty string");
428
+ }
429
+ if (!type || typeof type !== "string") {
430
+ throw new NdefError("writeExternal: type must be a non-empty string");
431
+ }
432
+ const rec = Builder.externalRecord(domain, type, payload, id);
433
+ await write2([rec]);
434
+ }
435
+ async function makeReadOnly() {
436
+ await nfcService.withTechnology(
437
+ nfcNdefTag.tech,
438
+ nfcManager4.ndefHandler.makeReadOnly
439
+ );
440
+ }
172
441
 
173
- // src/nfc/v/internal.ts
174
- import NfcManager3 from "react-native-nfc-manager";
442
+ // src/nfc/v/internal/operations.ts
443
+ var operations_exports5 = {};
444
+ __export(operations_exports5, {
445
+ getSystemInfo: () => getSystemInfo,
446
+ readBlock: () => readBlock,
447
+ readBlocks: () => readBlocks,
448
+ transceive: () => transceive,
449
+ writeBlock: () => writeBlock,
450
+ writeBlocks: () => writeBlocks
451
+ });
452
+ import nfcManager5 from "react-native-nfc-manager";
175
453
 
176
- // src/nfc/v/utils.ts
177
- import { Platform as Platform2 } from "react-native";
178
- import { NfcTech as NfcTech2 } from "react-native-nfc-manager";
179
- var utils2 = {
180
- tech: Platform2.OS === "ios" ? [NfcTech2.Iso15693IOS] : NfcTech2.NfcV,
181
- Flags: {
182
- HIGH_DATA_RATE: 2,
183
- ADDRESSED: 32
184
- // If needed later: OPTION: 0x40 (not commonly used)
185
- },
186
- Commands: {
187
- READ_SINGLE_BLOCK: 32,
188
- WRITE_SINGLE_BLOCK: 33,
189
- GET_SYSTEM_INFO: 43
190
- },
191
- /**
192
- * Combine multiple flag bits into one byte.
193
- * Example: Flags.ADDRESSED | Flags.HIGH_DATA_RATE
194
- */
195
- flags(...bits) {
196
- return bits.reduce((acc, bit) => acc | bit, 0);
197
- },
198
- /**
199
- * Convert tag.id hex string (MSB->LSB) into reversed byte array (LSB->MSB)
200
- * ISO15693 requires reversed UID for addressed commands.
201
- */
202
- reverseUid(tagIdHex) {
203
- const bytes = [];
204
- for (let i = 0; i < tagIdHex.length; i += 2) {
205
- bytes.unshift(Number.parseInt(tagIdHex.substring(i, i + 2), 16));
206
- }
207
- return bytes;
208
- },
209
- /**
210
- * Build READ_SINGLE_BLOCK command.
211
- * FLAGS: addressed + high data rate by default.
212
- */
213
- buildReadBlock(uidReversed, blockNumber) {
214
- const flags = this.flags(this.Flags.ADDRESSED, this.Flags.HIGH_DATA_RATE);
215
- return [
216
- flags,
217
- this.Commands.READ_SINGLE_BLOCK,
218
- ...uidReversed,
219
- blockNumber
220
- ];
221
- },
222
- /**
223
- * Build WRITE_SINGLE_BLOCK command.
224
- * Note: data must match the block size (usually 4 or 8 bytes).
225
- */
226
- buildWriteBlock(uidReversed, blockNumber, data) {
227
- const flags = this.flags(this.Flags.ADDRESSED, this.Flags.HIGH_DATA_RATE);
228
- return [
229
- flags,
230
- this.Commands.WRITE_SINGLE_BLOCK,
231
- ...uidReversed,
232
- blockNumber,
233
- ...data
234
- ];
235
- },
236
- /**
237
- * Build GET_SYSTEM_INFO command.
238
- */
239
- buildGetSystemInfo(uidReversed) {
240
- return [this.Flags.HIGH_DATA_RATE, this.Commands.GET_SYSTEM_INFO];
241
- },
242
- /**
243
- * Parse a READ_SINGLE_BLOCK response.
244
- * Response format:
245
- * - byte[0] = status (0x00 = success)
246
- * - byte[1..] = block payload bytes
247
- */
248
- parseReadResponse(resp) {
249
- if (!resp || resp.length === 0) {
250
- throw new Error("Empty NFC-V response");
251
- }
252
- const status = resp[0];
253
- if (status === void 0) {
254
- throw new Error("Invalid NFC-V response: missing status byte");
255
- }
256
- if (status !== 0) {
257
- throw new Error(`Read failed. Status: 0x${status.toString(16)}`);
258
- }
259
- return new Uint8Array(resp.slice(1));
260
- },
261
- /**
262
- * Parse WRITE_SINGLE_BLOCK response.
263
- * Successful write has resp[0] === 0x00.
264
- */
265
- parseWriteResponse(resp) {
266
- if (!resp || resp.length === 0) {
267
- throw new Error("Empty NFC-V response");
268
- }
269
- const status = resp[0];
270
- if (status === void 0) {
271
- throw new Error("Invalid NFC-V response: missing status byte");
272
- }
273
- if (status !== 0) {
274
- throw new Error(`Write failed. Status: 0x${status.toString(16)}`);
275
- }
276
- },
277
- /**
278
- * Parse GET_SYSTEM_INFO response.
279
- * Returns: UID, DSFID, AFI, numberOfBlocks, blockSize, manufacturer
280
- */
281
- parseSystemInfo(resp) {
282
- var _a;
283
- if (!resp || resp.length < 2) {
284
- throw new Error("Invalid System Info response");
285
- }
286
- const status = resp[0];
287
- if (status === void 0 || status !== 0) {
288
- throw new Error("Invalid System Info response");
289
- }
290
- const flagsByte = resp[1];
291
- if (flagsByte === void 0) {
292
- throw new Error("Invalid System Info response: missing flags byte");
293
- }
294
- const infoFlags = flagsByte & 15;
295
- let offset = 2;
296
- const result = {};
297
- if (resp.length >= offset + 8) {
298
- const uidBytes = resp.slice(offset, offset + 8);
299
- result.uid = uidBytes.slice().reverse().map((b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
300
- offset += 8;
301
- }
302
- if (infoFlags & 1 && resp.length > offset) {
303
- result.dsfid = resp[offset++];
304
- }
305
- if (infoFlags & 2 && resp.length > offset) {
306
- result.afi = resp[offset++];
307
- }
308
- if (infoFlags & 4 && resp.length >= offset + 2) {
309
- const numBlocks = resp[offset++];
310
- const blkSize = resp[offset++];
311
- if (numBlocks !== void 0) {
312
- result.numberOfBlocks = numBlocks + 1;
313
- }
314
- if (blkSize !== void 0) {
315
- result.blockSize = blkSize + 1;
316
- }
317
- }
318
- if (infoFlags & 8 && resp.length > offset) {
319
- result.icReference = resp[offset++];
320
- }
321
- if (!result.blockSize) result.blockSize = 4;
322
- result.manufacturer = this.detectManufacturer((_a = result.uid) != null ? _a : "");
323
- return result;
324
- },
325
- /** Identify common manufacturers based on UID prefix */
326
- detectManufacturer(uid) {
327
- if (uid.startsWith("E004") || uid.startsWith("E006") || uid.startsWith("E016"))
328
- return "EM Microelectronic";
329
- if (uid.startsWith("E002")) return "STMicroelectronics";
330
- if (uid.startsWith("E007")) return "Texas Instruments";
331
- if (uid.startsWith("E010")) return "NXP";
332
- return "Unknown";
454
+ // src/nfc/v/error.ts
455
+ var VError = class extends Error {
456
+ constructor(message) {
457
+ super(`[V] ${message}`);
333
458
  }
334
459
  };
335
460
 
336
- // src/nfc/v/internal.ts
337
- async function readBlockRaw(tag, blockNumber) {
338
- const uid = utils2.reverseUid(tag.id);
339
- const cmd = utils2.buildReadBlock(uid, blockNumber);
340
- const resp = await NfcManager3.transceive(cmd);
341
- return utils2.parseReadResponse(resp);
342
- }
343
- async function writeBlockRaw(tag, blockNumber, data) {
344
- const uid = utils2.reverseUid(tag.id);
345
- const cmd = utils2.buildWriteBlock(uid, blockNumber, data);
346
- const resp = await NfcManager3.transceive(cmd);
347
- return utils2.parseWriteResponse(resp);
348
- }
349
- async function getSystemInfoRaw(tag) {
350
- const uid = utils2.reverseUid(tag.id);
351
- const cmd = utils2.buildGetSystemInfo(uid);
352
- const resp = await NfcManager3.transceive(cmd);
353
- return utils2.parseSystemInfo(resp);
461
+ // src/nfc/v/internal/utils.ts
462
+ var utils_exports = {};
463
+ __export(utils_exports, {
464
+ COMMANDS: () => COMMANDS,
465
+ FLAGS: () => FLAGS,
466
+ buildFlags: () => buildFlags,
467
+ buildGetSystemInfo: () => buildGetSystemInfo,
468
+ buildReadBlock: () => buildReadBlock,
469
+ buildWriteBlock: () => buildWriteBlock,
470
+ detectManufacturer: () => detectManufacturer,
471
+ parseReadResponse: () => parseReadResponse,
472
+ parseSystemInfo: () => parseSystemInfo,
473
+ parseWriteResponse: () => parseWriteResponse,
474
+ reverseUid: () => reverseUid
475
+ });
476
+ var FLAGS = {
477
+ HIGH_DATA_RATE: 2,
478
+ ADDRESSED: 32
479
+ // If needed later: OPTION: 0x40 (not commonly used)
480
+ };
481
+ var COMMANDS = {
482
+ READ_SINGLE_BLOCK: 32,
483
+ WRITE_SINGLE_BLOCK: 33,
484
+ GET_SYSTEM_INFO: 43
485
+ };
486
+ function buildFlags(...bits) {
487
+ return bits.reduce((acc, bit) => acc | bit, 0);
488
+ }
489
+ function reverseUid(tagIdHex) {
490
+ const bytes = [];
491
+ for (let i = 0; i < tagIdHex.length; i += 2) {
492
+ bytes.unshift(Number.parseInt(tagIdHex.substring(i, i + 2), 16));
493
+ }
494
+ return bytes;
495
+ }
496
+ function buildReadBlock(uidReversed, blockNumber) {
497
+ const flags = buildFlags(FLAGS.ADDRESSED, FLAGS.HIGH_DATA_RATE);
498
+ return [flags, COMMANDS.READ_SINGLE_BLOCK, ...uidReversed, blockNumber];
499
+ }
500
+ function buildWriteBlock(uidReversed, blockNumber, data) {
501
+ const flags = buildFlags(FLAGS.ADDRESSED, FLAGS.HIGH_DATA_RATE);
502
+ return [
503
+ flags,
504
+ COMMANDS.WRITE_SINGLE_BLOCK,
505
+ ...uidReversed,
506
+ blockNumber,
507
+ ...data
508
+ ];
509
+ }
510
+ function buildGetSystemInfo() {
511
+ return [FLAGS.HIGH_DATA_RATE, COMMANDS.GET_SYSTEM_INFO];
512
+ }
513
+ function parseReadResponse(resp) {
514
+ if (!resp || resp.length === 0) {
515
+ throw new Error("Empty NFC-V response");
516
+ }
517
+ const status = resp[0];
518
+ if (status === void 0) {
519
+ throw new Error("Invalid NFC-V response: missing status byte");
520
+ }
521
+ if (status !== 0) {
522
+ throw new Error(`Read failed. Status: 0x${status.toString(16)}`);
523
+ }
524
+ return new Uint8Array(resp.slice(1));
525
+ }
526
+ function parseWriteResponse(resp) {
527
+ if (!resp || resp.length === 0) {
528
+ throw new Error("Empty NFC-V response");
529
+ }
530
+ const status = resp[0];
531
+ if (status === void 0) {
532
+ throw new Error("Invalid NFC-V response: missing status byte");
533
+ }
534
+ if (status !== 0) {
535
+ throw new Error(`Write failed. Status: 0x${status.toString(16)}`);
536
+ }
537
+ }
538
+ function parseSystemInfo(resp) {
539
+ var _a;
540
+ if (!resp || resp.length < 2) {
541
+ throw new Error("Invalid System Info response");
542
+ }
543
+ const status = resp[0];
544
+ if (status === void 0 || status !== 0) {
545
+ throw new Error("Invalid System Info response");
546
+ }
547
+ const flagsByte = resp[1];
548
+ if (flagsByte === void 0) {
549
+ throw new Error("Invalid System Info response: missing flags byte");
550
+ }
551
+ const infoFlags = flagsByte & 15;
552
+ let offset = 2;
553
+ const result = {};
554
+ if (resp.length >= offset + 8) {
555
+ const uidBytes = resp.slice(offset, offset + 8);
556
+ result.uid = uidBytes.slice().reverse().map((b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
557
+ offset += 8;
558
+ }
559
+ if (infoFlags & 1 && resp.length > offset) {
560
+ result.dsfid = resp[offset++];
561
+ }
562
+ if (infoFlags & 2 && resp.length > offset) {
563
+ result.afi = resp[offset++];
564
+ }
565
+ if (infoFlags & 4 && resp.length >= offset + 2) {
566
+ const numBlocks = resp[offset++];
567
+ const blkSize = resp[offset++];
568
+ if (numBlocks !== void 0) {
569
+ result.numberOfBlocks = numBlocks + 1;
570
+ }
571
+ if (blkSize !== void 0) {
572
+ result.blockSize = blkSize + 1;
573
+ }
574
+ }
575
+ if (infoFlags & 8 && resp.length > offset) {
576
+ result.icReference = resp[offset++];
577
+ }
578
+ if (!result.blockSize) result.blockSize = 4;
579
+ result.manufacturer = detectManufacturer((_a = result.uid) != null ? _a : "");
580
+ return result;
581
+ }
582
+ function detectManufacturer(uid) {
583
+ if (uid.startsWith("E004") || uid.startsWith("E006") || uid.startsWith("E016"))
584
+ return "EM Microelectronic";
585
+ if (uid.startsWith("E002")) return "STMicroelectronics";
586
+ if (uid.startsWith("E007")) return "Texas Instruments";
587
+ if (uid.startsWith("E010")) return "NXP";
588
+ return "Unknown";
354
589
  }
355
590
 
356
- // src/nfc/v/operations.ts
357
- var operations2 = {
358
- async withVTag(handler) {
359
- return nfcService.withTechnology(utils2.tech, async () => {
360
- const tag = await NfcManager4.getTag();
361
- if (!(tag == null ? void 0 : tag.id)) throw new Error("No NFC-V tag detected");
362
- return handler(tag);
363
- });
364
- },
365
- async writeBlockNfcV(blockNumber, data) {
366
- return this.withVTag((tag) => writeBlockRaw(tag, blockNumber, data));
367
- },
368
- async readBlockNfcV(blockNumber) {
369
- return this.withVTag((tag) => readBlockRaw(tag, blockNumber));
370
- },
371
- async getSystemInfoNfcV() {
372
- return this.withVTag((tag) => getSystemInfoRaw(tag));
591
+ // src/nfc/v/internal/operations.ts
592
+ async function transceive(bytes) {
593
+ return await nfcManager5.nfcVHandler.transceive(bytes);
594
+ }
595
+ async function readBlock(tagId, blockNumber) {
596
+ const uid = reverseUid(tagId);
597
+ const cmd = buildReadBlock(uid, blockNumber);
598
+ const resp = await transceive(cmd);
599
+ return parseReadResponse(resp);
600
+ }
601
+ async function readBlocks(tagId, startBlock, endBlock) {
602
+ const data = new Uint8Array();
603
+ let offset = 0;
604
+ for (let i = startBlock; i < endBlock; i++) {
605
+ const block = await readBlock(tagId, i);
606
+ data.set(block, offset);
607
+ offset += block.length;
373
608
  }
374
- };
609
+ return data;
610
+ }
611
+ async function writeBlock(tagId, blockNumber, data) {
612
+ const uid = reverseUid(tagId);
613
+ const cmd = buildWriteBlock(uid, blockNumber, data);
614
+ const resp = await transceive(cmd);
615
+ parseWriteResponse(resp);
616
+ }
617
+ async function writeBlocks(tagId, blockNumber, data) {
618
+ for (let i = 0; i < data.length; i++) {
619
+ const blockData = data[i];
620
+ if (blockData === void 0) {
621
+ throw new VError(`No data provided for block at index ${i}`);
622
+ }
623
+ await writeBlock(tagId, blockNumber + i, blockData);
624
+ }
625
+ }
626
+ async function getSystemInfo() {
627
+ const cmd = buildGetSystemInfo();
628
+ const resp = await transceive(cmd);
629
+ return parseSystemInfo(resp);
630
+ }
375
631
 
376
- // src/nfc/ndef/index.ts
377
- var ndef_exports = {};
378
- __export(ndef_exports, {
379
- operations: () => operations3,
380
- utils: () => utils3
381
- });
632
+ // src/nfc/v/internal/tech.ts
633
+ import { Platform as Platform3 } from "react-native";
634
+ import { NfcTech as NfcTech2 } from "react-native-nfc-manager";
635
+ var tech2 = Platform3.OS === "ios" ? [NfcTech2.Iso15693IOS] : NfcTech2.NfcV;
382
636
 
383
- // src/nfc/ndef/operations.ts
384
- import NfcManager5, {
385
- Ndef,
386
- NfcTech as NfcTech3
387
- } from "react-native-nfc-manager";
388
- var operations3 = {
389
- async writeNdef(records) {
390
- await nfcService.withTechnology([NfcTech3.Ndef, NfcTech3.NfcA], async () => {
391
- const bytes = Ndef.encodeMessage(records);
392
- await NfcManager5.ndefHandler.writeNdefMessage(bytes);
393
- });
394
- },
395
- writeTextNdef(text) {
396
- const record = Ndef.textRecord(text);
397
- return this.writeNdef([record]);
398
- },
399
- writeUriNdef(uri) {
400
- const record = Ndef.uriRecord(uri);
401
- return this.writeNdef([record]);
402
- }
637
+ // src/nfc/v/internal/index.ts
638
+ var nfcVTag = {
639
+ ...operations_exports5,
640
+ tech: tech2,
641
+ utils: utils_exports
403
642
  };
404
643
 
405
- // src/nfc/ndef/utils.ts
406
- var utils3 = {};
644
+ // src/nfc/v/operations.ts
645
+ var operations_exports6 = {};
646
+ __export(operations_exports6, {
647
+ getSystemInfo: () => getSystemInfo2,
648
+ readBlock: () => readBlock2,
649
+ readBlocks: () => readBlocks2,
650
+ writeBlock: () => writeBlock2,
651
+ writeBlocks: () => writeBlocks2
652
+ });
653
+ async function writeBlock2(blockNumber, data) {
654
+ await nfcService.withTechnology(nfcVTag.tech, async () => {
655
+ const tag = await nfcTag.getTag();
656
+ if (!(tag == null ? void 0 : tag.id)) throw new VError("No NFC-V tag id detected");
657
+ await nfcVTag.writeBlock(tag.id, blockNumber, data);
658
+ });
659
+ }
660
+ async function writeBlocks2(blockNumber, data) {
661
+ await nfcService.withTechnology(nfcVTag.tech, async () => {
662
+ const tag = await nfcTag.getTag();
663
+ if (!(tag == null ? void 0 : tag.id)) throw new VError("No NFC-V tag id detected");
664
+ nfcVTag.writeBlocks(tag.id, blockNumber, data);
665
+ });
666
+ }
667
+ async function readBlock2(blockNumber) {
668
+ return await nfcService.withTechnology(nfcVTag.tech, async () => {
669
+ const tag = await nfcTag.getTag();
670
+ if (!(tag == null ? void 0 : tag.id)) throw new VError("No NFC-V tag id detected");
671
+ return await nfcVTag.readBlock(tag.id, blockNumber);
672
+ });
673
+ }
674
+ async function readBlocks2(startBlock, endBlock) {
675
+ return await nfcService.withTechnology(nfcVTag.tech, async () => {
676
+ const tag = await nfcTag.getTag();
677
+ if (!(tag == null ? void 0 : tag.id)) throw new Error("No NFC-V tag id detected");
678
+ return await nfcVTag.readBlocks(tag.id, startBlock, endBlock);
679
+ });
680
+ }
681
+ async function getSystemInfo2() {
682
+ return await nfcService.withTechnology(nfcVTag.tech, nfcVTag.getSystemInfo);
683
+ }
407
684
 
408
685
  // src/nfc/namespace.ts
409
686
  var nfc = {
410
687
  service: nfcService,
411
- /** ISO15693 protocol helpers and high-level operations */
412
- v: {
413
- ...operations2,
414
- // NfcVOperations, nfcV
415
- utils: utils2
416
- },
417
- /** NFC-A / Type 2 helpers and operations */
418
- a: {
419
- ...operations,
420
- utils
421
- },
422
- /** NDEF read/write utilities and operations */
423
- ndef: {
424
- ...operations3,
425
- utils: utils3
426
- }
688
+ v: { ...operations_exports6 },
689
+ ndef: { ...operations_exports4, Builder },
690
+ tag: { ...operations_exports3 }
427
691
  };
428
692
 
429
693
  // src/react/nfc-provider.tsx
@@ -453,9 +717,7 @@ function useNfcContext() {
453
717
  import { useEffect as useEffect2 } from "react";
454
718
  function useNfc(onTag, options) {
455
719
  useEffect2(() => {
456
- const flags = options.flags;
457
720
  nfcService.startReader(
458
- flags,
459
721
  async (tag) => {
460
722
  if (!tag.id) return;
461
723
  onTag(tag.id);
@@ -472,8 +734,8 @@ function useNfc(onTag, options) {
472
734
  import { useCallback } from "react";
473
735
  function useNfcReader() {
474
736
  const start = useCallback(
475
- (flags, onTag, cooldownMs) => {
476
- nfcService.startReader(flags, onTag, { cooldownMs });
737
+ (onTag, cooldownMs) => {
738
+ nfcService.startReader(onTag, { cooldownMs });
477
739
  },
478
740
  []
479
741
  );
@@ -492,19 +754,19 @@ function useNfcState() {
492
754
  }
493
755
 
494
756
  // src/react/use-nfc-technology.ts
495
- import NfcManager6, {
496
- Ndef as Ndef2,
497
- NfcTech as NfcTech4
757
+ import NfcManager, {
758
+ Ndef as Ndef3,
759
+ NfcTech as NfcTech3
498
760
  } from "react-native-nfc-manager";
499
761
  function useNfcTechnology() {
500
762
  async function writeNdef(records) {
501
- return nfcService.withTechnology(NfcTech4.Ndef, async () => {
502
- const bytes = Ndef2.encodeMessage(records);
503
- await NfcManager6.ndefHandler.writeNdefMessage(bytes);
763
+ return nfcService.withTechnology(NfcTech3.Ndef, async () => {
764
+ const bytes = Ndef3.encodeMessage(records);
765
+ await NfcManager.ndefHandler.writeNdefMessage(bytes);
504
766
  });
505
767
  }
506
- async function runWithTech(tech, fn) {
507
- return nfcService.withTechnology(tech, fn);
768
+ async function runWithTech(tech3, fn) {
769
+ return nfcService.withTechnology(tech3, fn);
508
770
  }
509
771
  return {
510
772
  writeNdef,
@@ -514,10 +776,10 @@ function useNfcTechnology() {
514
776
  export {
515
777
  NfcProvider,
516
778
  nfc,
517
- a_exports as nfcA,
518
- ndef_exports as nfcNdef,
779
+ nfcNdefTag,
519
780
  nfcService,
520
- v_exports as nfcV,
781
+ nfcTag,
782
+ nfcVTag,
521
783
  useNfc,
522
784
  useNfcContext,
523
785
  useNfcReader,