@spencerls/react-native-nfc 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Spencer Smith
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # @spencer/nfc
2
+
3
+ A clean, easy, React-friendly NFC service built on `react-native-nfc-manager`.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @spencer/nfc
9
+ # or
10
+ yarn add @spencer/nfc
11
+ ```
12
+
13
+ ## Requires:
14
+
15
+ `react-native-nfc-manager`
16
+
17
+ React Native 0.74+ or Expo (Bare / Prebuild)
18
+
19
+ ## Usage
20
+
21
+ ```tsx
22
+ import { nfcService, useNfcState, NfcUtils } from "@spencer/nfc";
23
+
24
+ export default function Example() {
25
+ const { state, isWriting } = useNfcState();
26
+
27
+ useEffect(() => {
28
+ nfcService.startReader(
29
+ NfcAdapter.FLAG_READER_NFC_V | NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS,
30
+ async (tag) => {
31
+ console.log("Tag:", tag);
32
+ await nfcService.stopReader();
33
+ await nfcService.writeNdef([NfcUtils.textRecord("Hello NFC!")]);
34
+ }
35
+ );
36
+
37
+ return () => nfcService.stopReader();
38
+ }, []);
39
+
40
+ return <Text>NFC state: {state}</Text>;
41
+ }
42
+ ```
43
+
44
+ ## License
45
+
46
+ MIT © Spencer Smith
@@ -0,0 +1,133 @@
1
+ import * as react_native_nfc_manager from 'react-native-nfc-manager';
2
+ import { TagEvent, NdefRecord } from 'react-native-nfc-manager';
3
+
4
+ type NfcState = "idle" | "starting" | "active" | "stopping" | "writing";
5
+ type NfcListener = (state: NfcState) => void;
6
+ declare class NfcService {
7
+ private state;
8
+ private lastTag;
9
+ private listeners;
10
+ constructor();
11
+ private setState;
12
+ getState(): NfcState;
13
+ getLastTag(): TagEvent | null;
14
+ subscribe(fn: NfcListener): () => void;
15
+ startReader(readerModeFlags: number, onTag?: (tag: TagEvent) => void): Promise<void>;
16
+ stopReader(): Promise<void>;
17
+ writeNdef(records: NdefRecord[]): Promise<{
18
+ success: boolean;
19
+ error: undefined;
20
+ }>;
21
+ }
22
+ declare const nfcService: NfcService;
23
+
24
+ declare function decodeRecord(record: {
25
+ tnf: number;
26
+ type: number[] | string;
27
+ id?: number[];
28
+ payload: number[];
29
+ }): {
30
+ kind: string;
31
+ text: string;
32
+ lang: string;
33
+ uri?: undefined;
34
+ mimeType?: undefined;
35
+ data?: undefined;
36
+ type?: undefined;
37
+ tnf?: undefined;
38
+ payload?: undefined;
39
+ } | {
40
+ kind: string;
41
+ uri: string;
42
+ text?: undefined;
43
+ lang?: undefined;
44
+ mimeType?: undefined;
45
+ data?: undefined;
46
+ type?: undefined;
47
+ tnf?: undefined;
48
+ payload?: undefined;
49
+ } | {
50
+ kind: string;
51
+ mimeType: string;
52
+ data: any;
53
+ text?: undefined;
54
+ lang?: undefined;
55
+ uri?: undefined;
56
+ type?: undefined;
57
+ tnf?: undefined;
58
+ payload?: undefined;
59
+ } | {
60
+ kind: string;
61
+ mimeType: string;
62
+ data: Uint8Array<ArrayBufferLike>;
63
+ text: string | null;
64
+ lang?: undefined;
65
+ uri?: undefined;
66
+ type?: undefined;
67
+ tnf?: undefined;
68
+ payload?: undefined;
69
+ } | {
70
+ kind: string;
71
+ uri: string;
72
+ data: Uint8Array<ArrayBufferLike>;
73
+ text?: undefined;
74
+ lang?: undefined;
75
+ mimeType?: undefined;
76
+ type?: undefined;
77
+ tnf?: undefined;
78
+ payload?: undefined;
79
+ } | {
80
+ kind: string;
81
+ type: string;
82
+ data: Uint8Array<ArrayBufferLike>;
83
+ text?: undefined;
84
+ lang?: undefined;
85
+ uri?: undefined;
86
+ mimeType?: undefined;
87
+ tnf?: undefined;
88
+ payload?: undefined;
89
+ } | {
90
+ kind: string;
91
+ tnf: number;
92
+ type: string;
93
+ payload: Uint8Array<ArrayBufferLike>;
94
+ text?: undefined;
95
+ lang?: undefined;
96
+ uri?: undefined;
97
+ mimeType?: undefined;
98
+ data?: undefined;
99
+ };
100
+ declare function decodeJson(record: NdefRecord): any;
101
+ declare function encodeJson(obj: any): {
102
+ tnf: 2;
103
+ type: number[];
104
+ id: never[];
105
+ payload: Uint8Array<ArrayBuffer>;
106
+ };
107
+ declare function encodeMime(mimeType: string, data: Uint8Array): {
108
+ tnf: 2;
109
+ type: number[];
110
+ id: never[];
111
+ payload: Uint8Array<ArrayBufferLike>;
112
+ };
113
+ declare function willFit(tag: TagEvent, records: NdefRecord[]): boolean | null;
114
+ declare function spaceLeft(tag: TagEvent, records: NdefRecord[]): number | null;
115
+ declare const NfcUtils: {
116
+ Ndef: {
117
+ decodeRecord: typeof decodeRecord;
118
+ decodeJson: typeof decodeJson;
119
+ encodeText: (text: string, lang?: string) => NdefRecord;
120
+ encodeUri: (uri: string) => NdefRecord;
121
+ encodeJson: typeof encodeJson;
122
+ encodeMime: typeof encodeMime;
123
+ willFit: typeof willFit;
124
+ spaceLeft: typeof spaceLeft;
125
+ };
126
+ };
127
+
128
+ declare function useNfcState(): {
129
+ state: NfcState;
130
+ lastTag: react_native_nfc_manager.TagEvent | null;
131
+ };
132
+
133
+ export { type NfcListener, type NfcState, NfcUtils, nfcService, useNfcState };
@@ -0,0 +1,133 @@
1
+ import * as react_native_nfc_manager from 'react-native-nfc-manager';
2
+ import { TagEvent, NdefRecord } from 'react-native-nfc-manager';
3
+
4
+ type NfcState = "idle" | "starting" | "active" | "stopping" | "writing";
5
+ type NfcListener = (state: NfcState) => void;
6
+ declare class NfcService {
7
+ private state;
8
+ private lastTag;
9
+ private listeners;
10
+ constructor();
11
+ private setState;
12
+ getState(): NfcState;
13
+ getLastTag(): TagEvent | null;
14
+ subscribe(fn: NfcListener): () => void;
15
+ startReader(readerModeFlags: number, onTag?: (tag: TagEvent) => void): Promise<void>;
16
+ stopReader(): Promise<void>;
17
+ writeNdef(records: NdefRecord[]): Promise<{
18
+ success: boolean;
19
+ error: undefined;
20
+ }>;
21
+ }
22
+ declare const nfcService: NfcService;
23
+
24
+ declare function decodeRecord(record: {
25
+ tnf: number;
26
+ type: number[] | string;
27
+ id?: number[];
28
+ payload: number[];
29
+ }): {
30
+ kind: string;
31
+ text: string;
32
+ lang: string;
33
+ uri?: undefined;
34
+ mimeType?: undefined;
35
+ data?: undefined;
36
+ type?: undefined;
37
+ tnf?: undefined;
38
+ payload?: undefined;
39
+ } | {
40
+ kind: string;
41
+ uri: string;
42
+ text?: undefined;
43
+ lang?: undefined;
44
+ mimeType?: undefined;
45
+ data?: undefined;
46
+ type?: undefined;
47
+ tnf?: undefined;
48
+ payload?: undefined;
49
+ } | {
50
+ kind: string;
51
+ mimeType: string;
52
+ data: any;
53
+ text?: undefined;
54
+ lang?: undefined;
55
+ uri?: undefined;
56
+ type?: undefined;
57
+ tnf?: undefined;
58
+ payload?: undefined;
59
+ } | {
60
+ kind: string;
61
+ mimeType: string;
62
+ data: Uint8Array<ArrayBufferLike>;
63
+ text: string | null;
64
+ lang?: undefined;
65
+ uri?: undefined;
66
+ type?: undefined;
67
+ tnf?: undefined;
68
+ payload?: undefined;
69
+ } | {
70
+ kind: string;
71
+ uri: string;
72
+ data: Uint8Array<ArrayBufferLike>;
73
+ text?: undefined;
74
+ lang?: undefined;
75
+ mimeType?: undefined;
76
+ type?: undefined;
77
+ tnf?: undefined;
78
+ payload?: undefined;
79
+ } | {
80
+ kind: string;
81
+ type: string;
82
+ data: Uint8Array<ArrayBufferLike>;
83
+ text?: undefined;
84
+ lang?: undefined;
85
+ uri?: undefined;
86
+ mimeType?: undefined;
87
+ tnf?: undefined;
88
+ payload?: undefined;
89
+ } | {
90
+ kind: string;
91
+ tnf: number;
92
+ type: string;
93
+ payload: Uint8Array<ArrayBufferLike>;
94
+ text?: undefined;
95
+ lang?: undefined;
96
+ uri?: undefined;
97
+ mimeType?: undefined;
98
+ data?: undefined;
99
+ };
100
+ declare function decodeJson(record: NdefRecord): any;
101
+ declare function encodeJson(obj: any): {
102
+ tnf: 2;
103
+ type: number[];
104
+ id: never[];
105
+ payload: Uint8Array<ArrayBuffer>;
106
+ };
107
+ declare function encodeMime(mimeType: string, data: Uint8Array): {
108
+ tnf: 2;
109
+ type: number[];
110
+ id: never[];
111
+ payload: Uint8Array<ArrayBufferLike>;
112
+ };
113
+ declare function willFit(tag: TagEvent, records: NdefRecord[]): boolean | null;
114
+ declare function spaceLeft(tag: TagEvent, records: NdefRecord[]): number | null;
115
+ declare const NfcUtils: {
116
+ Ndef: {
117
+ decodeRecord: typeof decodeRecord;
118
+ decodeJson: typeof decodeJson;
119
+ encodeText: (text: string, lang?: string) => NdefRecord;
120
+ encodeUri: (uri: string) => NdefRecord;
121
+ encodeJson: typeof encodeJson;
122
+ encodeMime: typeof encodeMime;
123
+ willFit: typeof willFit;
124
+ spaceLeft: typeof spaceLeft;
125
+ };
126
+ };
127
+
128
+ declare function useNfcState(): {
129
+ state: NfcState;
130
+ lastTag: react_native_nfc_manager.TagEvent | null;
131
+ };
132
+
133
+ export { type NfcListener, type NfcState, NfcUtils, nfcService, useNfcState };
package/dist/index.js ADDED
@@ -0,0 +1,292 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/services/nfc/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ NfcUtils: () => NfcUtils,
34
+ nfcService: () => nfcService,
35
+ useNfcState: () => useNfcState
36
+ });
37
+ module.exports = __toCommonJS(index_exports);
38
+
39
+ // src/services/nfc/NfcService.ts
40
+ var import_react_native = require("react-native");
41
+ var import_react_native_nfc_manager = __toESM(require("react-native-nfc-manager"));
42
+ var NfcService = class {
43
+ constructor() {
44
+ this.state = "idle";
45
+ this.lastTag = null;
46
+ this.listeners = /* @__PURE__ */ new Set();
47
+ import_react_native_nfc_manager.default.start();
48
+ }
49
+ // --- internal state mgmt ---
50
+ setState(next) {
51
+ if (this.state !== next) {
52
+ this.state = next;
53
+ for (const listener of this.listeners) listener(next);
54
+ }
55
+ }
56
+ getState() {
57
+ return this.state;
58
+ }
59
+ getLastTag() {
60
+ return this.lastTag;
61
+ }
62
+ subscribe(fn) {
63
+ this.listeners.add(fn);
64
+ fn(this.state);
65
+ return () => {
66
+ this.listeners.delete(fn);
67
+ };
68
+ }
69
+ // --- Reader lifecycle ---
70
+ async startReader(readerModeFlags, onTag) {
71
+ if (this.state !== "idle") {
72
+ console.warn(`[NFC] Cannot start reader while ${this.state}`);
73
+ return;
74
+ }
75
+ this.setState("starting");
76
+ import_react_native_nfc_manager.default.setEventListener(import_react_native_nfc_manager.NfcEvents.DiscoverTag, (tag) => {
77
+ this.lastTag = tag;
78
+ onTag == null ? void 0 : onTag(tag);
79
+ });
80
+ try {
81
+ await import_react_native_nfc_manager.default.registerTagEvent({
82
+ isReaderModeEnabled: true,
83
+ readerModeFlags
84
+ });
85
+ if (this.state === "starting") {
86
+ this.setState("active");
87
+ }
88
+ } catch (err) {
89
+ console.warn("[NFC] startReader error:", err);
90
+ this.setState("idle");
91
+ }
92
+ }
93
+ async stopReader() {
94
+ if (["idle", "stopping"].includes(this.state)) return;
95
+ this.setState("stopping");
96
+ try {
97
+ await import_react_native_nfc_manager.default.unregisterTagEvent();
98
+ } catch {
99
+ }
100
+ this.setState("idle");
101
+ }
102
+ // --- Writer ---
103
+ async writeNdef(records) {
104
+ if (this.state !== "idle") {
105
+ throw new Error(`Cannot write while reader is ${this.state}`);
106
+ }
107
+ this.setState("writing");
108
+ let res = {
109
+ success: false,
110
+ error: void 0
111
+ };
112
+ try {
113
+ await import_react_native_nfc_manager.default.requestTechnology(import_react_native_nfc_manager.NfcTech.Ndef, {
114
+ alertMessage: "Hold near NFC tag to write"
115
+ });
116
+ const bytes = import_react_native_nfc_manager.Ndef.encodeMessage(records);
117
+ await import_react_native_nfc_manager.default.ndefHandler.writeNdefMessage(bytes);
118
+ if (import_react_native.Platform.OS === "ios")
119
+ import_react_native_nfc_manager.default.setAlertMessageIOS("Write successful");
120
+ } catch (err) {
121
+ console.warn("[NFC] writeNdef error:", err);
122
+ res.success = false;
123
+ res.error = err;
124
+ } finally {
125
+ try {
126
+ await import_react_native_nfc_manager.default.cancelTechnologyRequest();
127
+ } catch {
128
+ } finally {
129
+ this.setState("idle");
130
+ return res;
131
+ }
132
+ }
133
+ }
134
+ };
135
+ var nfcService = new NfcService();
136
+
137
+ // src/services/nfc/NfcUtils.ts
138
+ var import_react_native_nfc_manager2 = require("react-native-nfc-manager");
139
+ var toU8 = (v) => {
140
+ if (v instanceof Uint8Array) return v;
141
+ if (Array.isArray(v)) return Uint8Array.from(v);
142
+ return new Uint8Array(v);
143
+ };
144
+ var toAscii = (u8) => String.fromCharCode(...u8);
145
+ function decodeRecord(record) {
146
+ const { tnf } = record;
147
+ let typeStr;
148
+ if (typeof record.type === "string") {
149
+ typeStr = record.type;
150
+ } else {
151
+ typeStr = toAscii(toU8(record.type));
152
+ }
153
+ const payloadU8 = toU8(record.payload);
154
+ if (tnf === import_react_native_nfc_manager2.Ndef.TNF_WELL_KNOWN && typeStr === "T") {
155
+ const status = payloadU8[0];
156
+ const langLen = status & 63;
157
+ const lang = toAscii(payloadU8.subarray(1, 1 + langLen));
158
+ const textBytes = payloadU8.subarray(1 + langLen);
159
+ const text = new TextDecoder().decode(textBytes);
160
+ return { kind: "text", text, lang };
161
+ }
162
+ if (tnf === import_react_native_nfc_manager2.Ndef.TNF_WELL_KNOWN && typeStr === "U") {
163
+ const uri = import_react_native_nfc_manager2.Ndef.uri.decodePayload(payloadU8);
164
+ return { kind: "uri", uri };
165
+ }
166
+ if (tnf === import_react_native_nfc_manager2.Ndef.TNF_MIME_MEDIA) {
167
+ let tryDecodeAsText2 = function(u8) {
168
+ try {
169
+ return new TextDecoder().decode(u8);
170
+ } catch {
171
+ return null;
172
+ }
173
+ };
174
+ var tryDecodeAsText = tryDecodeAsText2;
175
+ if (typeStr === "application/json") {
176
+ return {
177
+ kind: "mime",
178
+ mimeType: typeStr,
179
+ data: JSON.parse(new TextDecoder().decode(payloadU8))
180
+ };
181
+ }
182
+ return {
183
+ kind: "mime",
184
+ mimeType: typeStr,
185
+ data: payloadU8,
186
+ text: typeStr.startsWith("text/") ? tryDecodeAsText2(payloadU8) : null
187
+ };
188
+ }
189
+ if (tnf === import_react_native_nfc_manager2.Ndef.TNF_ABSOLUTE_URI) {
190
+ return {
191
+ kind: "abs-uri",
192
+ uri: typeStr,
193
+ data: payloadU8
194
+ };
195
+ }
196
+ if (tnf === import_react_native_nfc_manager2.Ndef.TNF_EXTERNAL_TYPE) {
197
+ return {
198
+ kind: "external",
199
+ type: typeStr,
200
+ data: payloadU8
201
+ };
202
+ }
203
+ if (tnf === import_react_native_nfc_manager2.Ndef.TNF_UNKNOWN) {
204
+ return {
205
+ kind: "unknown",
206
+ type: typeStr,
207
+ data: payloadU8
208
+ };
209
+ }
210
+ return {
211
+ kind: "unknown",
212
+ tnf,
213
+ type: typeStr,
214
+ payload: payloadU8
215
+ };
216
+ }
217
+ function decodeJson(record) {
218
+ if (record.tnf !== import_react_native_nfc_manager2.Ndef.TNF_MIME_MEDIA) return null;
219
+ const typeStr = typeof record.type === "string" ? record.type : toAscii(toU8(record.type));
220
+ if (typeStr !== "application/json") return null;
221
+ const payloadU8 = toU8(record.payload);
222
+ const jsonText = new TextDecoder().decode(payloadU8);
223
+ try {
224
+ return JSON.parse(jsonText);
225
+ } catch (err) {
226
+ console.warn("Invalid JSON in NDEF:", err);
227
+ return null;
228
+ }
229
+ }
230
+ var encodeText = (text, lang = "en") => import_react_native_nfc_manager2.Ndef.textRecord(text, lang);
231
+ var encodeUri = (uri) => import_react_native_nfc_manager2.Ndef.uriRecord(uri);
232
+ function encodeJson(obj) {
233
+ const json = JSON.stringify(obj);
234
+ const payload = new TextEncoder().encode(json);
235
+ const typeArray = Array.from(new TextEncoder().encode("application/json"));
236
+ return {
237
+ tnf: import_react_native_nfc_manager2.Ndef.TNF_MIME_MEDIA,
238
+ type: typeArray,
239
+ // MUST be a number[] of ASCII bytes
240
+ id: [],
241
+ payload
242
+ };
243
+ }
244
+ function encodeMime(mimeType, data) {
245
+ const typeBytes = Array.from(new TextEncoder().encode(mimeType));
246
+ return {
247
+ tnf: import_react_native_nfc_manager2.Ndef.TNF_MIME_MEDIA,
248
+ type: typeBytes,
249
+ id: [],
250
+ payload: data
251
+ };
252
+ }
253
+ function willFit(tag, records) {
254
+ if (tag.maxSize === void 0) return null;
255
+ const totalSize = import_react_native_nfc_manager2.Ndef.encodeMessage(records).length;
256
+ return totalSize <= tag.maxSize;
257
+ }
258
+ function spaceLeft(tag, records) {
259
+ if (tag.maxSize === void 0) return null;
260
+ const totalSize = import_react_native_nfc_manager2.Ndef.encodeMessage(records).length;
261
+ return tag.maxSize - totalSize;
262
+ }
263
+ var NfcUtils = {
264
+ Ndef: {
265
+ decodeRecord,
266
+ decodeJson,
267
+ encodeText,
268
+ encodeUri,
269
+ encodeJson,
270
+ encodeMime,
271
+ willFit,
272
+ spaceLeft
273
+ }
274
+ };
275
+
276
+ // src/services/nfc/useNfcState.ts
277
+ var import_react = require("react");
278
+ function useNfcState() {
279
+ const [state, setState] = (0, import_react.useState)(nfcService.getState());
280
+ (0, import_react.useEffect)(() => nfcService.subscribe(setState), []);
281
+ return {
282
+ state,
283
+ lastTag: nfcService.getLastTag()
284
+ };
285
+ }
286
+ // Annotate the CommonJS export names for ESM import in node:
287
+ 0 && (module.exports = {
288
+ NfcUtils,
289
+ nfcService,
290
+ useNfcState
291
+ });
292
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/nfc/index.ts","../src/services/nfc/NfcService.ts","../src/services/nfc/NfcUtils.ts","../src/services/nfc/useNfcState.ts"],"sourcesContent":["export * from \"./NfcService\";\r\nexport * from \"./NfcUtils\";\r\nexport * from \"./useNfcState\";\r\n","// NfcService.ts\r\nimport { Platform } from \"react-native\";\r\nimport NfcManager, {\r\n Ndef,\r\n NdefRecord,\r\n NfcEvents,\r\n NfcTech,\r\n TagEvent,\r\n} from \"react-native-nfc-manager\";\r\n\r\nexport type NfcState = \"idle\" | \"starting\" | \"active\" | \"stopping\" | \"writing\";\r\n\r\nexport type NfcListener = (state: NfcState) => void;\r\n\r\nclass NfcService {\r\n private state: NfcState = \"idle\";\r\n private lastTag: TagEvent | null = null;\r\n private listeners = new Set<NfcListener>();\r\n\r\n constructor() {\r\n NfcManager.start();\r\n }\r\n\r\n // --- internal state mgmt ---\r\n private setState(next: NfcState) {\r\n if (this.state !== next) {\r\n this.state = next;\r\n for (const listener of this.listeners) listener(next);\r\n }\r\n }\r\n\r\n getState() {\r\n return this.state;\r\n }\r\n\r\n getLastTag() {\r\n return this.lastTag;\r\n }\r\n\r\n subscribe(fn: NfcListener) {\r\n this.listeners.add(fn);\r\n fn(this.state); // emit current state immediately\r\n return () => {\r\n this.listeners.delete(fn);\r\n };\r\n }\r\n\r\n // --- Reader lifecycle ---\r\n async startReader(readerModeFlags: number, onTag?: (tag: TagEvent) => void) {\r\n if (this.state !== \"idle\") {\r\n console.warn(`[NFC] Cannot start reader while ${this.state}`);\r\n return;\r\n }\r\n\r\n this.setState(\"starting\");\r\n\r\n NfcManager.setEventListener(NfcEvents.DiscoverTag, (tag: TagEvent) => {\r\n this.lastTag = tag;\r\n onTag?.(tag);\r\n });\r\n\r\n try {\r\n await NfcManager.registerTagEvent({\r\n isReaderModeEnabled: true,\r\n readerModeFlags,\r\n });\r\n if ((this.state as NfcState) === \"starting\") {\r\n this.setState(\"active\");\r\n }\r\n } catch (err) {\r\n console.warn(\"[NFC] startReader error:\", err);\r\n this.setState(\"idle\");\r\n }\r\n }\r\n\r\n async stopReader() {\r\n if ([\"idle\", \"stopping\"].includes(this.state)) return;\r\n this.setState(\"stopping\");\r\n try {\r\n await NfcManager.unregisterTagEvent();\r\n } catch {}\r\n this.setState(\"idle\");\r\n }\r\n\r\n // --- Writer ---\r\n async writeNdef(records: NdefRecord[]) {\r\n if (this.state !== \"idle\") {\r\n throw new Error(`Cannot write while reader is ${this.state}`);\r\n }\r\n\r\n this.setState(\"writing\");\r\n\r\n let res = {\r\n success: false,\r\n error: undefined,\r\n };\r\n\r\n try {\r\n await NfcManager.requestTechnology(NfcTech.Ndef, {\r\n alertMessage: \"Hold near NFC tag to write\",\r\n });\r\n const bytes = Ndef.encodeMessage(records);\r\n await NfcManager.ndefHandler.writeNdefMessage(bytes);\r\n if (Platform.OS === \"ios\")\r\n NfcManager.setAlertMessageIOS(\"Write successful\");\r\n } catch (err: any) {\r\n console.warn(\"[NFC] writeNdef error:\", err);\r\n\r\n res.success = false;\r\n res.error = err;\r\n } finally {\r\n try {\r\n await NfcManager.cancelTechnologyRequest();\r\n } catch {\r\n } finally {\r\n this.setState(\"idle\");\r\n return res;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// Export one stable instance\r\nexport const nfcService = new NfcService();\r\n","import { Ndef, NdefRecord, TagEvent } from \"react-native-nfc-manager\";\r\n\r\nconst toU8 = (v: number[] | Uint8Array | ArrayBuffer): Uint8Array => {\r\n if (v instanceof Uint8Array) return v;\r\n if (Array.isArray(v)) return Uint8Array.from(v);\r\n return new Uint8Array(v);\r\n};\r\n\r\nconst toAscii = (u8: Uint8Array): string => String.fromCharCode(...u8);\r\n\r\nfunction decodeRecord(record: {\r\n tnf: number;\r\n type: number[] | string;\r\n id?: number[];\r\n payload: number[];\r\n}) {\r\n const { tnf } = record;\r\n\r\n // --- TYPE STRING -----------------------------------------------------\r\n let typeStr: string;\r\n if (typeof record.type === \"string\") {\r\n // iOS\r\n typeStr = record.type;\r\n } else {\r\n // Android\r\n typeStr = toAscii(toU8(record.type));\r\n }\r\n\r\n // --- PAYLOAD ---------------------------------------------------------\r\n const payloadU8 = toU8(record.payload);\r\n\r\n // ✅ TEXT RECORD\r\n if (tnf === Ndef.TNF_WELL_KNOWN && typeStr === \"T\") {\r\n const status = payloadU8[0];\r\n const langLen = status & 0x3f;\r\n const lang = toAscii(payloadU8.subarray(1, 1 + langLen));\r\n const textBytes = payloadU8.subarray(1 + langLen);\r\n const text = new TextDecoder().decode(textBytes);\r\n return { kind: \"text\", text, lang };\r\n }\r\n\r\n // ✅ URI RECORD\r\n if (tnf === Ndef.TNF_WELL_KNOWN && typeStr === \"U\") {\r\n const uri = Ndef.uri.decodePayload(payloadU8);\r\n return { kind: \"uri\", uri };\r\n }\r\n\r\n // ✅ MIME RECORD\r\n if (tnf === Ndef.TNF_MIME_MEDIA) {\r\n if (typeStr === \"application/json\") {\r\n return {\r\n kind: \"mime\",\r\n mimeType: typeStr,\r\n data: JSON.parse(new TextDecoder().decode(payloadU8)),\r\n };\r\n }\r\n\r\n function tryDecodeAsText(u8: Uint8Array): string | null {\r\n try {\r\n return new TextDecoder().decode(u8);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n return {\r\n kind: \"mime\",\r\n mimeType: typeStr,\r\n data: payloadU8,\r\n text: typeStr.startsWith(\"text/\") ? tryDecodeAsText(payloadU8) : null,\r\n };\r\n }\r\n\r\n // ✅ ABSOLUTE URI RECORD\r\n if (tnf === Ndef.TNF_ABSOLUTE_URI) {\r\n return {\r\n kind: \"abs-uri\",\r\n uri: typeStr,\r\n data: payloadU8,\r\n };\r\n }\r\n\r\n // ✅ EXTERNAL RECORD\r\n if (tnf === Ndef.TNF_EXTERNAL_TYPE) {\r\n return {\r\n kind: \"external\",\r\n type: typeStr,\r\n data: payloadU8,\r\n };\r\n }\r\n\r\n // ✅ UNKNOWN RECORD\r\n if (tnf === Ndef.TNF_UNKNOWN) {\r\n return {\r\n kind: \"unknown\",\r\n type: typeStr,\r\n data: payloadU8,\r\n };\r\n }\r\n\r\n // ✅ FALLBACK\r\n return {\r\n kind: \"unknown\",\r\n tnf,\r\n type: typeStr,\r\n payload: payloadU8,\r\n };\r\n}\r\n\r\nfunction decodeJson(record: NdefRecord) {\r\n if (record.tnf !== Ndef.TNF_MIME_MEDIA) return null;\r\n\r\n // Convert type to string\r\n const typeStr =\r\n typeof record.type === \"string\" ? record.type : toAscii(toU8(record.type));\r\n\r\n if (typeStr !== \"application/json\") return null;\r\n\r\n const payloadU8 = toU8(record.payload);\r\n const jsonText = new TextDecoder().decode(payloadU8);\r\n\r\n try {\r\n return JSON.parse(jsonText);\r\n } catch (err) {\r\n console.warn(\"Invalid JSON in NDEF:\", err);\r\n return null;\r\n }\r\n}\r\n\r\nconst encodeText = (text: string, lang = \"en\") => Ndef.textRecord(text, lang);\r\n\r\nconst encodeUri = (uri: string) => Ndef.uriRecord(uri);\r\n\r\nfunction encodeJson(obj: any) {\r\n const json = JSON.stringify(obj);\r\n const payload = new TextEncoder().encode(json); // Uint8Array\r\n const typeArray = Array.from(new TextEncoder().encode(\"application/json\"));\r\n\r\n return {\r\n tnf: Ndef.TNF_MIME_MEDIA,\r\n type: typeArray, // MUST be a number[] of ASCII bytes\r\n id: [],\r\n payload,\r\n };\r\n}\r\n\r\nfunction encodeMime(mimeType: string, data: Uint8Array) {\r\n const typeBytes = Array.from(new TextEncoder().encode(mimeType));\r\n\r\n return {\r\n tnf: Ndef.TNF_MIME_MEDIA,\r\n type: typeBytes,\r\n id: [],\r\n payload: data,\r\n };\r\n}\r\n\r\n// Android only\r\nfunction willFit(tag: TagEvent, records: NdefRecord[]) {\r\n if (tag.maxSize === undefined) return null;\r\n\r\n const totalSize = Ndef.encodeMessage(records).length;\r\n return totalSize <= tag.maxSize;\r\n}\r\n\r\n// Android only\r\nfunction spaceLeft(tag: TagEvent, records: NdefRecord[]) {\r\n if (tag.maxSize === undefined) return null;\r\n\r\n const totalSize = Ndef.encodeMessage(records).length;\r\n return tag.maxSize - totalSize;\r\n}\r\n\r\nexport const NfcUtils = {\r\n Ndef: {\r\n decodeRecord,\r\n decodeJson,\r\n encodeText,\r\n encodeUri,\r\n encodeJson,\r\n encodeMime,\r\n willFit,\r\n spaceLeft,\r\n },\r\n};\r\n","import { useEffect, useState } from \"react\";\r\nimport { nfcService, NfcState } from \"./NfcService\";\r\n\r\nexport function useNfcState() {\r\n const [state, setState] = useState<NfcState>(nfcService.getState());\r\n\r\n useEffect(() => nfcService.subscribe(setState), []);\r\n\r\n return {\r\n state,\r\n lastTag: nfcService.getLastTag(),\r\n };\r\n}\r\n"],"mappings":"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","names":["NfcManager","import_react_native_nfc_manager","tryDecodeAsText"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,257 @@
1
+ // src/services/nfc/NfcService.ts
2
+ import { Platform } from "react-native";
3
+ import NfcManager, {
4
+ Ndef,
5
+ NfcEvents,
6
+ NfcTech
7
+ } from "react-native-nfc-manager";
8
+ var NfcService = class {
9
+ constructor() {
10
+ this.state = "idle";
11
+ this.lastTag = null;
12
+ this.listeners = /* @__PURE__ */ new Set();
13
+ NfcManager.start();
14
+ }
15
+ // --- internal state mgmt ---
16
+ setState(next) {
17
+ if (this.state !== next) {
18
+ this.state = next;
19
+ for (const listener of this.listeners) listener(next);
20
+ }
21
+ }
22
+ getState() {
23
+ return this.state;
24
+ }
25
+ getLastTag() {
26
+ return this.lastTag;
27
+ }
28
+ subscribe(fn) {
29
+ this.listeners.add(fn);
30
+ fn(this.state);
31
+ return () => {
32
+ this.listeners.delete(fn);
33
+ };
34
+ }
35
+ // --- Reader lifecycle ---
36
+ async startReader(readerModeFlags, onTag) {
37
+ if (this.state !== "idle") {
38
+ console.warn(`[NFC] Cannot start reader while ${this.state}`);
39
+ return;
40
+ }
41
+ this.setState("starting");
42
+ NfcManager.setEventListener(NfcEvents.DiscoverTag, (tag) => {
43
+ this.lastTag = tag;
44
+ onTag == null ? void 0 : onTag(tag);
45
+ });
46
+ try {
47
+ await NfcManager.registerTagEvent({
48
+ isReaderModeEnabled: true,
49
+ readerModeFlags
50
+ });
51
+ if (this.state === "starting") {
52
+ this.setState("active");
53
+ }
54
+ } catch (err) {
55
+ console.warn("[NFC] startReader error:", err);
56
+ this.setState("idle");
57
+ }
58
+ }
59
+ async stopReader() {
60
+ if (["idle", "stopping"].includes(this.state)) return;
61
+ this.setState("stopping");
62
+ try {
63
+ await NfcManager.unregisterTagEvent();
64
+ } catch {
65
+ }
66
+ this.setState("idle");
67
+ }
68
+ // --- Writer ---
69
+ async writeNdef(records) {
70
+ if (this.state !== "idle") {
71
+ throw new Error(`Cannot write while reader is ${this.state}`);
72
+ }
73
+ this.setState("writing");
74
+ let res = {
75
+ success: false,
76
+ error: void 0
77
+ };
78
+ try {
79
+ await NfcManager.requestTechnology(NfcTech.Ndef, {
80
+ alertMessage: "Hold near NFC tag to write"
81
+ });
82
+ const bytes = Ndef.encodeMessage(records);
83
+ await NfcManager.ndefHandler.writeNdefMessage(bytes);
84
+ if (Platform.OS === "ios")
85
+ NfcManager.setAlertMessageIOS("Write successful");
86
+ } catch (err) {
87
+ console.warn("[NFC] writeNdef error:", err);
88
+ res.success = false;
89
+ res.error = err;
90
+ } finally {
91
+ try {
92
+ await NfcManager.cancelTechnologyRequest();
93
+ } catch {
94
+ } finally {
95
+ this.setState("idle");
96
+ return res;
97
+ }
98
+ }
99
+ }
100
+ };
101
+ var nfcService = new NfcService();
102
+
103
+ // src/services/nfc/NfcUtils.ts
104
+ import { Ndef as Ndef2 } from "react-native-nfc-manager";
105
+ var toU8 = (v) => {
106
+ if (v instanceof Uint8Array) return v;
107
+ if (Array.isArray(v)) return Uint8Array.from(v);
108
+ return new Uint8Array(v);
109
+ };
110
+ var toAscii = (u8) => String.fromCharCode(...u8);
111
+ function decodeRecord(record) {
112
+ const { tnf } = record;
113
+ let typeStr;
114
+ if (typeof record.type === "string") {
115
+ typeStr = record.type;
116
+ } else {
117
+ typeStr = toAscii(toU8(record.type));
118
+ }
119
+ const payloadU8 = toU8(record.payload);
120
+ if (tnf === Ndef2.TNF_WELL_KNOWN && typeStr === "T") {
121
+ const status = payloadU8[0];
122
+ const langLen = status & 63;
123
+ const lang = toAscii(payloadU8.subarray(1, 1 + langLen));
124
+ const textBytes = payloadU8.subarray(1 + langLen);
125
+ const text = new TextDecoder().decode(textBytes);
126
+ return { kind: "text", text, lang };
127
+ }
128
+ if (tnf === Ndef2.TNF_WELL_KNOWN && typeStr === "U") {
129
+ const uri = Ndef2.uri.decodePayload(payloadU8);
130
+ return { kind: "uri", uri };
131
+ }
132
+ if (tnf === Ndef2.TNF_MIME_MEDIA) {
133
+ let tryDecodeAsText2 = function(u8) {
134
+ try {
135
+ return new TextDecoder().decode(u8);
136
+ } catch {
137
+ return null;
138
+ }
139
+ };
140
+ var tryDecodeAsText = tryDecodeAsText2;
141
+ if (typeStr === "application/json") {
142
+ return {
143
+ kind: "mime",
144
+ mimeType: typeStr,
145
+ data: JSON.parse(new TextDecoder().decode(payloadU8))
146
+ };
147
+ }
148
+ return {
149
+ kind: "mime",
150
+ mimeType: typeStr,
151
+ data: payloadU8,
152
+ text: typeStr.startsWith("text/") ? tryDecodeAsText2(payloadU8) : null
153
+ };
154
+ }
155
+ if (tnf === Ndef2.TNF_ABSOLUTE_URI) {
156
+ return {
157
+ kind: "abs-uri",
158
+ uri: typeStr,
159
+ data: payloadU8
160
+ };
161
+ }
162
+ if (tnf === Ndef2.TNF_EXTERNAL_TYPE) {
163
+ return {
164
+ kind: "external",
165
+ type: typeStr,
166
+ data: payloadU8
167
+ };
168
+ }
169
+ if (tnf === Ndef2.TNF_UNKNOWN) {
170
+ return {
171
+ kind: "unknown",
172
+ type: typeStr,
173
+ data: payloadU8
174
+ };
175
+ }
176
+ return {
177
+ kind: "unknown",
178
+ tnf,
179
+ type: typeStr,
180
+ payload: payloadU8
181
+ };
182
+ }
183
+ function decodeJson(record) {
184
+ if (record.tnf !== Ndef2.TNF_MIME_MEDIA) return null;
185
+ const typeStr = typeof record.type === "string" ? record.type : toAscii(toU8(record.type));
186
+ if (typeStr !== "application/json") return null;
187
+ const payloadU8 = toU8(record.payload);
188
+ const jsonText = new TextDecoder().decode(payloadU8);
189
+ try {
190
+ return JSON.parse(jsonText);
191
+ } catch (err) {
192
+ console.warn("Invalid JSON in NDEF:", err);
193
+ return null;
194
+ }
195
+ }
196
+ var encodeText = (text, lang = "en") => Ndef2.textRecord(text, lang);
197
+ var encodeUri = (uri) => Ndef2.uriRecord(uri);
198
+ function encodeJson(obj) {
199
+ const json = JSON.stringify(obj);
200
+ const payload = new TextEncoder().encode(json);
201
+ const typeArray = Array.from(new TextEncoder().encode("application/json"));
202
+ return {
203
+ tnf: Ndef2.TNF_MIME_MEDIA,
204
+ type: typeArray,
205
+ // MUST be a number[] of ASCII bytes
206
+ id: [],
207
+ payload
208
+ };
209
+ }
210
+ function encodeMime(mimeType, data) {
211
+ const typeBytes = Array.from(new TextEncoder().encode(mimeType));
212
+ return {
213
+ tnf: Ndef2.TNF_MIME_MEDIA,
214
+ type: typeBytes,
215
+ id: [],
216
+ payload: data
217
+ };
218
+ }
219
+ function willFit(tag, records) {
220
+ if (tag.maxSize === void 0) return null;
221
+ const totalSize = Ndef2.encodeMessage(records).length;
222
+ return totalSize <= tag.maxSize;
223
+ }
224
+ function spaceLeft(tag, records) {
225
+ if (tag.maxSize === void 0) return null;
226
+ const totalSize = Ndef2.encodeMessage(records).length;
227
+ return tag.maxSize - totalSize;
228
+ }
229
+ var NfcUtils = {
230
+ Ndef: {
231
+ decodeRecord,
232
+ decodeJson,
233
+ encodeText,
234
+ encodeUri,
235
+ encodeJson,
236
+ encodeMime,
237
+ willFit,
238
+ spaceLeft
239
+ }
240
+ };
241
+
242
+ // src/services/nfc/useNfcState.ts
243
+ import { useEffect, useState } from "react";
244
+ function useNfcState() {
245
+ const [state, setState] = useState(nfcService.getState());
246
+ useEffect(() => nfcService.subscribe(setState), []);
247
+ return {
248
+ state,
249
+ lastTag: nfcService.getLastTag()
250
+ };
251
+ }
252
+ export {
253
+ NfcUtils,
254
+ nfcService,
255
+ useNfcState
256
+ };
257
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/nfc/NfcService.ts","../src/services/nfc/NfcUtils.ts","../src/services/nfc/useNfcState.ts"],"sourcesContent":["// NfcService.ts\r\nimport { Platform } from \"react-native\";\r\nimport NfcManager, {\r\n Ndef,\r\n NdefRecord,\r\n NfcEvents,\r\n NfcTech,\r\n TagEvent,\r\n} from \"react-native-nfc-manager\";\r\n\r\nexport type NfcState = \"idle\" | \"starting\" | \"active\" | \"stopping\" | \"writing\";\r\n\r\nexport type NfcListener = (state: NfcState) => void;\r\n\r\nclass NfcService {\r\n private state: NfcState = \"idle\";\r\n private lastTag: TagEvent | null = null;\r\n private listeners = new Set<NfcListener>();\r\n\r\n constructor() {\r\n NfcManager.start();\r\n }\r\n\r\n // --- internal state mgmt ---\r\n private setState(next: NfcState) {\r\n if (this.state !== next) {\r\n this.state = next;\r\n for (const listener of this.listeners) listener(next);\r\n }\r\n }\r\n\r\n getState() {\r\n return this.state;\r\n }\r\n\r\n getLastTag() {\r\n return this.lastTag;\r\n }\r\n\r\n subscribe(fn: NfcListener) {\r\n this.listeners.add(fn);\r\n fn(this.state); // emit current state immediately\r\n return () => {\r\n this.listeners.delete(fn);\r\n };\r\n }\r\n\r\n // --- Reader lifecycle ---\r\n async startReader(readerModeFlags: number, onTag?: (tag: TagEvent) => void) {\r\n if (this.state !== \"idle\") {\r\n console.warn(`[NFC] Cannot start reader while ${this.state}`);\r\n return;\r\n }\r\n\r\n this.setState(\"starting\");\r\n\r\n NfcManager.setEventListener(NfcEvents.DiscoverTag, (tag: TagEvent) => {\r\n this.lastTag = tag;\r\n onTag?.(tag);\r\n });\r\n\r\n try {\r\n await NfcManager.registerTagEvent({\r\n isReaderModeEnabled: true,\r\n readerModeFlags,\r\n });\r\n if ((this.state as NfcState) === \"starting\") {\r\n this.setState(\"active\");\r\n }\r\n } catch (err) {\r\n console.warn(\"[NFC] startReader error:\", err);\r\n this.setState(\"idle\");\r\n }\r\n }\r\n\r\n async stopReader() {\r\n if ([\"idle\", \"stopping\"].includes(this.state)) return;\r\n this.setState(\"stopping\");\r\n try {\r\n await NfcManager.unregisterTagEvent();\r\n } catch {}\r\n this.setState(\"idle\");\r\n }\r\n\r\n // --- Writer ---\r\n async writeNdef(records: NdefRecord[]) {\r\n if (this.state !== \"idle\") {\r\n throw new Error(`Cannot write while reader is ${this.state}`);\r\n }\r\n\r\n this.setState(\"writing\");\r\n\r\n let res = {\r\n success: false,\r\n error: undefined,\r\n };\r\n\r\n try {\r\n await NfcManager.requestTechnology(NfcTech.Ndef, {\r\n alertMessage: \"Hold near NFC tag to write\",\r\n });\r\n const bytes = Ndef.encodeMessage(records);\r\n await NfcManager.ndefHandler.writeNdefMessage(bytes);\r\n if (Platform.OS === \"ios\")\r\n NfcManager.setAlertMessageIOS(\"Write successful\");\r\n } catch (err: any) {\r\n console.warn(\"[NFC] writeNdef error:\", err);\r\n\r\n res.success = false;\r\n res.error = err;\r\n } finally {\r\n try {\r\n await NfcManager.cancelTechnologyRequest();\r\n } catch {\r\n } finally {\r\n this.setState(\"idle\");\r\n return res;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// Export one stable instance\r\nexport const nfcService = new NfcService();\r\n","import { Ndef, NdefRecord, TagEvent } from \"react-native-nfc-manager\";\r\n\r\nconst toU8 = (v: number[] | Uint8Array | ArrayBuffer): Uint8Array => {\r\n if (v instanceof Uint8Array) return v;\r\n if (Array.isArray(v)) return Uint8Array.from(v);\r\n return new Uint8Array(v);\r\n};\r\n\r\nconst toAscii = (u8: Uint8Array): string => String.fromCharCode(...u8);\r\n\r\nfunction decodeRecord(record: {\r\n tnf: number;\r\n type: number[] | string;\r\n id?: number[];\r\n payload: number[];\r\n}) {\r\n const { tnf } = record;\r\n\r\n // --- TYPE STRING -----------------------------------------------------\r\n let typeStr: string;\r\n if (typeof record.type === \"string\") {\r\n // iOS\r\n typeStr = record.type;\r\n } else {\r\n // Android\r\n typeStr = toAscii(toU8(record.type));\r\n }\r\n\r\n // --- PAYLOAD ---------------------------------------------------------\r\n const payloadU8 = toU8(record.payload);\r\n\r\n // ✅ TEXT RECORD\r\n if (tnf === Ndef.TNF_WELL_KNOWN && typeStr === \"T\") {\r\n const status = payloadU8[0];\r\n const langLen = status & 0x3f;\r\n const lang = toAscii(payloadU8.subarray(1, 1 + langLen));\r\n const textBytes = payloadU8.subarray(1 + langLen);\r\n const text = new TextDecoder().decode(textBytes);\r\n return { kind: \"text\", text, lang };\r\n }\r\n\r\n // ✅ URI RECORD\r\n if (tnf === Ndef.TNF_WELL_KNOWN && typeStr === \"U\") {\r\n const uri = Ndef.uri.decodePayload(payloadU8);\r\n return { kind: \"uri\", uri };\r\n }\r\n\r\n // ✅ MIME RECORD\r\n if (tnf === Ndef.TNF_MIME_MEDIA) {\r\n if (typeStr === \"application/json\") {\r\n return {\r\n kind: \"mime\",\r\n mimeType: typeStr,\r\n data: JSON.parse(new TextDecoder().decode(payloadU8)),\r\n };\r\n }\r\n\r\n function tryDecodeAsText(u8: Uint8Array): string | null {\r\n try {\r\n return new TextDecoder().decode(u8);\r\n } catch {\r\n return null;\r\n }\r\n }\r\n\r\n return {\r\n kind: \"mime\",\r\n mimeType: typeStr,\r\n data: payloadU8,\r\n text: typeStr.startsWith(\"text/\") ? tryDecodeAsText(payloadU8) : null,\r\n };\r\n }\r\n\r\n // ✅ ABSOLUTE URI RECORD\r\n if (tnf === Ndef.TNF_ABSOLUTE_URI) {\r\n return {\r\n kind: \"abs-uri\",\r\n uri: typeStr,\r\n data: payloadU8,\r\n };\r\n }\r\n\r\n // ✅ EXTERNAL RECORD\r\n if (tnf === Ndef.TNF_EXTERNAL_TYPE) {\r\n return {\r\n kind: \"external\",\r\n type: typeStr,\r\n data: payloadU8,\r\n };\r\n }\r\n\r\n // ✅ UNKNOWN RECORD\r\n if (tnf === Ndef.TNF_UNKNOWN) {\r\n return {\r\n kind: \"unknown\",\r\n type: typeStr,\r\n data: payloadU8,\r\n };\r\n }\r\n\r\n // ✅ FALLBACK\r\n return {\r\n kind: \"unknown\",\r\n tnf,\r\n type: typeStr,\r\n payload: payloadU8,\r\n };\r\n}\r\n\r\nfunction decodeJson(record: NdefRecord) {\r\n if (record.tnf !== Ndef.TNF_MIME_MEDIA) return null;\r\n\r\n // Convert type to string\r\n const typeStr =\r\n typeof record.type === \"string\" ? record.type : toAscii(toU8(record.type));\r\n\r\n if (typeStr !== \"application/json\") return null;\r\n\r\n const payloadU8 = toU8(record.payload);\r\n const jsonText = new TextDecoder().decode(payloadU8);\r\n\r\n try {\r\n return JSON.parse(jsonText);\r\n } catch (err) {\r\n console.warn(\"Invalid JSON in NDEF:\", err);\r\n return null;\r\n }\r\n}\r\n\r\nconst encodeText = (text: string, lang = \"en\") => Ndef.textRecord(text, lang);\r\n\r\nconst encodeUri = (uri: string) => Ndef.uriRecord(uri);\r\n\r\nfunction encodeJson(obj: any) {\r\n const json = JSON.stringify(obj);\r\n const payload = new TextEncoder().encode(json); // Uint8Array\r\n const typeArray = Array.from(new TextEncoder().encode(\"application/json\"));\r\n\r\n return {\r\n tnf: Ndef.TNF_MIME_MEDIA,\r\n type: typeArray, // MUST be a number[] of ASCII bytes\r\n id: [],\r\n payload,\r\n };\r\n}\r\n\r\nfunction encodeMime(mimeType: string, data: Uint8Array) {\r\n const typeBytes = Array.from(new TextEncoder().encode(mimeType));\r\n\r\n return {\r\n tnf: Ndef.TNF_MIME_MEDIA,\r\n type: typeBytes,\r\n id: [],\r\n payload: data,\r\n };\r\n}\r\n\r\n// Android only\r\nfunction willFit(tag: TagEvent, records: NdefRecord[]) {\r\n if (tag.maxSize === undefined) return null;\r\n\r\n const totalSize = Ndef.encodeMessage(records).length;\r\n return totalSize <= tag.maxSize;\r\n}\r\n\r\n// Android only\r\nfunction spaceLeft(tag: TagEvent, records: NdefRecord[]) {\r\n if (tag.maxSize === undefined) return null;\r\n\r\n const totalSize = Ndef.encodeMessage(records).length;\r\n return tag.maxSize - totalSize;\r\n}\r\n\r\nexport const NfcUtils = {\r\n Ndef: {\r\n decodeRecord,\r\n decodeJson,\r\n encodeText,\r\n encodeUri,\r\n encodeJson,\r\n encodeMime,\r\n willFit,\r\n spaceLeft,\r\n },\r\n};\r\n","import { useEffect, useState } from \"react\";\r\nimport { nfcService, NfcState } from \"./NfcService\";\r\n\r\nexport function useNfcState() {\r\n const [state, setState] = useState<NfcState>(nfcService.getState());\r\n\r\n useEffect(() => nfcService.subscribe(setState), []);\r\n\r\n return {\r\n state,\r\n lastTag: nfcService.getLastTag(),\r\n };\r\n}\r\n"],"mappings":"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","names":["Ndef","tryDecodeAsText"]}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@spencerls/react-native-nfc",
3
+ "version": "1.0.0",
4
+ "description": "A lightweight NFC manager for React Native projects using react-native-nfc-manager.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsup",
9
+ "clean": "rm -rf dist"
10
+ },
11
+ "keywords": [
12
+ "nfc",
13
+ "react-native",
14
+ "expo",
15
+ "nfc-manager",
16
+ "capacitor"
17
+ ],
18
+ "author": "Spencer Smith",
19
+ "license": "MIT",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/Spencer1O1/react-native-nfc.git"
23
+ },
24
+ "peerDependencies": {
25
+ "react": ">=18",
26
+ "react-native": ">=0.74",
27
+ "react-native-nfc-manager": ">=3.17.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/react": "^19.2.3",
31
+ "@types/react-native": "^0.72.8",
32
+ "tsup": "^8.0.0",
33
+ "typescript": "^5.3.0"
34
+ }
35
+ }