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