@spencerls/react-native-nfc 1.0.4 → 1.0.6

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
@@ -27,27 +27,49 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
- // src/services/nfc/index.ts
30
+ // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- ndef: () => ndef_exports,
33
+ NfcProvider: () => NfcProvider,
34
34
  nfc: () => nfc,
35
35
  nfcA: () => a_exports,
36
+ nfcNdef: () => ndef_exports,
36
37
  nfcService: () => nfcService,
37
- nfcV: () => v_exports
38
+ nfcV: () => v_exports,
39
+ useNfc: () => useNfc,
40
+ useNfcContext: () => useNfcContext,
41
+ useNfcReader: () => useNfcReader,
42
+ useNfcState: () => useNfcState,
43
+ useNfcTechnology: () => useNfcTechnology
38
44
  });
39
45
  module.exports = __toCommonJS(index_exports);
40
46
 
41
- // src/services/nfc/service.ts
47
+ // src/nfc/a/index.ts
48
+ var a_exports = {};
49
+ __export(a_exports, {
50
+ operations: () => operations,
51
+ utils: () => utils
52
+ });
53
+
54
+ // src/nfc/a/operations.ts
55
+ var import_react_native_nfc_manager2 = __toESM(require("react-native-nfc-manager"));
56
+
57
+ // src/nfc/service.ts
42
58
  var import_react_native = require("react-native");
43
59
  var import_react_native_nfc_manager = __toESM(require("react-native-nfc-manager"));
44
60
  var NfcService = class {
61
+ // needed for iOS restart
45
62
  constructor() {
46
63
  this.state = { mode: "idle", tag: null };
47
64
  this.listeners = /* @__PURE__ */ new Set();
65
+ this.isProcessingTag = false;
66
+ this.currentCooldownMs = 1500;
67
+ this.lastUsedReaderFlags = null;
48
68
  import_react_native_nfc_manager.default.start();
49
69
  }
50
- // --- internal state mgmt ---
70
+ // -----------------------------
71
+ // Internal state management
72
+ // -----------------------------
51
73
  setState(partial) {
52
74
  this.state = { ...this.state, ...partial };
53
75
  for (const listener of this.listeners) listener(this.state);
@@ -62,17 +84,45 @@ var NfcService = class {
62
84
  this.listeners.delete(fn);
63
85
  };
64
86
  }
65
- // --- Reader lifecycle ---
66
- async startReader(readerModeFlags, onTag) {
87
+ // -----------------------------
88
+ // START READER
89
+ // -----------------------------
90
+ async startReader(readerModeFlags, onTag, options) {
91
+ var _a;
67
92
  if (this.state.mode !== "idle") {
68
93
  console.warn(`[NFC] Cannot start reader while ${this.state.mode}`);
69
94
  return;
70
95
  }
71
- this.setState({ mode: "starting" });
72
- import_react_native_nfc_manager.default.setEventListener(import_react_native_nfc_manager.NfcEvents.DiscoverTag, (tag) => {
73
- this.setState({ tag });
74
- onTag == null ? void 0 : onTag(tag);
75
- });
96
+ this.currentOnTag = onTag;
97
+ this.currentCooldownMs = (_a = options == null ? void 0 : options.cooldownMs) != null ? _a : 1500;
98
+ this.lastUsedReaderFlags = readerModeFlags;
99
+ this.isProcessingTag = false;
100
+ this.setState({ mode: "starting", tag: null });
101
+ import_react_native_nfc_manager.default.setEventListener(
102
+ import_react_native_nfc_manager.NfcEvents.DiscoverTag,
103
+ async (tag) => {
104
+ if (!tag) return;
105
+ if (this.isProcessingTag) return;
106
+ this.isProcessingTag = true;
107
+ this.setState({ tag, mode: "active" });
108
+ try {
109
+ if (this.currentOnTag) {
110
+ await this.currentOnTag(tag);
111
+ }
112
+ } catch (err) {
113
+ console.warn("[NFC] onTag handler error:", err);
114
+ } finally {
115
+ const cooldown = this.currentCooldownMs;
116
+ setTimeout(async () => {
117
+ this.isProcessingTag = false;
118
+ this.setState({ tag: null, mode: "active" });
119
+ if (import_react_native.Platform.OS === "ios") {
120
+ await this._restartIosReader();
121
+ }
122
+ }, cooldown);
123
+ }
124
+ }
125
+ );
76
126
  try {
77
127
  await import_react_native_nfc_manager.default.registerTagEvent({
78
128
  isReaderModeEnabled: true,
@@ -83,23 +133,53 @@ var NfcService = class {
83
133
  }
84
134
  } catch (err) {
85
135
  console.warn("[NFC] startReader error:", err);
86
- this.setState({ mode: "idle" });
136
+ this._resetReaderState();
87
137
  }
88
138
  }
139
+ // -----------------------------
140
+ // STOP READER
141
+ // -----------------------------
89
142
  async stopReader() {
90
143
  if (["idle", "stopping"].includes(this.state.mode)) return;
91
144
  this.setState({ mode: "stopping" });
92
145
  try {
93
146
  await import_react_native_nfc_manager.default.unregisterTagEvent();
94
- } catch {
147
+ } catch (err) {
148
+ console.warn("[NFC] unregisterTagEvent error:", err);
149
+ }
150
+ this._resetReaderState();
151
+ }
152
+ _resetReaderState() {
153
+ this.setState({ mode: "idle", tag: null });
154
+ this.currentOnTag = void 0;
155
+ this.isProcessingTag = false;
156
+ }
157
+ // -----------------------------
158
+ // iOS RESTART
159
+ // -----------------------------
160
+ async _restartIosReader() {
161
+ if (import_react_native.Platform.OS !== "ios") return;
162
+ if (this.lastUsedReaderFlags == null) return;
163
+ try {
164
+ await import_react_native_nfc_manager.default.unregisterTagEvent();
165
+ await import_react_native_nfc_manager.default.registerTagEvent({
166
+ isReaderModeEnabled: true,
167
+ readerModeFlags: this.lastUsedReaderFlags
168
+ });
169
+ this.setState({ mode: "active" });
170
+ } catch (err) {
171
+ console.warn("[NFC] iOS restart error:", err);
172
+ this._resetReaderState();
95
173
  }
96
- this.setState({ mode: "idle" });
97
174
  }
175
+ // -----------------------------
176
+ // Technology sessions (NDEF, NfcV, etc.)
177
+ // -----------------------------
98
178
  async withTechnology(tech, handler) {
99
179
  if (this.state.mode === "technology") {
100
- throw new Error(`[NFC] Technology is already in use!`);
180
+ throw new Error("[NFC] Technology is already in use!");
101
181
  }
102
- if (this.state.mode === "starting" || this.state.mode === "active" || this.state.mode === "stopping") {
182
+ if (["starting", "active", "stopping"].includes(this.state.mode)) {
103
183
  await this.stopReader();
104
184
  }
105
185
  if (this.state.mode !== "idle") {
@@ -107,15 +187,15 @@ var NfcService = class {
107
187
  `[NFC] Cannot start technology session in mode ${this.state.mode}`
108
188
  );
109
189
  }
110
- this.setState({ mode: "technology" });
190
+ this.setState({ mode: "technology", tag: null });
111
191
  try {
112
192
  await import_react_native_nfc_manager.default.requestTechnology(tech, {
113
193
  alertMessage: "Hold near NFC tag"
114
- // iOS
115
194
  });
116
195
  const result = await handler();
117
- if (import_react_native.Platform.OS === "ios")
196
+ if (import_react_native.Platform.OS === "ios") {
118
197
  await import_react_native_nfc_manager.default.setAlertMessageIOS("Success!");
198
+ }
119
199
  return result;
120
200
  } catch (err) {
121
201
  const message = typeof err === "string" ? err : (err == null ? void 0 : err.message) || "Unknown NFC error";
@@ -123,24 +203,15 @@ var NfcService = class {
123
203
  } finally {
124
204
  try {
125
205
  await import_react_native_nfc_manager.default.cancelTechnologyRequest();
126
- } catch (cancelErr) {
127
- console.warn("[NFC] cancelTechnologyRequest failed:", cancelErr);
206
+ } catch {
128
207
  }
129
- this.setState({ mode: "idle" });
208
+ this.setState({ mode: "idle", tag: null });
130
209
  }
131
210
  }
132
211
  };
133
212
  var nfcService = new NfcService();
134
213
 
135
- // src/services/nfc/a/index.ts
136
- var a_exports = {};
137
- __export(a_exports, {
138
- operations: () => operations,
139
- utils: () => utils
140
- });
141
-
142
- // src/services/nfc/a/operations.ts
143
- var import_react_native_nfc_manager2 = __toESM(require("react-native-nfc-manager"));
214
+ // src/nfc/a/operations.ts
144
215
  var operations = {
145
216
  async transceive(data) {
146
217
  return nfcService.withTechnology(import_react_native_nfc_manager2.NfcTech.NfcA, async () => {
@@ -149,56 +220,27 @@ var operations = {
149
220
  }
150
221
  };
151
222
 
152
- // src/services/nfc/a/utils.ts
223
+ // src/nfc/a/utils.ts
153
224
  var utils = {};
154
225
 
155
- // src/services/nfc/ndef/index.ts
156
- var ndef_exports = {};
157
- __export(ndef_exports, {
158
- operations: () => operations2,
159
- utils: () => utils2
160
- });
161
-
162
- // src/services/nfc/ndef/operations.ts
163
- var import_react_native_nfc_manager3 = __toESM(require("react-native-nfc-manager"));
164
- var operations2 = {
165
- async writeNdef(records) {
166
- await nfcService.withTechnology([import_react_native_nfc_manager3.NfcTech.Ndef, import_react_native_nfc_manager3.NfcTech.NfcA], async () => {
167
- const bytes = import_react_native_nfc_manager3.Ndef.encodeMessage(records);
168
- await import_react_native_nfc_manager3.default.ndefHandler.writeNdefMessage(bytes);
169
- });
170
- },
171
- writeTextNdef(text) {
172
- const record = import_react_native_nfc_manager3.Ndef.textRecord(text);
173
- return this.writeNdef([record]);
174
- },
175
- writeUriNdef(uri) {
176
- const record = import_react_native_nfc_manager3.Ndef.uriRecord(uri);
177
- return this.writeNdef([record]);
178
- }
179
- };
180
-
181
- // src/services/nfc/ndef/utils.ts
182
- var utils2 = {};
183
-
184
- // src/services/nfc/v/index.ts
226
+ // src/nfc/v/index.ts
185
227
  var v_exports = {};
186
228
  __export(v_exports, {
187
- operations: () => operations3,
188
- utils: () => utils3
229
+ operations: () => operations2,
230
+ utils: () => utils2
189
231
  });
190
232
 
191
- // src/services/nfc/v/operations.ts
192
- var import_react_native_nfc_manager6 = __toESM(require("react-native-nfc-manager"));
193
-
194
- // src/services/nfc/v/internal.ts
233
+ // src/nfc/v/operations.ts
195
234
  var import_react_native_nfc_manager5 = __toESM(require("react-native-nfc-manager"));
196
235
 
197
- // src/services/nfc/v/utils.ts
236
+ // src/nfc/v/internal.ts
237
+ var import_react_native_nfc_manager4 = __toESM(require("react-native-nfc-manager"));
238
+
239
+ // src/nfc/v/utils.ts
198
240
  var import_react_native2 = require("react-native");
199
- var import_react_native_nfc_manager4 = require("react-native-nfc-manager");
200
- var utils3 = {
201
- tech: import_react_native2.Platform.OS === "ios" ? [import_react_native_nfc_manager4.NfcTech.Iso15693IOS] : import_react_native_nfc_manager4.NfcTech.NfcV,
241
+ var import_react_native_nfc_manager3 = require("react-native-nfc-manager");
242
+ var utils2 = {
243
+ tech: import_react_native2.Platform.OS === "ios" ? [import_react_native_nfc_manager3.NfcTech.Iso15693IOS] : import_react_native_nfc_manager3.NfcTech.NfcV,
202
244
  Flags: {
203
245
  HIGH_DATA_RATE: 2,
204
246
  ADDRESSED: 32
@@ -223,7 +265,7 @@ var utils3 = {
223
265
  reverseUid(tagIdHex) {
224
266
  const bytes = [];
225
267
  for (let i = 0; i < tagIdHex.length; i += 2) {
226
- bytes.unshift(parseInt(tagIdHex.substring(i, i + 2), 16));
268
+ bytes.unshift(Number.parseInt(tagIdHex.substring(i, i + 2), 16));
227
269
  }
228
270
  return bytes;
229
271
  },
@@ -270,8 +312,12 @@ var utils3 = {
270
312
  if (!resp || resp.length === 0) {
271
313
  throw new Error("Empty NFC-V response");
272
314
  }
273
- if (resp[0] !== 0) {
274
- throw new Error(`Read failed. Status: 0x${resp[0].toString(16)}`);
315
+ const status = resp[0];
316
+ if (status === void 0) {
317
+ throw new Error("Invalid NFC-V response: missing status byte");
318
+ }
319
+ if (status !== 0) {
320
+ throw new Error(`Read failed. Status: 0x${status.toString(16)}`);
275
321
  }
276
322
  return new Uint8Array(resp.slice(1));
277
323
  },
@@ -283,8 +329,12 @@ var utils3 = {
283
329
  if (!resp || resp.length === 0) {
284
330
  throw new Error("Empty NFC-V response");
285
331
  }
286
- if (resp[0] !== 0) {
287
- throw new Error(`Write failed. Status: 0x${resp[0].toString(16)}`);
332
+ const status = resp[0];
333
+ if (status === void 0) {
334
+ throw new Error("Invalid NFC-V response: missing status byte");
335
+ }
336
+ if (status !== 0) {
337
+ throw new Error(`Write failed. Status: 0x${status.toString(16)}`);
288
338
  }
289
339
  },
290
340
  /**
@@ -293,10 +343,18 @@ var utils3 = {
293
343
  */
294
344
  parseSystemInfo(resp) {
295
345
  var _a;
296
- if (!resp || resp.length < 2 || resp[0] !== 0) {
346
+ if (!resp || resp.length < 2) {
347
+ throw new Error("Invalid System Info response");
348
+ }
349
+ const status = resp[0];
350
+ if (status === void 0 || status !== 0) {
297
351
  throw new Error("Invalid System Info response");
298
352
  }
299
- const infoFlags = resp[1] & 15;
353
+ const flagsByte = resp[1];
354
+ if (flagsByte === void 0) {
355
+ throw new Error("Invalid System Info response: missing flags byte");
356
+ }
357
+ const infoFlags = flagsByte & 15;
300
358
  let offset = 2;
301
359
  const result = {};
302
360
  if (resp.length >= offset + 8) {
@@ -311,8 +369,14 @@ var utils3 = {
311
369
  result.afi = resp[offset++];
312
370
  }
313
371
  if (infoFlags & 4 && resp.length >= offset + 2) {
314
- result.numberOfBlocks = resp[offset++] + 1;
315
- result.blockSize = resp[offset++] + 1;
372
+ const numBlocks = resp[offset++];
373
+ const blkSize = resp[offset++];
374
+ if (numBlocks !== void 0) {
375
+ result.numberOfBlocks = numBlocks + 1;
376
+ }
377
+ if (blkSize !== void 0) {
378
+ result.blockSize = blkSize + 1;
379
+ }
316
380
  }
317
381
  if (infoFlags & 8 && resp.length > offset) {
318
382
  result.icReference = resp[offset++];
@@ -332,31 +396,31 @@ var utils3 = {
332
396
  }
333
397
  };
334
398
 
335
- // src/services/nfc/v/internal.ts
399
+ // src/nfc/v/internal.ts
336
400
  async function readBlockRaw(tag, blockNumber) {
337
- const uid = utils3.reverseUid(tag.id);
338
- const cmd = utils3.buildReadBlock(uid, blockNumber);
339
- const resp = await import_react_native_nfc_manager5.default.transceive(cmd);
340
- return utils3.parseReadResponse(resp);
401
+ const uid = utils2.reverseUid(tag.id);
402
+ const cmd = utils2.buildReadBlock(uid, blockNumber);
403
+ const resp = await import_react_native_nfc_manager4.default.transceive(cmd);
404
+ return utils2.parseReadResponse(resp);
341
405
  }
342
406
  async function writeBlockRaw(tag, blockNumber, data) {
343
- const uid = utils3.reverseUid(tag.id);
344
- const cmd = utils3.buildWriteBlock(uid, blockNumber, data);
345
- const resp = await import_react_native_nfc_manager5.default.transceive(cmd);
346
- return utils3.parseWriteResponse(resp);
407
+ const uid = utils2.reverseUid(tag.id);
408
+ const cmd = utils2.buildWriteBlock(uid, blockNumber, data);
409
+ const resp = await import_react_native_nfc_manager4.default.transceive(cmd);
410
+ return utils2.parseWriteResponse(resp);
347
411
  }
348
412
  async function getSystemInfoRaw(tag) {
349
- const uid = utils3.reverseUid(tag.id);
350
- const cmd = utils3.buildGetSystemInfo(uid);
351
- const resp = await import_react_native_nfc_manager5.default.transceive(cmd);
352
- return utils3.parseSystemInfo(resp);
413
+ const uid = utils2.reverseUid(tag.id);
414
+ const cmd = utils2.buildGetSystemInfo(uid);
415
+ const resp = await import_react_native_nfc_manager4.default.transceive(cmd);
416
+ return utils2.parseSystemInfo(resp);
353
417
  }
354
418
 
355
- // src/services/nfc/v/operations.ts
356
- var operations3 = {
419
+ // src/nfc/v/operations.ts
420
+ var operations2 = {
357
421
  async withVTag(handler) {
358
- return nfcService.withTechnology(utils3.tech, async () => {
359
- const tag = await import_react_native_nfc_manager6.default.getTag();
422
+ return nfcService.withTechnology(utils2.tech, async () => {
423
+ const tag = await import_react_native_nfc_manager5.default.getTag();
360
424
  if (!(tag == null ? void 0 : tag.id)) throw new Error("No NFC-V tag detected");
361
425
  return handler(tag);
362
426
  });
@@ -372,14 +436,43 @@ var operations3 = {
372
436
  }
373
437
  };
374
438
 
375
- // src/services/nfc/namespace.ts
439
+ // src/nfc/ndef/index.ts
440
+ var ndef_exports = {};
441
+ __export(ndef_exports, {
442
+ operations: () => operations3,
443
+ utils: () => utils3
444
+ });
445
+
446
+ // src/nfc/ndef/operations.ts
447
+ var import_react_native_nfc_manager6 = __toESM(require("react-native-nfc-manager"));
448
+ var operations3 = {
449
+ async writeNdef(records) {
450
+ await nfcService.withTechnology([import_react_native_nfc_manager6.NfcTech.Ndef, import_react_native_nfc_manager6.NfcTech.NfcA], async () => {
451
+ const bytes = import_react_native_nfc_manager6.Ndef.encodeMessage(records);
452
+ await import_react_native_nfc_manager6.default.ndefHandler.writeNdefMessage(bytes);
453
+ });
454
+ },
455
+ writeTextNdef(text) {
456
+ const record = import_react_native_nfc_manager6.Ndef.textRecord(text);
457
+ return this.writeNdef([record]);
458
+ },
459
+ writeUriNdef(uri) {
460
+ const record = import_react_native_nfc_manager6.Ndef.uriRecord(uri);
461
+ return this.writeNdef([record]);
462
+ }
463
+ };
464
+
465
+ // src/nfc/ndef/utils.ts
466
+ var utils3 = {};
467
+
468
+ // src/nfc/namespace.ts
376
469
  var nfc = {
377
470
  service: nfcService,
378
471
  /** ISO15693 protocol helpers and high-level operations */
379
472
  v: {
380
- ...operations3,
473
+ ...operations2,
381
474
  // NfcVOperations, nfcV
382
- utils: utils3
475
+ utils: utils2
383
476
  },
384
477
  /** NFC-A / Type 2 helpers and operations */
385
478
  a: {
@@ -388,16 +481,100 @@ var nfc = {
388
481
  },
389
482
  /** NDEF read/write utilities and operations */
390
483
  ndef: {
391
- ...operations2,
392
- utils: utils2
484
+ ...operations3,
485
+ utils: utils3
393
486
  }
394
487
  };
488
+
489
+ // src/react/nfc-provider.tsx
490
+ var import_react = require("react");
491
+ var import_jsx_runtime = require("react/jsx-runtime");
492
+ var NfcContext = (0, import_react.createContext)(null);
493
+ function NfcProvider({ children }) {
494
+ const [state, setState] = (0, import_react.useState)(nfcService.getState());
495
+ (0, import_react.useEffect)(() => {
496
+ const unsubscribe = nfcService.subscribe(setState);
497
+ return unsubscribe;
498
+ }, []);
499
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NfcContext.Provider, { value: { state, service: nfcService }, children });
500
+ }
501
+ function useNfcContext() {
502
+ const ctx = (0, import_react.useContext)(NfcContext);
503
+ if (!ctx) throw new Error("useNfcContext must be inside <NfcProvider>");
504
+ return ctx;
505
+ }
506
+
507
+ // src/react/use-nfc.ts
508
+ var import_react2 = require("react");
509
+ function useNfc(onTag, options) {
510
+ (0, import_react2.useEffect)(() => {
511
+ const flags = options.flags;
512
+ nfcService.startReader(
513
+ flags,
514
+ async (tag) => {
515
+ if (!tag.id) return;
516
+ onTag(tag.id);
517
+ },
518
+ { cooldownMs: options == null ? void 0 : options.cooldownMs }
519
+ );
520
+ return () => {
521
+ nfcService.stopReader();
522
+ };
523
+ }, [onTag]);
524
+ }
525
+
526
+ // src/react/use-nfc-reader.ts
527
+ var import_react3 = require("react");
528
+ function useNfcReader() {
529
+ const start = (0, import_react3.useCallback)(
530
+ (flags, onTag, cooldownMs) => {
531
+ nfcService.startReader(flags, onTag, { cooldownMs });
532
+ },
533
+ []
534
+ );
535
+ const stop = (0, import_react3.useCallback)(() => {
536
+ nfcService.stopReader();
537
+ }, []);
538
+ return { start, stop };
539
+ }
540
+
541
+ // src/react/use-nfc-state.ts
542
+ var import_react4 = require("react");
543
+ function useNfcState() {
544
+ const [nfcState, setNfcState] = (0, import_react4.useState)(nfcService.getState());
545
+ (0, import_react4.useEffect)(() => nfcService.subscribe(setNfcState), []);
546
+ return nfcState;
547
+ }
548
+
549
+ // src/react/use-nfc-technology.ts
550
+ var import_react_native_nfc_manager7 = __toESM(require("react-native-nfc-manager"));
551
+ function useNfcTechnology() {
552
+ async function writeNdef(records) {
553
+ return nfcService.withTechnology(import_react_native_nfc_manager7.NfcTech.Ndef, async () => {
554
+ const bytes = import_react_native_nfc_manager7.Ndef.encodeMessage(records);
555
+ await import_react_native_nfc_manager7.default.ndefHandler.writeNdefMessage(bytes);
556
+ });
557
+ }
558
+ async function runWithTech(tech, fn) {
559
+ return nfcService.withTechnology(tech, fn);
560
+ }
561
+ return {
562
+ writeNdef,
563
+ runWithTech
564
+ };
565
+ }
395
566
  // Annotate the CommonJS export names for ESM import in node:
396
567
  0 && (module.exports = {
397
- ndef,
568
+ NfcProvider,
398
569
  nfc,
399
570
  nfcA,
571
+ nfcNdef,
400
572
  nfcService,
401
- nfcV
573
+ nfcV,
574
+ useNfc,
575
+ useNfcContext,
576
+ useNfcReader,
577
+ useNfcState,
578
+ useNfcTechnology
402
579
  });
403
580
  //# sourceMappingURL=index.js.map